feat(ui): ✨ add theme picker
This commit is contained in:
parent
1431a21d5d
commit
fd32f4c59d
|
@ -1,4 +1,5 @@
|
|||
import { asset } from '$fresh/runtime.ts'
|
||||
import ThemePicker from '../islands/ThemePicker.tsx'
|
||||
|
||||
export function Header() {
|
||||
return (
|
||||
|
@ -50,6 +51,7 @@ export function Header() {
|
|||
</li>
|
||||
</nav>
|
||||
<input type='search' name='' id='' placeholder='Rechercher' />
|
||||
<ThemePicker />
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
|
|
29
islands/ThemePicker.css
Normal file
29
islands/ThemePicker.css
Normal 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
55
islands/ThemePicker.tsx
Normal 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>
|
||||
)
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
@import url('../../components/Header.css');
|
||||
@import url('../../components/Footer.css');
|
||||
@import url('../../components/Heros.css');
|
||||
@import url('../../islands/ThemePicker.css');
|
||||
|
|
Loading…
Reference in a new issue