"use client"; import { Moon, Monitor, Sun } from "lucide-react"; import { useEffect, useState } from "react"; import { cn } from "@/lib/utils"; type ThemeMode = "light" | "dark" | "system"; const storageKey = "teatea-theme"; const themeOptions: Array<{ mode: ThemeMode; label: string; icon: React.ComponentType<{ className?: string; "aria-hidden"?: boolean }>; }> = [ { mode: "light", label: "浅色主题", icon: Sun }, { mode: "dark", label: "深色主题", icon: Moon }, { mode: "system", label: "跟随系统", icon: Monitor }, ]; function getStoredTheme(): ThemeMode { if (typeof window === "undefined") { return "system"; } const storedTheme = window.localStorage.getItem(storageKey); return storedTheme === "light" || storedTheme === "dark" || storedTheme === "system" ? storedTheme : "system"; } function applyTheme(mode: ThemeMode): void { const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches; document.documentElement.classList.toggle("dark", mode === "dark" || (mode === "system" && prefersDark)); document.documentElement.style.colorScheme = mode === "dark" || (mode === "system" && prefersDark) ? "dark" : "light"; } export function ThemeToggle(): React.ReactElement { const [theme, setTheme] = useState("system"); useEffect(() => { const storedTheme = getStoredTheme(); setTheme(storedTheme); applyTheme(storedTheme); const media = window.matchMedia("(prefers-color-scheme: dark)"); const handleChange = (): void => { if (getStoredTheme() === "system") { applyTheme("system"); } }; media.addEventListener("change", handleChange); return () => media.removeEventListener("change", handleChange); }, []); function handleThemeChange(nextTheme: ThemeMode): void { window.localStorage.setItem(storageKey, nextTheme); setTheme(nextTheme); applyTheme(nextTheme); } return (
{themeOptions.map((option) => { const Icon = option.icon; const isSelected = theme === option.mode; return ( ); })}
); }