'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 (
);
}