返回 JoyAI-Echo
useTheme.ts
1 import { useCallback, useEffect, useState } from "react";
2
3 type Theme = "light" | "dark";
4 const STORAGE_KEY = "nanobot-webui.theme";
5
6 function readStored(): Theme | null {
7 try {
8 const v = localStorage.getItem(STORAGE_KEY);
9 return v === "light" || v === "dark" ? v : null;
10 } catch {
11 return null;
12 }
13 }
14
15 function applyTheme(theme: Theme): void {
16 const root = document.documentElement;
17 if (theme === "dark") root.classList.add("dark");
18 else root.classList.remove("dark");
19 }
20
21 export function useTheme(): { theme: Theme; toggle: () => void; setTheme: (t: Theme) => void } {
22 const [theme, setThemeState] = useState<Theme>(() => {
23 const stored = readStored();
24 if (stored) return stored;
25 if (typeof window !== "undefined" && window.matchMedia) {
26 return window.matchMedia("(prefers-color-scheme: dark)").matches
27 ? "dark"
28 : "light";
29 }
30 return "light";
31 });
32
33 useEffect(() => {
34 applyTheme(theme);
35 try {
36 localStorage.setItem(STORAGE_KEY, theme);
37 } catch {
38 // ignore
39 }
40 }, [theme]);
41
42 const setTheme = useCallback((t: Theme) => setThemeState(t), []);
43 const toggle = useCallback(
44 () => setThemeState((t) => (t === "dark" ? "light" : "dark")),
45 [],
46 );
47 return { theme, toggle, setTheme };
48 }
49
49 lines TYPESCRIPT