Files
time_to_leave/apps/web/src/hooks/useTheme.ts
T

46 lines
1.3 KiB
TypeScript

"use client";
import { useState, useCallback, useEffect, useRef } from "react";
const THEME_KEY = "ttl_theme";
function getServerTheme(): "dark" | "light" {
return "light";
}
function getClientTheme(): "dark" | "light" {
if (typeof window === "undefined") return getServerTheme();
const stored = localStorage.getItem(THEME_KEY);
if (stored) return stored as "dark" | "light";
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
}
/**
* Theme toggle hook. Reads from `prefers-color-scheme` on first load, then
* respects the user's explicit choice persisted in localStorage.
*
* Returns `mounted` flag so child components can avoid hydration mismatch.
*/
export function useTheme() {
const [dark, setDark] = useState(() => getClientTheme() === "dark");
const [mounted] = useState(() => typeof window !== "undefined");
const initialized = useRef(false);
useEffect(() => {
if (!initialized.current) {
initialized.current = true;
document.documentElement.classList.toggle("dark", dark);
}
}, [dark]);
const toggle = useCallback(() => {
setDark((prev) => {
const next = !prev;
localStorage.setItem(THEME_KEY, next ? "dark" : "light");
return next;
});
}, []);
return { dark, toggle, mounted };
}