"use client"; /** * — a compact Auto / Light / Dark control for the date strip. * * Dark mode is scoped to the /docs routes (see globals.css `.docs-theme`), * so the toggle only renders while on a docs route — showing it site-wide * would be a control that appears to do nothing on the marketing pages. * * "auto" removes the attribute and follows prefers-color-scheme; "light" and * "dark" force the choice via `data-theme` on . The choice persists to * localStorage and is re-applied before paint by the inline script in the * locale layout, so there is no theme flash on reload. */ import { useEffect, useState } from "react"; import { usePathname } from "next/navigation"; type Mode = "auto" | "light" | "dark"; const ORDER: Mode[] = ["auto", "light", "dark"]; const KEY = "cw-theme"; function apply(mode: Mode) { const el = document.documentElement; if (mode === "auto") el.removeAttribute("data-theme"); else el.setAttribute("data-theme", mode); } export function ThemeToggle({ isZh = false }: { isZh?: boolean }) { const pathname = usePathname(); const [mode, setMode] = useState("auto"); const [mounted, setMounted] = useState(false); useEffect(() => { setMounted(true); const stored = (typeof localStorage !== "undefined" && localStorage.getItem(KEY)) as Mode | null; if (stored && ORDER.includes(stored)) setMode(stored); }, []); const onDocs = /^\/[a-z]{2}\/docs(\/|$)/.test(pathname) || pathname.includes("/docs"); if (!onDocs) return null; const cycle = () => { const next = ORDER[(ORDER.indexOf(mode) + 1) % ORDER.length]; setMode(next); try { localStorage.setItem(KEY, next); } catch { /* private mode / storage disabled — the choice just won't persist */ } apply(next); }; const labels: Record = isZh ? { auto: "自动", light: "浅色", dark: "深色" } : { auto: "auto", light: "light", dark: "dark" }; const glyph: Record = { auto: "◐", light: "☀", dark: "☾" }; return ( ); }