42 lines
1,003 B
TypeScript
42 lines
1,003 B
TypeScript
'use client';
|
|
|
|
import { useEffect, useState } from 'react';
|
|
|
|
type Theme = 'light' | 'dark';
|
|
|
|
function apply(theme: Theme) {
|
|
document.documentElement.classList.toggle('dark', theme === 'dark');
|
|
try {
|
|
localStorage.setItem('theme', theme);
|
|
} catch {
|
|
/* ignore */
|
|
}
|
|
}
|
|
|
|
export function ThemeToggle() {
|
|
const [theme, setTheme] = useState<Theme>('light');
|
|
|
|
useEffect(() => {
|
|
const current = document.documentElement.classList.contains('dark') ? 'dark' : 'light';
|
|
setTheme(current);
|
|
}, []);
|
|
|
|
function toggle() {
|
|
const next: Theme = theme === 'dark' ? 'light' : 'dark';
|
|
setTheme(next);
|
|
apply(next);
|
|
}
|
|
|
|
return (
|
|
<button
|
|
type="button"
|
|
className="btn-secondary"
|
|
onClick={toggle}
|
|
aria-label={theme === 'dark' ? 'Switch to light theme' : 'Switch to dark theme'}
|
|
>
|
|
<span aria-hidden>{theme === 'dark' ? '☾' : '☀'}</span>
|
|
<span className="hidden sm:inline">{theme === 'dark' ? 'Dark' : 'Light'}</span>
|
|
</button>
|
|
);
|
|
}
|