Barazo default frontend
barazo.forum
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}