'use client'; import { Monitor, Moon, Sun } from 'lucide-react'; import { useEffect, useState } from 'react'; import { cn } from '@/lib/cn'; import { THEME_DARK, THEME_LIGHT } from '@/lib/site'; import { THEME_KEY } from '@/lib/prepaint'; export type ThemePref = 'light' | 'dark' | 'system'; const KEY = THEME_KEY; /** Inline in before paint — the string itself lives in `lib/prepaint.ts` (server-safe); import it from there in server code. */ export { THEME_SCRIPT } from '@/lib/prepaint'; function apply(pref: ThemePref) { const dark = window.matchMedia('(prefers-color-scheme: dark)').matches; const t = pref === 'system' ? (dark ? 'dark' : 'light') : pref; document.documentElement.setAttribute('data-theme', t); document.documentElement.style.colorScheme = t; const meta = document.querySelector('meta[name="theme-color"]'); if (meta) meta.setAttribute('content', t === 'dark' ? THEME_DARK : THEME_LIGHT); } export function useTheme(): [ThemePref, (p: ThemePref) => void] { const [pref, setPref] = useState('system'); useEffect(() => { const p = localStorage.getItem(KEY); if (p === 'light' || p === 'dark') setPref(p); // Error/not-found shells are client-rendered from scratch and lose the attribute set by THEME_SCRIPT: re-apply. if (!document.documentElement.getAttribute('data-theme')) apply(p === 'light' || p === 'dark' ? p : 'system'); const m = window.matchMedia('(prefers-color-scheme: dark)'); const onChange = () => { const cur = localStorage.getItem(KEY); if (cur !== 'light' && cur !== 'dark') apply('system'); }; m.addEventListener('change', onChange); return () => m.removeEventListener('change', onChange); }, []); const set = (p: ThemePref) => { setPref(p); if (p === 'system') localStorage.removeItem(KEY); else localStorage.setItem(KEY, p); apply(p); }; return [pref, set]; } /** Three-state toggle (system → light → dark). Touch target 44 px. */ export function ThemeToggle({ className }: { className?: string }) { const [pref, set] = useTheme(); const next: ThemePref = pref === 'system' ? 'light' : pref === 'light' ? 'dark' : 'system'; const Icon = pref === 'system' ? Monitor : pref === 'light' ? Sun : Moon; const label = pref === 'system' ? 'Theme: system' : pref === 'light' ? 'Theme: light' : 'Theme: dark'; return ( ); }