Files
emaui/user-management-config/fhc.theme.ts
2026-06-13 11:21:32 +03:00

224 lines
6.4 KiB
TypeScript

/**
* fhc.theme.ts — Federal Housing Corporation (FHC) look & feel preset.
*
* ┌─────────────────────────────────────────────────────────────────────────┐
* │ HOST-OWNED config. Lives in app-config/, NOT inside the user-management │
* │ module. At submodule-split time this whole folder moves to the host repo. │
* │ It is fully self-contained — no imports from the module. │
* └─────────────────────────────────────────────────────────────────────────┘
*
* WHAT IT GIVES YOU
* - The FHC Mantine color palettes: fhcBlue, fhcBrick, fhcGold, fhcGray
* - The FHC layout design tokens (brick-gradient sidebar, glassy header,
* page background, brand colors, sizes) under `theme.other.fhcLayout`
* (light) and `theme.other.fhcLayoutDark` (dark) — the classic shell reads
* these via useFhcLayout()
* - FHC typography (Plus Jakarta Sans), radii, shadows and component defaults
*
* HOW TO USE — in app-config/project.theme.ts:
*
* import { fhcMantineTheme } from "./fhc.theme";
*
* export const projectTheme: DesignConfig = {
* typography: { fontFamily: "Plus Jakarta Sans, sans-serif" },
* mantineTheme: fhcMantineTheme, // escape hatch — merges the FHC theme in
* };
*
* Load the font once in index.html:
* <link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800;900&display=swap" rel="stylesheet" />
*/
import type { MantineColorsTuple, MantineThemeOverride } from "@mantine/core";
/** Mantine 10-shade color scales used across the FHC UI. */
export const FHC_COLORS = {
fhcBlue: [
"#EEF4FC",
"#D9E8FA",
"#BCD5F5",
"#96BDEB",
"#6FA4E0",
"#4A90E2",
"#4b7fe5",
"#2C669D",
"#224F7A",
"#173654",
],
fhcBrick: [
"#F6ECE8",
"#EACFC4",
"#DBAD99",
"#C9876B",
"#B86B49",
"#A85735",
"#8C462B",
"#703622",
"#55281A",
"#3D1E14",
],
fhcGold: [
"#FFFBE6",
"#FFF3BF",
"#FEE98A",
"#FCDD57",
"#F9CF2F",
"#FFD700",
"#D9B700",
"#B39400",
"#8C7300",
"#665300",
],
fhcGray: [
"#F8FAFC",
"#F1F5F9",
"#E2E8F0",
"#CBD5E1",
"#94A3B8",
"#64748B",
"#475569",
"#334155",
"#1E293B",
"#0F172A",
],
} as const;
/**
* Layout design tokens — the brick-gradient sidebar, glassy header, page
* surfaces, brand colors and sizes. Mirrored under `theme.other.fhcLayout`.
*/
export const FHC_LAYOUT = {
sidebar: {
bg: "linear-gradient(180deg, #1A3A5C 0%, #0F2440 100%)",
headerBg: "rgba(26, 58, 92, 0.82)",
footerBg: "rgba(15, 36, 64, 0.62)",
border: "rgba(255,255,255,0.10)",
text: "rgba(255,255,255,0.76)",
mutedText: "rgba(255,255,255,0.42)",
childText: "rgba(255,255,255,0.68)",
activeText: "#FFFFFF",
iconBg: "rgba(255,255,255,0.06)",
iconActiveBg: "rgba(255,255,255,0.12)",
hoverBg: "rgba(255,255,255,0.08)",
activeBg: "rgba(255,255,255,0.15)",
activeBorder: "rgba(255,255,255,0.14)",
sectionLine: "rgba(255,255,255,0.10)",
rail: "linear-gradient(180deg, #4A90E2 0%, #1A3A5C 100%)",
},
header: {
bg: "rgba(255,255,255,0.92)",
border: "rgba(15, 23, 42, 0.08)",
searchBg: "#F9FAFB",
searchBorder: "#E5E7EB",
title: "#1F2937",
subtitle: "#6B7280",
},
page: {
bg: "#F8FAFC",
cardBg: "rgba(255,255,255,0.92)",
},
brand: {
brick: "#1A3A5C",
brickDark: "#0F2440",
blue: "#4A90E2",
blueDark: "#4b7fe5",
gold: "#4A90E2",
text: "#1F2937",
},
sizes: {
sidebarExpanded: 288,
sidebarCollapsed: 80,
headerHeight: 64,
},
} as const;
/**
* Dark-mode counterpart of FHC_LAYOUT. The brick-gradient sidebar, accent rail
* and sizes are intentionally kept (they already read well on dark), while the
* glassy white header, page background, card surfaces and dark text are flipped
* to dark equivalents.
*/
export const FHC_LAYOUT_DARK = {
...FHC_LAYOUT,
header: {
bg: "rgba(26, 27, 30, 0.92)",
border: "rgba(255,255,255,0.08)",
searchBg: "#25262B",
searchBorder: "#2C2E33",
title: "#F1F5F9",
subtitle: "#9CA3AF",
},
page: {
bg: "#141517",
cardBg: "rgba(26, 27, 30, 0.92)",
},
brand: {
...FHC_LAYOUT.brand,
text: "#F1F5F9",
},
} as const;
/**
* Full Mantine theme override carrying the FHC palettes, layout tokens,
* typography, radii, shadows and component defaults. Pass this as the
* `mantineTheme` escape hatch in project.theme.ts.
*
* Note: BOTH `fhcLayout` (light) and `fhcLayoutDark` (dark) are published under
* `other` — the module's useFhcLayout() reads the matching one per color scheme.
*/
export const fhcMantineTheme: MantineThemeOverride = {
fontFamily: "Plus Jakarta Sans, sans-serif",
headings: {
fontFamily: "Plus Jakarta Sans, sans-serif",
},
defaultRadius: "md",
radius: {
xs: "6px",
sm: "8px",
md: "10px",
lg: "14px",
xl: "18px",
},
shadows: {
xs: "0 1px 2px rgba(15, 23, 42, 0.04)",
sm: "0 2px 8px rgba(15, 23, 42, 0.06)",
md: "0 4px 20px rgba(15, 23, 42, 0.08)",
lg: "0 8px 30px rgba(15, 23, 42, 0.12)",
},
colors: {
fhcBlue: FHC_COLORS.fhcBlue as unknown as MantineColorsTuple,
fhcBrick: FHC_COLORS.fhcBrick as unknown as MantineColorsTuple,
fhcGold: FHC_COLORS.fhcGold as unknown as MantineColorsTuple,
fhcGray: FHC_COLORS.fhcGray as unknown as MantineColorsTuple,
},
other: {
fhcLayout: FHC_LAYOUT,
fhcLayoutDark: FHC_LAYOUT_DARK,
},
components: {
Paper: {
defaultProps: {
radius: "lg",
shadow: "sm",
},
},
NavLink: {
defaultProps: {
radius: "md",
},
},
},
};
/**
* Optional convenience: the bits of a DesignConfig that carry the FHC look.
* Spread this into your projectTheme if you also want FHC as the primary brand
* (this re-tints buttons/links to fhcBlue). Leave it out to keep your own brand
* color while still getting the fhc* palettes + layout tokens via `mantineTheme`.
*/
export const fhcDesignPreset = {
colors: { primary: "#4b7fe5" },
typography: { fontFamily: "Plus Jakarta Sans, sans-serif" },
shape: { radius: "10px" },
mantineTheme: fhcMantineTheme,
};