feat(ui): add theme picker

This commit is contained in:
Julien Oculi 2024-02-13 14:01:37 +01:00
parent 1431a21d5d
commit fd32f4c59d
4 changed files with 87 additions and 0 deletions

View file

@ -1,4 +1,5 @@
import { asset } from '$fresh/runtime.ts' import { asset } from '$fresh/runtime.ts'
import ThemePicker from '../islands/ThemePicker.tsx'
export function Header() { export function Header() {
return ( return (
@ -50,6 +51,7 @@ export function Header() {
</li> </li>
</nav> </nav>
<input type='search' name='' id='' placeholder='Rechercher' /> <input type='search' name='' id='' placeholder='Rechercher' />
<ThemePicker />
</div> </div>
</header> </header>
) )

29
islands/ThemePicker.css Normal file
View file

@ -0,0 +1,29 @@
.islands__theme_picker {
display: inline-flex;
align-items: center;
gap: var(--_gap-half);
height: fit-content;
margin: auto;
padding: var(--_gap-half);
&:has(select:focus-visible) {
outline: currentColor solid var(--_border-size);
}
& select {
border: none;
background-color: transparent;
outline: none;
color: currentColor;
}
& option {
background-color: var(--_background-color);
}
& span {
padding: 0;
font-weight: normal;
line-height: normal;
}
}

55
islands/ThemePicker.tsx Normal file
View file

@ -0,0 +1,55 @@
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>
)
}

View file

@ -1,3 +1,4 @@
@import url('../../components/Header.css'); @import url('../../components/Header.css');
@import url('../../components/Footer.css'); @import url('../../components/Footer.css');
@import url('../../components/Heros.css'); @import url('../../components/Heros.css');
@import url('../../islands/ThemePicker.css');