"use client"; import { useEffect, useState } from "react"; export type Theme = "light" | "dark" | "system"; export default function ThemeToggle() { const [theme, setTheme] = useState(null); useEffect(() => { try { const stored = localStorage.getItem("theme") as Theme | null; if (stored === "light" || stored === "dark" || stored === "system") { setTheme(stored); } else { setTheme("system"); } } catch (e) { setTheme("system"); } }, []); const applyTheme = (targetTheme: Theme) => { const isDark = targetTheme === "dark" || (targetTheme === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches); if (isDark) { document.documentElement.classList.add("dark"); document.documentElement.setAttribute("data-theme", "dark"); } else { document.documentElement.classList.remove("dark"); document.documentElement.setAttribute("data-theme", "light"); } }; const toggleTheme = () => { if (theme === null) return; const themeCycle: Record = { light: "dark", dark: "system", system: "light", }; const nextTheme = themeCycle[theme]; setTheme(nextTheme); try { localStorage.setItem("theme", nextTheme); } catch (e) {} applyTheme(nextTheme); window.dispatchEvent(new Event("theme-change")); }; useEffect(() => { const handleSync = () => { try { const stored = localStorage.getItem("theme") as Theme | null; if (stored === "light" || stored === "dark" || stored === "system") { setTheme(stored); } else { setTheme("system"); } } catch (e) { setTheme("system"); } }; window.addEventListener("theme-change", handleSync); return () => window.removeEventListener("theme-change", handleSync); }, []); useEffect(() => { const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); const handleSystemThemeChange = (e: MediaQueryListEvent) => { try { const stored = localStorage.getItem("theme"); if (!stored || stored === "system") { if (e.matches) { document.documentElement.classList.add("dark"); document.documentElement.setAttribute("data-theme", "dark"); } else { document.documentElement.classList.remove("dark"); document.documentElement.setAttribute("data-theme", "light"); } window.dispatchEvent(new Event("theme-change")); } } catch (err) {} }; if (mediaQuery.addEventListener) { mediaQuery.addEventListener("change", handleSystemThemeChange); } else { mediaQuery.addListener(handleSystemThemeChange); } return () => { if (mediaQuery.removeEventListener) { mediaQuery.removeEventListener("change", handleSystemThemeChange); } else { mediaQuery.removeListener(handleSystemThemeChange); } }; }, []); if (theme === null) { return ( ); } const getLabel = () => { if (theme === "dark") return "DARK"; if (theme === "system") return "AUTO"; return "LIGHT"; }; const getTitle = () => { if (theme === "light") return "Switch to Dark Mode"; if (theme === "dark") return "Switch to System Theme"; return "Switch to Light Mode"; }; const getAriaLabel = () => { if (theme === "light") return "다크 모드로 전환"; if (theme === "dark") return "시스템 설정 모드로 전환"; return "라이트 모드로 전환"; }; return ( ); }