feat: govern effective appearance defaults

This commit is contained in:
2026-08-20 07:03:28 +02:00
parent 6643c8fc1e
commit 8f642bd618
13 changed files with 429 additions and 61 deletions
@@ -0,0 +1,66 @@
import type { UserUiPalette, UserUiTheme } from "../types";
export const APPEARANCE_PALETTE_OPTIONS: ReadonlyArray<{ value: UserUiPalette; label: string }> = [
{ value: "default", label: "i18n:govoplan-core.palette_default" },
{ value: "civic_blue", label: "i18n:govoplan-core.palette_civic_blue" },
{ value: "forest", label: "i18n:govoplan-core.palette_forest" },
{ value: "plum", label: "i18n:govoplan-core.palette_plum" }
];
export function AppearancePaletteSelect({
value,
onChange,
allowInherit = false,
inheritLabel = "i18n:govoplan-core.inherit_governed_palette",
disabled = false
}: {
value: UserUiPalette | null;
onChange: (value: UserUiPalette | null) => void;
allowInherit?: boolean;
inheritLabel?: string;
disabled?: boolean;
}) {
return (
<select
value={value ?? (allowInherit ? "inherit" : "default")}
disabled={disabled}
onChange={(event) => onChange(event.target.value === "inherit" ? null : event.target.value as UserUiPalette)}
>
{allowInherit && <option value="inherit">{inheritLabel}</option>}
{APPEARANCE_PALETTE_OPTIONS.map((item) => (
<option key={item.value} value={item.value}>{item.label}</option>
))}
</select>
);
}
export function AppearancePalettePreview({
theme = "system",
palette
}: {
theme?: UserUiTheme;
palette: UserUiPalette;
}) {
const variants: UserUiTheme[] = theme === "system" ? ["light", "dark"] : [theme];
return (
<div className="theme-preview-list" aria-label="i18n:govoplan-core.theme.a797e309">
{variants.map((variant) => (
<div key={variant} className="theme-preview" data-preview-theme={variant} data-preview-palette={palette}>
<div className="theme-preview-header">
<span>{variant === "light" ? "i18n:govoplan-core.light_theme.7878f1fa" : "i18n:govoplan-core.dark_theme.164a90d9"}</span>
<i />
</div>
<div className="theme-preview-body">
<strong>GovOPlaN</strong>
<span />
<span />
</div>
</div>
))}
</div>
);
}
export function appearancePaletteLabel(value: UserUiPalette): string {
return APPEARANCE_PALETTE_OPTIONS.find((item) => item.value === value)?.label ?? APPEARANCE_PALETTE_OPTIONS[0].label;
}