Pure `nix fmt` output from the commit before this one — no hand edits. 203 files: 52 md, 42 tsx, 32 js, 32 css, 21 ts, 13 html, 8 json, 3 mjs. Reproduce with `nix develop -c nix fmt` on the parent commit; the result should be byte-identical to this tree. None of the 13 `.prettierignore` entries appears here — verified by intersecting the changed-file list against the ignore file, with a control proving the intersection finds a match when one exists.
46 lines
1.9 KiB
TypeScript
46 lines
1.9 KiB
TypeScript
// Applies a stored theme override by setting `data-theme="light"|"dark"`
|
|
// on `<html>`, 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<ThemeOverride>(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]);
|
|
}
|