91e22e1f89
Use fixed ::before and ::after pseudo-elements to render the background color in safe-area inset zones, preventing transparent gaps on notched mobile devices while maintaining body padding for content flow.
28 lines
959 B
TypeScript
28 lines
959 B
TypeScript
import { MoonIcon, SunIcon, MonitorIcon } from "lucide-react"
|
|
import { Button } from "@/components/ui/button"
|
|
import { useThemeStore, type ThemeMode } from "@/store/themeStore"
|
|
import { usePlatform } from "@/hooks/usePlatform"
|
|
|
|
const next: Record<ThemeMode, ThemeMode> = { system: "dark", dark: "light", light: "system" }
|
|
const icon: Record<ThemeMode, typeof SunIcon> = { system: MonitorIcon, dark: MoonIcon, light: SunIcon }
|
|
|
|
export default function ThemeToggle() {
|
|
const mode = useThemeStore((s) => s.mode)
|
|
const setMode = useThemeStore((s) => s.setMode)
|
|
const platform = usePlatform()
|
|
const hideTitle = platform === "mobile"
|
|
|
|
const Icon = icon[mode]
|
|
|
|
return (
|
|
<Button
|
|
variant="ghost"
|
|
size="icon-sm"
|
|
onClick={() => setMode(next[mode])}
|
|
{...(!hideTitle && { title: `主题:${mode === "system" ? "跟随系统" : mode === "dark" ? "深色" : "浅色"}` })}
|
|
>
|
|
<Icon className="size-4" />
|
|
</Button>
|
|
)
|
|
}
|