feat(theme): expand color settings to 8-token CI palette + alt button

This commit is contained in:
Luca
2026-05-05 16:04:43 +02:00
parent ee7de6f6a1
commit 114aab5777
11 changed files with 612 additions and 150 deletions
+110 -19
View File
@@ -19,29 +19,60 @@
@layer base {
:root {
/* Theme CSS Variables */
/*
* Theme CSS Variables — 8-token CI palette.
* Token names are kept aligned with frontend/src/types/theme.types.ts
* (ThemeConfig). ThemeContext.applyTheme() writes these from the active
* theme/branding settings; values here are the "Classic Grid" defaults.
*/
--color-background: #fafafa; /* page base */
--color-surface: #ffffff; /* cards, nav, alternating sections */
--color-elevated: #f5f5f5; /* raised panels */
--color-surface-border: #e5e5e5; /* dividers, borders (a.k.a. border token) */
--color-text: #171717; /* primary text */
--color-muted-text: #737373; /* secondary text */
--color-accent: #22c55e; /* links, focus rings, hover */
--color-accent-dark: #5C8762; /* primary CTA fill */
/* Legacy aliases — kept for any consumer that still reads --color-primary.
* Both resolve to the accent-dark token (the previous "primary" CTA color). */
--color-primary: #5C8762;
--color-primary-light: #7aa583;
--color-primary-dark: #4a6f4f;
--color-accent: #22c55e;
--color-background: #fafafa;
--color-text: #171717;
--font-family: 'Inter', 'Noto Sans', system-ui, -apple-system, sans-serif;
--heading-font-family: 'Inter', 'Noto Sans', system-ui, -apple-system, sans-serif;
--border-radius: 0.5rem;
--font-size-base: 16px;
--shadow-default: 0 4px 6px rgba(0,0,0,0.1);
/* Surface colors (for cards, inputs, etc.) */
--color-surface: #ffffff;
--color-surface-border: #e5e5e5;
--color-muted-text: #737373;
/* Tailwind RGB values for primary color */
/* Tailwind RGB values for primary color (legacy, used by primary-* utilities) */
--tw-color-primary: 92 135 98;
--radius: 0.5rem;
}
/*
* Admin dark mode unification.
* AdminDarkModeContext toggles `.dark` on <html> without going through
* applyTheme(). Previously this only flipped the components that had
* explicit `.dark .x` overrides; everything else (cards/inputs/buttons
* that now read CSS variables) stayed light. We re-declare the 8-token
* defaults under `.dark` so the same variables resolve to a dark palette
* whenever the class is present. Gallery applyTheme() still wins because
* it writes inline `--color-*` styles on the html element, which beat the
* .dark stylesheet rule in the cascade.
*/
.dark {
--color-background: #0a0a0a;
--color-surface: #171717;
--color-elevated: #1f1f1f;
--color-surface-border: #262626;
--color-text: #f5f5f5;
--color-muted-text: #a3a3a3;
--color-accent: #22c55e;
--color-accent-dark: #5C8762;
}
* {
font-family: var(--font-family);
}
@@ -100,33 +131,57 @@
}
@layer components {
/* Button styles */
/*
* Button styles.
*
* Migration note: .btn-primary / .btn-secondary / .btn-outline keep the
* exact same visual contract they had before the 8-token migration —
* --color-primary still drives .btn-primary's background, white text on
* primary, and the legacy --color-primary-dark hover. This guarantees
* existing themes render identically after upgrade. The new .btn-alt
* implements the LBM "Alternative" button (outlined, inverts on hover)
* and the focus ring switches to var(--color-accent) so it reads on
* every surface (light, dark, branded).
*/
.btn {
@apply inline-flex items-center justify-center font-medium transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50;
border-radius: var(--border-radius);
--tw-ring-color: var(--color-accent);
--tw-ring-offset-color: var(--color-background);
}
.btn-primary {
background-color: var(--color-primary);
color: white;
@apply hover:opacity-90 focus-visible:ring-2;
@apply hover:opacity-90;
}
.btn-primary:hover {
background-color: var(--color-primary-dark);
}
.btn-alt {
background-color: transparent;
color: var(--color-text);
border: 2px solid var(--color-text);
}
.btn-alt:hover {
background-color: var(--color-text);
color: var(--color-background);
}
.btn-secondary {
background-color: var(--color-surface-border);
color: var(--color-text);
@apply hover:opacity-80 focus-visible:ring-neutral-400;
@apply hover:opacity-80;
}
.btn-outline {
border-color: var(--color-surface-border);
background-color: transparent;
color: var(--color-muted-text);
@apply border hover:opacity-80 focus-visible:ring-neutral-400;
@apply border hover:opacity-80;
}
.btn-sm {
@@ -141,7 +196,13 @@
@apply h-11 px-8 text-lg;
}
/* Input styles - Admin inputs use explicit Tailwind colors */
/*
* Input styles - Admin inputs keep explicit Tailwind colors so the visual
* contract is byte-for-byte identical to pre-migration (border-neutral-300
* vs the lighter neutral-200/surface-border). Dark mode is handled by the
* .dark .input override below. Gallery inputs use .input-themed which
* binds to the 8-token palette via CSS variables.
*/
.input {
@apply flex h-10 w-full rounded-lg border px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-600 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50;
@apply bg-white border-neutral-300 text-neutral-900;
@@ -163,7 +224,10 @@
color: var(--color-muted-text);
}
/* Card styles - Admin cards use explicit Tailwind colors, gallery cards use CSS variables */
/* Card styles - Admin cards keep their explicit Tailwind colors for
* migration safety (visible border lightness change otherwise); the
* .dark .card override below handles admin dark mode. Gallery uses
* .card-themed which binds to the 8-token palette. */
.card {
@apply rounded-xl border bg-white border-neutral-200;
box-shadow: var(--shadow-default);
@@ -191,11 +255,33 @@
@apply mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl w-full;
}
/* Surface utility classes for gallery dark mode */
/*
* Theme-token utility classes — exposed so any component (admin or gallery)
* can opt into the 8-token palette without an inline style. The Tailwind
* config also exposes these as full color aliases (bg-surface, text-theme,
* etc.) but these single-purpose classes are kept for back-compat with
* existing call sites.
*/
.bg-background {
background-color: var(--color-background);
}
.bg-surface {
background-color: var(--color-surface);
}
.bg-elevated {
background-color: var(--color-elevated);
}
.bg-accent {
background-color: var(--color-accent);
}
.bg-accent-dark {
background-color: var(--color-accent-dark);
}
.border-surface {
border-color: var(--color-surface-border);
}
@@ -208,6 +294,10 @@
color: var(--color-muted-text);
}
.text-accent {
color: var(--color-accent);
}
/* Image loading skeleton */
.skeleton {
@apply animate-pulse rounded-lg bg-neutral-200;
@@ -281,7 +371,8 @@
@apply bg-red-900/40 text-red-300;
}
/* Secondary and outline buttons for admin dark mode */
/* Secondary and outline buttons for admin dark mode — restore explicit
* neutral overrides so existing admin pages render exactly as before. */
.dark .btn-secondary {
@apply bg-neutral-700 border-neutral-600 text-neutral-100;
}