Spaces:
Paused
Paused
| import { Moon, Sun, Monitor } from "lucide-react"; | |
| import { useTheme } from "./theme-provider"; | |
| import { Button } from "./ui/button"; | |
| import { useState, useRef, useEffect } from "react"; | |
| export function ThemeToggle() { | |
| const { theme, setTheme } = useTheme(); | |
| const [isOpen, setIsOpen] = useState(false); | |
| const dropdownRef = useRef<HTMLDivElement>(null); | |
| useEffect(() => { | |
| function handleClickOutside(event: MouseEvent) { | |
| if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) { | |
| setIsOpen(false); | |
| } | |
| } | |
| document.addEventListener("mousedown", handleClickOutside); | |
| return () => document.removeEventListener("mousedown", handleClickOutside); | |
| }, []); | |
| const getIcon = () => { | |
| if (theme === "light") return <Sun className="h-5 w-5" />; | |
| if (theme === "dark") return <Moon className="h-5 w-5" />; | |
| return <Monitor className="h-5 w-5" />; | |
| }; | |
| const themes = [ | |
| { value: "light", label: "Light", icon: <Sun className="h-4 w-4" /> }, | |
| { value: "dark", label: "Dark", icon: <Moon className="h-4 w-4" /> }, | |
| { value: "system", label: "System", icon: <Monitor className="h-4 w-4" /> }, | |
| ]; | |
| return ( | |
| <div className="relative" ref={dropdownRef}> | |
| <Button | |
| variant="ghost" | |
| size="icon" | |
| onClick={() => setIsOpen(!isOpen)} | |
| aria-label="Toggle theme" | |
| > | |
| {getIcon()} | |
| </Button> | |
| {isOpen && ( | |
| <div className="absolute right-0 mt-2 w-40 rounded-md shadow-lg bg-popover border border-border z-50"> | |
| <div className="py-1"> | |
| {themes.map((themeOption) => ( | |
| <button | |
| key={themeOption.value} | |
| onClick={() => { | |
| setTheme(themeOption.value as "light" | "dark" | "system"); | |
| setIsOpen(false); | |
| }} | |
| className={`w-full flex items-center gap-2 px-4 py-2 text-sm hover:bg-accent hover:text-accent-foreground transition-colors ${ | |
| theme === themeOption.value ? "bg-accent" : "" | |
| }`} | |
| > | |
| {themeOption.icon} | |
| <span>{themeOption.label}</span> | |
| </button> | |
| ))} | |
| </div> | |
| </div> | |
| )} | |
| </div> | |
| ); | |
| } | |