56 lines
1.4 KiB
TypeScript
56 lines
1.4 KiB
TypeScript
import { useComputed, useSignal, useSignalEffect } from '@preact/signals'
|
|
import { IS_BROWSER } from '$fresh/runtime.ts'
|
|
|
|
export default function ThemePicker() {
|
|
const colorSchemeQuery = '(prefers-color-scheme: dark)'
|
|
|
|
const colorSchemeDark = useSignal(
|
|
IS_BROWSER ? matchMedia('(prefers-color-scheme: dark)').matches : false,
|
|
)
|
|
|
|
if (IS_BROWSER) {
|
|
matchMedia(colorSchemeQuery).addEventListener(
|
|
'change',
|
|
(event) => colorSchemeDark.value = event.matches,
|
|
)
|
|
}
|
|
|
|
type Theme = 'system' | 'light' | 'dark'
|
|
const theme = useSignal<Theme>(
|
|
localStorage.getItem('$cohabit.theme') as Theme ?? 'system',
|
|
)
|
|
const themeIcon = useComputed(() => {
|
|
if (theme.value === 'light') {
|
|
return <i class='ri-sun-line'></i>
|
|
}
|
|
if (theme.value === 'dark') {
|
|
return <i class='ri-moon-line'></i>
|
|
}
|
|
//If not forced use system
|
|
if (colorSchemeDark.value) {
|
|
return <i class='ri-moon-line'></i>
|
|
}
|
|
return <i class='ri-sun-line'></i>
|
|
})
|
|
|
|
useSignalEffect(() => {
|
|
localStorage.setItem('$cohabit.theme', theme.value)
|
|
document.body.setAttribute('data-theme', theme.value)
|
|
})
|
|
|
|
return (
|
|
<label class='islands__theme_picker'>
|
|
<span>{themeIcon}</span>
|
|
<select
|
|
value={theme}
|
|
onChange={(event) =>
|
|
theme.value = (event.target as HTMLSelectElement).value as Theme}
|
|
>
|
|
<option value='system'>Système</option>
|
|
<option value='light'>Light</option>
|
|
<option value='dark'>Dark</option>
|
|
</select>
|
|
</label>
|
|
)
|
|
}
|