-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
Copy paththeme-toggle.tsx
73 lines (64 loc) · 2.06 KB
/
theme-toggle.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import { component$, $, useContext, useStyles$ } from '@builder.io/qwik';
import { SunAndMoon } from './sun-and-moon';
import { themeStorageKey } from '../router-head/theme-script';
import themeToggle from './theme-toggle.css?inline';
import { GlobalStore } from '../../context';
export type ThemePreference = 'dark' | 'light';
export const colorSchemeChangeListener = (onColorSchemeChange: (isDark: boolean) => void) => {
const listener = ({ matches: isDark }: MediaQueryListEvent) => {
onColorSchemeChange(isDark);
};
window
.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', (event) => listener(event));
return () =>
window.matchMedia('(prefers-color-scheme: dark)').removeEventListener('change', listener);
};
export const setPreference = (theme: ThemePreference) => {
localStorage.setItem(themeStorageKey, theme);
reflectPreference(theme);
};
export const reflectPreference = (theme: ThemePreference) => {
document.firstElementChild?.setAttribute('data-theme', theme);
};
export const getColorPreference = (): ThemePreference => {
let theme;
try {
theme = localStorage.getItem(themeStorageKey);
} catch (err) {
//
}
if (theme) {
return theme as ThemePreference;
} else {
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
};
export const ThemeToggle = component$(() => {
useStyles$(themeToggle);
const state = useContext(GlobalStore);
const onClick$ = $(() => {
state.theme = state.theme === 'light' ? 'dark' : 'light';
setPreference(state.theme);
});
return (
<>
<span class="lg:hidden">
<button onClick$={onClick$}>{state.theme === 'light' ? 'Dark' : 'Light'} theme</button>
</span>
<span class="hidden lg:block">
<button
type="button"
class="theme-toggle"
id="theme-toggle"
title="Toggles light & dark"
aria-label={state.theme}
aria-live="polite"
onClick$={onClick$}
>
<SunAndMoon />
</button>
</span>
</>
);
});