/
theme-toggle.js
54 lines (43 loc) · 1.34 KB
/
theme-toggle.js
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
// ------------------- theme switcher
const storageKey = 'theme-preference';
let switchSound;
document.addEventListener('DOMContentLoaded', () => {
switchSound = new Audio('/assets/sounds/light-on.mp3');
});
const onClick = () => {
if (switchSound) {
switchSound.play();
}
// flip current value
theme.value = theme.value === 'light' ? 'dark' : 'light';
setPreference();
};
const getColorPreference = () => {
if (localStorage.getItem(storageKey)) return localStorage.getItem(storageKey);
else
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
};
const setPreference = () => {
localStorage.setItem(storageKey, theme.value);
reflectPreference();
};
const reflectPreference = () => {
document.firstElementChild.setAttribute('data-theme', theme.value);
document.querySelector('#theme-toggle')?.setAttribute('aria-label', theme.value);
};
const theme = {
value: getColorPreference()
};
// set early so no page flashes / CSS is made aware
reflectPreference();
window.onload = () => {
reflectPreference();
document.querySelector('#theme-toggle').addEventListener('click', onClick);
};
// sync with system changes
window
.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', ({matches: isDark}) => {
theme.value = isDark ? 'dark' : 'light';
setPreference();
});