50 lines
1.3 KiB
TypeScript
50 lines
1.3 KiB
TypeScript
import { useState, useEffect } from 'react'
|
|
|
|
import { mdiWeatherSunny, mdiWeatherNight } from '@mdi/js'
|
|
import Icon from '@mdi/react'
|
|
|
|
const LIGHT_THEME = 'light'
|
|
const DARK_THEME = 'dark'
|
|
|
|
const ThemeToggle = () => {
|
|
const [theme, setTheme] = useState(
|
|
(localStorage.getItem('theme') ??
|
|
window.matchMedia('(prefers-color-scheme: dark)').matches)
|
|
? DARK_THEME
|
|
: LIGHT_THEME
|
|
)
|
|
|
|
const handleToggle = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
if (e.target.checked) setTheme(DARK_THEME)
|
|
else setTheme(LIGHT_THEME)
|
|
}
|
|
|
|
useEffect(() => {
|
|
localStorage.setItem('theme', theme)
|
|
|
|
document
|
|
.querySelector('html')
|
|
.setAttribute('data-theme', localStorage.getItem('theme'))
|
|
|
|
document
|
|
.querySelector('html')
|
|
.setAttribute('data-uppy-theme', localStorage.getItem('theme'))
|
|
}, [theme])
|
|
|
|
return (
|
|
// eslint-disable-next-line jsx-a11y/label-has-associated-control
|
|
<label className="btn btn-ghost swap swap-rotate w-12">
|
|
<input
|
|
type="checkbox"
|
|
className="theme-controller"
|
|
checked={theme === DARK_THEME}
|
|
onChange={handleToggle}
|
|
/>
|
|
<Icon path={mdiWeatherSunny} className="swap-off size-8 text-warning" />
|
|
<Icon path={mdiWeatherNight} className="swap-on size-8 text-primary" />
|
|
</label>
|
|
)
|
|
}
|
|
|
|
export default ThemeToggle
|