fix(branding): selected-state accent colors, force-mode actually flips galleries, compact color picker layout

This commit is contained in:
Luca
2026-05-05 16:48:47 +02:00
parent 67d7d8d3fa
commit 5b410ed9f8
10 changed files with 275 additions and 121 deletions
+65
View File
@@ -1,5 +1,70 @@
import type { ThemeConfig, HeaderStyleType, HeroDividerStyle, GalleryLayoutType } from '../types/theme.types';
/**
* Surface defaults for the two color modes — the same values applyTheme()
* falls back to when a theme has no explicit surface/elevated/border/text
* tokens. Exposed here so the force-color-mode helper can swap them
* wholesale when an admin locks the instance to a mode that the active
* theme doesn't natively support.
*/
const DARK_SURFACE_DEFAULTS = {
backgroundColor: '#0f0f0f',
surfaceColor: '#1a1a1a',
elevatedColor: '#242424',
surfaceBorderColor: '#2e2e2e',
textColor: '#e5e5e5',
mutedTextColor: '#a3a3a3',
};
const LIGHT_SURFACE_DEFAULTS = {
backgroundColor: '#fafafa',
surfaceColor: '#ffffff',
elevatedColor: '#f5f5f5',
surfaceBorderColor: '#e5e5e5',
textColor: '#171717',
mutedTextColor: '#737373',
};
/**
* Apply an instance-wide force color mode lock to a theme config.
*
* If the theme already matches the locked mode (or no lock is set), only
* the colorMode flag is pinned. If the theme is locked to a mode it
* doesn't natively support (e.g. an admin set Force Dark but is opening
* a light gallery preset), the surface/text tokens are replaced with the
* matching mode's defaults — the user's accent/accentDark colours are
* preserved so brand identity survives the flip.
*
* Centralised here so GlobalThemeProvider, GalleryPage and GalleryView
* stay in sync (#397 follow-up: galleries did not visibly flip when
* Force Dark/Light was toggled because only colorMode was overridden,
* leaving the original light/dark surface colours in place).
*/
export function applyForceColorMode(
theme: ThemeConfig,
forced: 'dark' | 'light' | null | undefined
): ThemeConfig {
if (!forced) return theme;
const themeMode = theme.colorMode === 'auto'
? (typeof window !== 'undefined'
&& window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
: 'light')
: (theme.colorMode || 'light');
if (themeMode === forced) {
return { ...theme, colorMode: forced };
}
const surfaces = forced === 'dark' ? DARK_SURFACE_DEFAULTS : LIGHT_SURFACE_DEFAULTS;
return {
...theme,
...surfaces,
colorMode: forced,
};
}
/**
* Fills in any missing 8-token CI palette fields on legacy themes that were
* saved before the palette expanded from 4 → 8 explicit tokens.