fix(web): sync data-seed-user-color-scheme so system dark-mode follows OS
This commit is contained in:
parent
6260cc3479
commit
2e391ce244
2 changed files with 29 additions and 1 deletions
|
|
@ -12,7 +12,14 @@ const THEME_INIT_SCRIPT = `
|
||||||
try {
|
try {
|
||||||
var v = localStorage.getItem("mercury.theme");
|
var v = localStorage.getItem("mercury.theme");
|
||||||
var mode = v === "light" ? "light-only" : v === "dark" ? "dark-only" : "system";
|
var mode = v === "light" ? "light-only" : v === "dark" ? "dark-only" : "system";
|
||||||
document.documentElement.setAttribute("data-seed-color-mode", mode);
|
var el = document.documentElement;
|
||||||
|
el.setAttribute("data-seed-color-mode", mode);
|
||||||
|
// Seed's "system" mode resolves dark ONLY when data-seed-user-color-scheme
|
||||||
|
// reflects the OS preference — the CSS has no prefers-color-scheme media
|
||||||
|
// query of its own. Sync it from matchMedia so "system" actually follows
|
||||||
|
// the OS (light-only/dark-only ignore this attribute).
|
||||||
|
var dark = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches;
|
||||||
|
el.setAttribute("data-seed-user-color-scheme", dark ? "dark" : "light");
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
})();
|
})();
|
||||||
`;
|
`;
|
||||||
|
|
|
||||||
|
|
@ -39,9 +39,19 @@ function persistTheme(theme: MercuryTheme): void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Seed's "system" color-mode resolves dark only via data-seed-user-color-scheme
|
||||||
|
* (there's no prefers-color-scheme media query in the tokens), so we sync it
|
||||||
|
* from matchMedia. light-only/dark-only ignore this attribute. */
|
||||||
|
function syncUserScheme(): void {
|
||||||
|
if (typeof window === "undefined" || !window.matchMedia) return;
|
||||||
|
const dark = window.matchMedia("(prefers-color-scheme: dark)").matches;
|
||||||
|
document.documentElement.setAttribute("data-seed-user-color-scheme", dark ? "dark" : "light");
|
||||||
|
}
|
||||||
|
|
||||||
function applyTheme(theme: MercuryTheme): void {
|
function applyTheme(theme: MercuryTheme): void {
|
||||||
if (typeof document === "undefined") return;
|
if (typeof document === "undefined") return;
|
||||||
document.documentElement.setAttribute("data-seed-color-mode", toColorMode(theme));
|
document.documentElement.setAttribute("data-seed-color-mode", toColorMode(theme));
|
||||||
|
syncUserScheme();
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ThemeToggleProps {
|
export interface ThemeToggleProps {
|
||||||
|
|
@ -60,6 +70,17 @@ export function ThemeToggle({ labels = DEFAULT_LABELS }: ThemeToggleProps) {
|
||||||
// DOM before this ever mounts, so both agree from the first paint.
|
// DOM before this ever mounts, so both agree from the first paint.
|
||||||
const [theme, setTheme] = React.useState<MercuryTheme>(() => getStoredTheme());
|
const [theme, setTheme] = React.useState<MercuryTheme>(() => getStoredTheme());
|
||||||
|
|
||||||
|
// Keep data-seed-user-color-scheme synced to the OS so "system" mode follows
|
||||||
|
// live OS light/dark changes without a reload.
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (typeof window === "undefined" || !window.matchMedia) return;
|
||||||
|
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
||||||
|
syncUserScheme();
|
||||||
|
const onChange = () => syncUserScheme();
|
||||||
|
mq.addEventListener?.("change", onChange);
|
||||||
|
return () => mq.removeEventListener?.("change", onChange);
|
||||||
|
}, []);
|
||||||
|
|
||||||
function handleChange(next: string) {
|
function handleChange(next: string) {
|
||||||
const nextTheme = next as MercuryTheme;
|
const nextTheme = next as MercuryTheme;
|
||||||
setTheme(nextTheme);
|
setTheme(nextTheme);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue