mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 12:32:43 +00:00
Default to the dark theme for a fresh visitor
With no stored preference the app now resolves to dark instead of tracking the OS. An explicit choice still wins: light/dark persist as before, and "system" is now persisted verbatim rather than as a cleared key, so an explicit OS-tracking choice stays distinguishable from a never-chosen state and survives a reload. The first-paint bootstrap script mirrors the same resolution so a fresh visitor sees no flash to light.
This commit is contained in:
1 parent
74a245a29c
commit
f0b26141ed
2 files changed
+15
-7
No files matched your search
+1
-1
@@ -90,7 +90,7 @@ export const viewport: Viewport = {
|
||||
};
|
||||
|
||||
// Inline script to apply theme before first paint (prevents FOUC)
|
||||
const themeScript = `(function(){try{var t=localStorage.getItem("healthlog-theme");var c=(t==="light"||t==="dark")?t:(window.matchMedia("(prefers-color-scheme:dark)").matches?"dark":"light");document.documentElement.classList.add(c)}catch(e){document.documentElement.classList.add("dark")}})()`;
|
||||
const themeScript = `(function(){try{var t=localStorage.getItem("healthlog-theme");var c=(t==="light"||t==="dark")?t:(t==="system"?(window.matchMedia("(prefers-color-scheme:dark)").matches?"dark":"light"):"dark");document.documentElement.classList.add(c)}catch(e){document.documentElement.classList.add("dark")}})()`;
|
||||
|
||||
export default async function RootLayout({
|
||||
children,
|
||||
|
||||
@@ -49,16 +49,21 @@ function applyTheme(resolved: "dark" | "light") {
|
||||
|
||||
function ThemeProvider({ children }: { children: ReactNode }) {
|
||||
const [theme, setThemeState] = useState<Theme>(() => {
|
||||
if (typeof window === "undefined") return "system";
|
||||
if (typeof window === "undefined") return "dark";
|
||||
const saved = localStorage.getItem("healthlog-theme") as Theme | null;
|
||||
return saved === "light" || saved === "dark" ? saved : "system";
|
||||
// A stored "light"/"dark"/"system" choice wins. With no stored
|
||||
// preference the app defaults to dark rather than tracking the OS.
|
||||
if (saved === "light" || saved === "dark") return saved;
|
||||
if (saved === "system") return "system";
|
||||
return "dark";
|
||||
});
|
||||
|
||||
const [resolvedTheme, setResolvedTheme] = useState<"dark" | "light">(() => {
|
||||
if (typeof window === "undefined") return "dark";
|
||||
const saved = localStorage.getItem("healthlog-theme") as Theme | null;
|
||||
const t = saved === "light" || saved === "dark" ? saved : "system";
|
||||
return t === "system" ? getSystemTheme() : t;
|
||||
if (saved === "light" || saved === "dark") return saved;
|
||||
if (saved === "system") return getSystemTheme();
|
||||
return "dark";
|
||||
});
|
||||
|
||||
// Apply theme on mount (inline script handles FOUC, this ensures classes are in sync)
|
||||
@@ -82,13 +87,16 @@ function ThemeProvider({ children }: { children: ReactNode }) {
|
||||
|
||||
const setTheme = useCallback((next: Theme) => {
|
||||
setThemeState(next);
|
||||
// Persist every explicit choice, including "system" — the absence of a
|
||||
// stored value is reserved for a fresh visitor and now defaults to dark.
|
||||
// Storing "system" verbatim keeps an explicit OS-tracking choice
|
||||
// distinguishable from "never chose", so a reload honours it.
|
||||
localStorage.setItem("healthlog-theme", next);
|
||||
if (next === "system") {
|
||||
localStorage.removeItem("healthlog-theme");
|
||||
const resolved = getSystemTheme();
|
||||
setResolvedTheme(resolved);
|
||||
applyTheme(resolved);
|
||||
} else {
|
||||
localStorage.setItem("healthlog-theme", next);
|
||||
setResolvedTheme(next);
|
||||
applyTheme(next);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user