Spaces:
Sleeping
Sleeping
| 'use client'; | |
| import { useState, useEffect } from 'react'; | |
| import { Moon, Sun } from 'lucide-react'; | |
| import { Button } from '@/components/ui/button'; | |
| export function ThemeToggle() { | |
| const [theme, setTheme] = useState<string | undefined>(undefined); | |
| useEffect(() => { | |
| // Set initial theme based on localStorage or system preference | |
| const storedTheme = localStorage.getItem('theme'); | |
| const systemPrefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches; | |
| if (storedTheme) { | |
| setTheme(storedTheme); | |
| } else { | |
| setTheme(systemPrefersDark ? 'dark' : 'light'); | |
| } | |
| }, []); | |
| useEffect(() => { | |
| // Apply theme to document and save to localStorage | |
| if (theme === 'dark') { | |
| document.documentElement.classList.add('dark'); | |
| localStorage.setItem('theme', 'dark'); | |
| } else if (theme === 'light') { | |
| document.documentElement.classList.remove('dark'); | |
| localStorage.setItem('theme', 'light'); | |
| } | |
| }, [theme]); | |
| const toggleTheme = () => { | |
| setTheme(prevTheme => (prevTheme === 'light' ? 'dark' : 'light')); | |
| }; | |
| if (theme === undefined) { | |
| // Return a placeholder to avoid rendering mismatch during initial load | |
| // and to reserve space, matching the button's size. | |
| return <Button variant="ghost" size="icon" disabled className="h-9 w-9" />; | |
| } | |
| return ( | |
| <Button variant="ghost" size="icon" onClick={toggleTheme} aria-label="Toggle theme" className="h-9 w-9"> | |
| {theme === 'light' ? <Moon className="h-5 w-5" /> : <Sun className="h-5 w-5" />} | |
| </Button> | |
| ); | |
| } | |