// Applies a stored theme override by setting `data-theme="light"|"dark"` // on ``, cleared when the override is "system" (letting the // `prefers-color-scheme` media query in `./colors.css` resume control). // No palette values live here — `colors.css`'s own // `:root[data-theme='light']` / `:root[data-theme='dark']` blocks are // what actually apply the colours. // // Callers own their own storage key (kept in their own small constant, // not derived here) so two pages never silently share one browser-local // setting by accident. `fallback` defaults to `'dark'`: `prefers-color- // scheme` has no real "unset" value the way `prefers-reduced-motion` // does, so a browser with no explicit dark-mode toggle reports `light` // — `'system'` as a default silently reads as light-by-default for most // first-time visitors (mara: "light mode seems to be default"). Still // fully overridable per caller if a page ever wants a different default. import { useEffect } from 'preact/hooks'; import { useLocalSetting } from './settings-storage.js'; export type ThemeOverride = 'system' | 'light' | 'dark'; export function useThemeOverride(key: string, fallback: ThemeOverride = 'dark') { return useLocalSetting(key, fallback); } // Mounted once, high in the tree — one mount point applies the override // regardless of what else is rendering, and `useLocalSetting`'s // same-tab subscription means `SettingsMenu` changing the value re-runs // this effect without either component needing to know about the other // directly. export function useApplyThemeOverride(key: string, fallback: ThemeOverride = 'dark'): void { const [override] = useThemeOverride(key, fallback); useEffect(() => { const root = document.documentElement; if (override === 'system') { delete root.dataset.theme; } else { root.dataset.theme = override; } }, [override]); }