feat(ui): apply approved A3 shared design foundation
This commit is contained in:
+36
-43
@@ -4,17 +4,16 @@ type PaletteLike = Record<string, any>;
|
||||
|
||||
export type ContentDensity = "comfortable" | "compact";
|
||||
|
||||
// Existing provisional brand hue. Dark mode uses a lighter tone for readable text;
|
||||
// this does not settle the Phase 3 brand/identity decision.
|
||||
const ACCENT = "#5B5BD6";
|
||||
const DARK_ACCENT = lighten(ACCENT, 0.45);
|
||||
// Approved A3/D1 application palette; document renderers own their own colours.
|
||||
const ACCENT = "#694394";
|
||||
const DARK_ACCENT = "#D7B6F7";
|
||||
|
||||
// The existing inverse sidebar remains inverse in both modes. These are MUI palette
|
||||
// roles so feature code does not have to invent colors for this surface.
|
||||
const navigation = {
|
||||
background: "#0F172A", border: "rgba(255,255,255,0.08)",
|
||||
text: "#E2E8F0", muted: "#94A3B8", hover: "rgba(255,255,255,0.06)",
|
||||
selected: "rgba(99,102,241,0.18)", selectedText: "#FFFFFF", selectedIcon: "#A5B4FC",
|
||||
background: "#302744", border: "#5E526E",
|
||||
text: "#EDF0F6", muted: "#CEC2DA", hover: "rgba(215,182,247,0.10)",
|
||||
selected: "rgba(215,182,247,0.18)", selectedText: "#FFFFFF", selectedIcon: DARK_ACCENT,
|
||||
};
|
||||
|
||||
function buildPrimary(main: string) {
|
||||
@@ -28,11 +27,11 @@ function buildPrimary(main: string) {
|
||||
}
|
||||
|
||||
function buildLightPalette(): PaletteLike {
|
||||
const textPrimary = "#1B1B1F";
|
||||
const textSecondary = "#46464F";
|
||||
const textPrimary = "#302744";
|
||||
const textSecondary = "#695E78";
|
||||
|
||||
const secondaryMain = "#5A5C78";
|
||||
const divider = "#EFEDF4";
|
||||
const divider = "#DDD6E7";
|
||||
const background = "#FFFFFF";
|
||||
|
||||
const disabled = "#777680";
|
||||
@@ -42,7 +41,7 @@ function buildLightPalette(): PaletteLike {
|
||||
primary: { ...buildPrimary(ACCENT), contrastText: "#FFFFFF" },
|
||||
contrastThreshold: 4.5,
|
||||
navigation,
|
||||
focus: { main: ACCENT, inverse: "#A5B4FC" },
|
||||
focus: { main: ACCENT, inverse: DARK_ACCENT },
|
||||
border: { subtle: divider, default: "#777680", strong: textSecondary },
|
||||
secondary: {
|
||||
lighter: "#E0E0FF",
|
||||
@@ -97,9 +96,7 @@ function buildLightPalette(): PaletteLike {
|
||||
disabled,
|
||||
},
|
||||
divider,
|
||||
// Soft grey app background with white paper gives the layered dashboard look
|
||||
// from the product mockups; cards/inputs (paper) sit above it.
|
||||
background: { default: "#F4F6FB", paper: background, elevated: background },
|
||||
background: { default: background, paper: background, elevated: "#F5F4F9" },
|
||||
action: {
|
||||
hover: alpha(ACCENT, 0.05),
|
||||
selected: alpha(ACCENT, 0.12),
|
||||
@@ -111,11 +108,11 @@ function buildLightPalette(): PaletteLike {
|
||||
}
|
||||
|
||||
function buildDarkPalette(): PaletteLike {
|
||||
const bg = "#0B0B0E";
|
||||
const paper = "#111116";
|
||||
const divider = alpha("#FFFFFF", 0.10);
|
||||
const textPrimary = "#EAEAF2";
|
||||
const textSecondary = alpha(textPrimary, 0.72);
|
||||
const bg = "#282334";
|
||||
const paper = "#282334";
|
||||
const divider = "#5E526E";
|
||||
const textPrimary = "#EDF0F6";
|
||||
const textSecondary = "#CEC2DA";
|
||||
|
||||
const secondaryMain = "#A4A6C8";
|
||||
const disabled = alpha(textPrimary, 0.5);
|
||||
@@ -125,8 +122,8 @@ function buildDarkPalette(): PaletteLike {
|
||||
primary: { ...buildPrimary(DARK_ACCENT), contrastText: paper },
|
||||
contrastThreshold: 4.5,
|
||||
navigation,
|
||||
focus: { main: DARK_ACCENT, inverse: "#A5B4FC" },
|
||||
border: { subtle: divider, default: "#777680", strong: "#B8B8C6" },
|
||||
focus: { main: DARK_ACCENT, inverse: DARK_ACCENT },
|
||||
border: { subtle: divider, default: "#9B8EAA", strong: "#CEC2DA" },
|
||||
secondary: {
|
||||
lighter: alpha(secondaryMain, 0.22),
|
||||
light: alpha(secondaryMain, 0.14),
|
||||
@@ -137,8 +134,9 @@ function buildDarkPalette(): PaletteLike {
|
||||
error: {
|
||||
lighter: alpha("#DE3730", 0.18),
|
||||
light: alpha("#DE3730", 0.12),
|
||||
main: "#FF5A52",
|
||||
dark: "#FF3B33",
|
||||
main: "#FF8A80",
|
||||
dark: "#FF7067",
|
||||
contrastText: paper,
|
||||
darker: "#FFC2BE",
|
||||
},
|
||||
warning: {
|
||||
@@ -180,7 +178,7 @@ function buildDarkPalette(): PaletteLike {
|
||||
disabled,
|
||||
},
|
||||
divider,
|
||||
background: { default: bg, paper, elevated: "#1C1C24" },
|
||||
background: { default: bg, paper, elevated: "#352D43" },
|
||||
action: {
|
||||
hover: alpha(DARK_ACCENT, 0.10),
|
||||
selected: alpha(DARK_ACCENT, 0.18),
|
||||
@@ -196,10 +194,7 @@ function buildCustomShadows(palette: any) {
|
||||
const primaryColor = palette.primary.main;
|
||||
return {
|
||||
button: `0px 0.711px 1.422px 0px ${alpha(shadowColor, 0.05)}`,
|
||||
// Mockup cards float on the grey page background with no visible border, just a soft,
|
||||
// fairly generous shadow (dashboard stat tiles, pipeline columns' cards, job-workspace
|
||||
// panels) -- the old 1px "section" shadow read as flat/bordered rather than elevated.
|
||||
section: `0px 1px 2px 0px ${alpha(shadowColor, 0.04)}, 0px 8px 24px -12px ${alpha(shadowColor, 0.12)}`,
|
||||
section: "none",
|
||||
tooltip: `0px 12px 16px -4px ${alpha(shadowColor, 0.08)}, 0px 4px 6px -2px ${alpha(shadowColor, 0.03)}`,
|
||||
focus: `0px 0px 0px 3px ${palette.focus.main}`,
|
||||
// Gradient CTA (mockup's "Tailor my CV" / "See the interface tour" buttons) gets its own
|
||||
@@ -218,10 +213,10 @@ export const GRADIENT_CTA = "linear-gradient(90deg, #6366F1 0%, #22D3EE 100%)";
|
||||
|
||||
function buildTypography() {
|
||||
return {
|
||||
fontFamily: "'Archivo', system-ui, -apple-system, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif",
|
||||
fontFamily: "'Trebuchet MS', system-ui, -apple-system, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif",
|
||||
letterSpacing: 0,
|
||||
// Opt-in application hierarchy; legacy page/marketing variants stay unchanged.
|
||||
pageTitle: { fontWeight: 700, fontSize: "1.5rem", lineHeight: 1.25, letterSpacing: "-0.01em", "@media (min-width: 768px)": { fontSize: "1.75rem", lineHeight: 34 / 28 } },
|
||||
pageTitle: { fontWeight: 700, fontSize: "1.75rem", lineHeight: 1.25, letterSpacing: "-0.01em", "@media (min-width: 768px)": { fontSize: "2rem", lineHeight: 1.25 } },
|
||||
sectionTitle: { fontWeight: 600, fontSize: "1.125rem", lineHeight: 24 / 18 },
|
||||
pageDescription: { fontWeight: 400, fontSize: "0.875rem", lineHeight: 20 / 14 },
|
||||
// Mockup headings (F:\Pictures\website\jobtracker\new) are bold/black-weight display
|
||||
@@ -237,12 +232,12 @@ function buildTypography() {
|
||||
h6: { fontWeight: 600, fontSize: 16, lineHeight: "20px" },
|
||||
subtitle1: { fontWeight: 600, fontSize: 14, lineHeight: "18px" },
|
||||
subtitle2: { fontWeight: 600, fontSize: 13, lineHeight: "17px" },
|
||||
body1: { fontWeight: 400, fontSize: 14, lineHeight: "18px" },
|
||||
body2: { fontWeight: 400, fontSize: 13, lineHeight: "17px" },
|
||||
body1: { fontWeight: 400, fontSize: 15, lineHeight: 1.55 },
|
||||
body2: { fontWeight: 400, fontSize: 14, lineHeight: 1.5 },
|
||||
caption: { fontWeight: 400, fontSize: 12, lineHeight: "16px", letterSpacing: 0 },
|
||||
overline: { fontWeight: 700, fontSize: 11, lineHeight: "14px", letterSpacing: "0.08em", textTransform: "uppercase" as const },
|
||||
caption1: { fontWeight: 500, fontSize: 12, lineHeight: "16px", letterSpacing: 0 },
|
||||
button: { textTransform: "capitalize" as const, fontWeight: 600 },
|
||||
button: { textTransform: "none" as const, fontWeight: 600 },
|
||||
};
|
||||
}
|
||||
|
||||
@@ -269,9 +264,7 @@ export const getTheme = (_mode: "light" | "dark") => {
|
||||
light: { palette: lightPalette, customShadows: buildCustomShadows(lightPalette) },
|
||||
dark: { palette: darkPalette, customShadows: buildCustomShadows(darkPalette) },
|
||||
},
|
||||
// Mockup radius reads noticeably rounder than the previous 10/8px defaults across cards,
|
||||
// stat tiles, kanban cards and buttons.
|
||||
shape: { borderRadius: 14 },
|
||||
shape: { borderRadius: 8 },
|
||||
typography: buildTypography() as any,
|
||||
} as any) as any;
|
||||
|
||||
@@ -376,9 +369,8 @@ export const getTheme = (_mode: "light" | "dark") => {
|
||||
defaultProps: { elevation: 0 },
|
||||
styleOverrides: {
|
||||
root: ({ theme }: any) => ({
|
||||
// No border -- mockup cards float on the grey page background purely via shadow.
|
||||
border: "none",
|
||||
borderRadius: 16,
|
||||
border: `1px solid ${theme.vars.palette.divider}`,
|
||||
borderRadius: 8,
|
||||
backgroundImage: "none",
|
||||
boxShadow: theme.vars.customShadows.section,
|
||||
}),
|
||||
@@ -395,8 +387,8 @@ export const getTheme = (_mode: "light" | "dark") => {
|
||||
styleOverrides: {
|
||||
paper: ({ theme }: any) => ({
|
||||
backgroundColor: theme.vars.palette.background.elevated,
|
||||
border: "none",
|
||||
borderRadius: 20,
|
||||
border: `1px solid ${theme.vars.palette.divider}`,
|
||||
borderRadius: 12,
|
||||
boxShadow: theme.vars.customShadows.tooltip,
|
||||
}),
|
||||
},
|
||||
@@ -438,7 +430,8 @@ export const getTheme = (_mode: "light" | "dark") => {
|
||||
defaultProps: { disableFocusRipple: true },
|
||||
styleOverrides: {
|
||||
root: ({ theme }: any) => ({
|
||||
borderRadius: 10,
|
||||
borderRadius: 7,
|
||||
minHeight: 44,
|
||||
boxShadow: theme.vars.customShadows.button,
|
||||
"&:hover": { boxShadow: theme.vars.customShadows.button },
|
||||
}),
|
||||
@@ -459,7 +452,7 @@ export const getTheme = (_mode: "light" | "dark") => {
|
||||
background: theme.vars.palette.background.default,
|
||||
paddingLeft: 10,
|
||||
paddingRight: 10,
|
||||
minHeight: 42,
|
||||
minHeight: 44,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
// Use the existing label notch: an outer outline crosses floating labels.
|
||||
|
||||
Reference in New Issue
Block a user