Barazo default frontend barazo.forum
at main 65 lines 1.9 kB view raw
1/** 2 * Theme Toggle Component 3 * Dark/Light mode toggle for the header 4 * Uses next-themes for persistence 5 */ 6'use client' 7 8import { useTheme } from 'next-themes' 9import { Moon, Sun } from '@phosphor-icons/react' 10import { useLayoutEffect, useState } from 'react' 11import { cn } from '@/lib/utils' 12 13interface ThemeToggleProps { 14 className?: string 15} 16 17export function ThemeToggle({ className }: ThemeToggleProps) { 18 const { theme, setTheme } = useTheme() 19 const [mounted, setMounted] = useState(false) 20 21 // Prevent hydration mismatch 22 /* eslint-disable react-hooks/set-state-in-effect -- Required for hydration mismatch prevention */ 23 useLayoutEffect(() => { 24 setMounted(true) 25 }, []) 26 /* eslint-enable react-hooks/set-state-in-effect */ 27 28 if (!mounted) { 29 return ( 30 <button 31 className={cn( 32 'inline-flex h-10 w-10 items-center justify-center rounded-md border border-border bg-card text-muted-foreground', 33 className 34 )} 35 disabled 36 aria-hidden="true" 37 > 38 <span className="h-5 w-5" /> 39 </button> 40 ) 41 } 42 43 const isDark = theme === 'dark' 44 45 return ( 46 <button 47 type="button" 48 onClick={() => setTheme(isDark ? 'light' : 'dark')} 49 className={cn( 50 'inline-flex h-10 w-10 items-center justify-center rounded-md border border-border bg-card text-muted-foreground transition-colors', 51 'hover:bg-card-hover hover:text-foreground', 52 'focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2', 53 className 54 )} 55 aria-label={isDark ? 'Switch to light mode' : 'Switch to dark mode'} 56 aria-pressed={isDark} 57 > 58 {isDark ? ( 59 <Sun className="h-5 w-5" weight="regular" aria-hidden="true" /> 60 ) : ( 61 <Moon className="h-5 w-5" weight="regular" aria-hidden="true" /> 62 )} 63 </button> 64 ) 65}