"use client"; import { useEffect, useState } from "react"; import { useI18n } from "@/lib/i18n"; import { haptic } from "@/lib/haptics"; import { cn } from "@/lib/utils"; import { MoonIcon, SunIcon } from "@/components/icons"; const STORAGE_KEY = "freezmo.theme"; const THEME_COLORS = { light: "#f4f7fd", dark: "#0e1424" } as const; /** * Keeps the first `theme-color` meta (the one the app owns) in step with the * in-app theme. The SSR metas follow the OS preference; this one always wins * because it is media-less and first in the head. */ export function syncThemeColor(theme: "light" | "dark") { try { let meta = document.querySelector('meta[name="theme-color"][data-app]'); if (!meta) { meta = document.createElement("meta"); meta.setAttribute("name", "theme-color"); meta.setAttribute("data-app", "1"); document.head.insertBefore(meta, document.head.firstChild); } meta.setAttribute("content", THEME_COLORS[theme]); } catch { /* private mode / odd embedded browsers */ } } export function applyTheme(next: "light" | "dark") { document.documentElement.classList.toggle("dark", next === "dark"); syncThemeColor(next); try { window.localStorage.setItem(STORAGE_KEY, next); } catch { /* private mode */ } } export function useTheme() { const [theme, setTheme] = useState<"light" | "dark">("light"); useEffect(() => { const stored = window.localStorage.getItem(STORAGE_KEY); const isDark = stored ? stored === "dark" : window.matchMedia("(prefers-color-scheme: dark)").matches; setTheme(isDark ? "dark" : "light"); syncThemeColor(isDark ? "dark" : "light"); }, []); const apply = (next: "light" | "dark") => { setTheme(next); applyTheme(next); }; return { theme, toggle: () => apply(theme === "dark" ? "light" : "dark") }; } export function ThemeToggle({ className }: { className?: string }) { const { theme, toggle } = useTheme(); const { t } = useI18n(); const dark = theme === "dark"; return ( ); }