Files
erika/components/theme-toggle.tsx
2026-08-10 13:19:09 +07:00

67 lines
1.7 KiB
TypeScript

"use client"
import * as React from "react"
import { Moon, Sun, Monitor } from "lucide-react"
import { useTheme } from "next-themes"
import { Button } from "@/components/ui/button"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
const THEME_ICONS = {
light: Sun,
dark: Moon,
system: Monitor,
} as const
type ThemeOption = keyof typeof THEME_ICONS
const THEME_OPTIONS: { value: ThemeOption; label: string }[] = [
{ value: "light", label: "Light theme" },
{ value: "dark", label: "Dark theme" },
{ value: "system", label: "System" },
]
export function ThemeToggle() {
const { setTheme, theme, resolvedTheme } = useTheme()
const [mounted, setMounted] = React.useState(false)
React.useEffect(() => {
const timeout = setTimeout(() => setMounted(true), 0)
return () => clearTimeout(timeout)
}, [])
// Once mounted, resolve "system" to its actual rendered theme for the icon
const activeIcon = !mounted
? Sun
: THEME_ICONS[theme === "system" ? (resolvedTheme as ThemeOption) : (theme as ThemeOption)] ?? Sun
const Icon = activeIcon
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="icon">
<Icon />
<span className="sr-only">Toggle theme</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
{THEME_OPTIONS.map(({ value, label }) => {
const OptionIcon = THEME_ICONS[value]
return (
<DropdownMenuItem key={value} onClick={() => setTheme(value)}>
<OptionIcon />
{label}
</DropdownMenuItem>
)
})}
</DropdownMenuContent>
</DropdownMenu>
)
}