File size: 1,665 Bytes
4a940a5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f3c6831
b4b60dc
 
 
 
 
 
f3c6831
b4b60dc
4a940a5
b4b60dc
4a940a5
 
 
 
 
 
 
 
 
 
f3c6831
4a940a5
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import { createContext } from "preact";
import { useContext, useState, useCallback } from "preact/hooks";
import type { ComponentChildren } from "preact";

interface ThemeContextValue {
  isDark: boolean;
  toggle: () => void;
}

const ThemeContext = createContext<ThemeContextValue>(null!);

function getInitialDark(): boolean {
  try {
    const saved = localStorage.getItem("codex-proxy-theme");
    if (saved === "dark") return true;
    if (saved === "light") return false;
  } catch {}
  return window.matchMedia("(prefers-color-scheme: dark)").matches;
}

// Sync dark class + color-scheme to <html> on initial load (before first render to avoid flash)
const _initialDark = getInitialDark();
if (_initialDark) {
  document.documentElement.classList.add("dark");
} else {
  document.documentElement.classList.remove("dark");
}
document.documentElement.style.colorScheme = _initialDark ? "dark" : "light";

export function ThemeProvider({ children }: { children: ComponentChildren }) {
  const [isDark, setIsDark] = useState(_initialDark);

  const toggle = useCallback(() => {
    setIsDark((prev) => {
      const next = !prev;
      localStorage.setItem("codex-proxy-theme", next ? "dark" : "light");
      if (next) {
        document.documentElement.classList.add("dark");
      } else {
        document.documentElement.classList.remove("dark");
      }
      document.documentElement.style.colorScheme = next ? "dark" : "light";
      return next;
    });
  }, []);

  return (
    <ThemeContext.Provider value={{ isDark, toggle }}>
      {children}
    </ThemeContext.Provider>
  );
}

export function useTheme() {
  return useContext(ThemeContext);
}