51 lines
1.6 KiB
TypeScript
51 lines
1.6 KiB
TypeScript
'use client'
|
|
|
|
import { useTheme } from 'next-themes'
|
|
import { useEffect, useState } from 'react'
|
|
|
|
function SunIcon() {
|
|
return (
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden>
|
|
<circle cx="12" cy="12" r="5"/>
|
|
<line x1="12" y1="1" x2="12" y2="3"/>
|
|
<line x1="12" y1="21" x2="12" y2="23"/>
|
|
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/>
|
|
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/>
|
|
<line x1="1" y1="12" x2="3" y2="12"/>
|
|
<line x1="21" y1="12" x2="23" y2="12"/>
|
|
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/>
|
|
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/>
|
|
</svg>
|
|
)
|
|
}
|
|
|
|
function MoonIcon() {
|
|
return (
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden>
|
|
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
|
|
</svg>
|
|
)
|
|
}
|
|
|
|
export function ThemeToggle() {
|
|
const { theme, setTheme } = useTheme()
|
|
const [mounted, setMounted] = useState(false)
|
|
|
|
useEffect(() => { setMounted(true) }, [])
|
|
|
|
if (!mounted) {
|
|
// Prevents hydration mismatch -- renders a same-size placeholder
|
|
return <div className="w-9 h-9" />
|
|
}
|
|
|
|
return (
|
|
<button
|
|
onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
|
|
aria-label="Basculer le theme"
|
|
className="rounded-lg p-2 text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-slate-800 transition-colors"
|
|
>
|
|
{theme === 'dark' ? <SunIcon /> : <MoonIcon />}
|
|
</button>
|
|
)
|
|
}
|