Skip to content

Commit 13a5c86

Browse files
committed
remove color flicker
1 parent 1ff9973 commit 13a5c86

1 file changed

Lines changed: 85 additions & 82 deletions

File tree

js/theme.js

Lines changed: 85 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,100 @@
1-
document.addEventListener("DOMContentLoaded", ()=>{
2-
const themeBtn = document.querySelector('#theme-toggle');
3-
const root = document?.documentElement;
4-
5-
const themeWatcher = watchColorSchemeChange((colorScheme) => {
6-
if (!hasLocalStorage()) {
7-
// If localStorage is not supported, use system preference
1+
let themeBtn;
2+
const themeWatcher = watchColorSchemeChange((colorScheme) => {
3+
if (!hasLocalStorage()) {
4+
// If localStorage is not supported, use system preference
5+
document?.addEventListener('DOMContentLoaded', () => {
6+
// remove icon
7+
document.querySelector('#theme-toggle').remove()
88
setTheme(colorScheme);
9-
themeBtn.remove(); // Hide toggle
9+
})
10+
} else {
11+
const localTheme = localStorage.getItem('expressjs-theme');
12+
if (localTheme === null) {
13+
localStorage.setItem('expressjs-theme', colorScheme); // store system theme as local theme
14+
setTheme(colorScheme); // use system theme
1015
} else {
11-
const localTheme = localStorage.getItem('local-theme');
12-
if (localTheme === null) {
13-
localStorage.setItem('local-theme', colorScheme); // store system theme as local theme
14-
setTheme(colorScheme); // use system theme
15-
} else {
16-
setTheme(localTheme); // use previous theme
17-
}
16+
setTheme(localTheme); // use previous theme
17+
};
1818

19+
document.addEventListener("DOMContentLoaded", ()=>{
20+
const themeBtn = document.querySelector('#theme-toggle');
1921
// add click event on theme loggle btn
2022
themeBtn.addEventListener('click', toggleLocalStorageTheme);
2123
// set accessibility on page load
2224
themeBtn.setAttribute('aria-label', colorScheme === 'dark' ? 'Switch to light mode' : 'Switch to dark mode');
23-
}
24-
});
25+
});
26+
}
27+
});
2528

26-
// apply given theme
27-
function setTheme(theme) {
28-
if (theme === 'dark') {
29-
darkModeOn()
30-
} else {
31-
lightModeOn()
32-
}
29+
// apply given theme
30+
function setTheme(theme) {
31+
if (theme === 'dark') {
32+
darkModeOn()
33+
} else {
34+
lightModeOn()
3335
}
34-
// toggle theme btn or set a theme if none set
35-
function toggleLocalStorageTheme() {
36-
let nextTheme;
37-
const localTheme = localStorage.getItem('local-theme');
36+
}
37+
// toggle theme btn or set a theme if none set
38+
function toggleLocalStorageTheme() {
39+
let nextTheme;
40+
const localTheme = localStorage.getItem('expressjs-theme');
3841

39-
if (localTheme === 'light') {
40-
nextTheme = 'dark';
41-
} else if (localTheme === 'dark') {
42-
nextTheme = 'light';
43-
} else {
44-
nextTheme = darkModeState() ? 'light' : 'dark';
45-
}
42+
if (localTheme === 'light') {
43+
nextTheme = 'dark';
44+
} else if (localTheme === 'dark') {
45+
nextTheme = 'light';
46+
} else {
47+
nextTheme = darkModeState() ? 'light' : 'dark'; // fallback
48+
};
4649

47-
localStorage.setItem('local-theme', nextTheme);
48-
setTheme(nextTheme);
49-
}
50-
function darkModeOn() {
51-
root.classList.remove('light-mode')
52-
root.classList.add('dark-mode')
53-
updateThemeIcon('dark');
54-
}
55-
function lightModeOn() {
56-
root.classList.remove('dark-mode')
57-
root.classList.add('light-mode')
58-
updateThemeIcon('light');
59-
}
60-
function darkModeState() {
61-
return root.classList.contains('dark-mode')
62-
}
63-
function hasLocalStorage() {
64-
return typeof Storage !== 'undefined'
65-
}
66-
function watchColorSchemeChange(callback) {
67-
// get system theme preference
68-
const darkMediaQuery = window?.matchMedia('(prefers-color-scheme: dark)')
50+
localStorage.setItem('local-theme', nextTheme);
51+
setTheme(nextTheme);
52+
}
53+
function darkModeOn() {
54+
document?.documentElement?.classList.remove('light-mode')
55+
document?.documentElement?.classList.add('dark-mode')
56+
updateThemeIcon('dark');
57+
}
58+
function lightModeOn() {
59+
document?.documentElement?.classList.remove('dark-mode')
60+
document?.documentElement?.classList.add('light-mode')
61+
updateThemeIcon('light');
62+
}
63+
function darkModeState() {
64+
return document?.documentElement?.classList.contains('dark-mode')
65+
}
66+
function hasLocalStorage() {
67+
return typeof Storage !== 'undefined'
68+
}
69+
function watchColorSchemeChange(callback) {
70+
// get system theme preference
71+
const darkMediaQuery = window?.matchMedia('(prefers-color-scheme: dark)')
6972

70-
const handleChange = (event) => {
71-
const newColorScheme = event?.matches ? 'dark' : 'light'
72-
callback(newColorScheme)
73-
}
74-
darkMediaQuery.addEventListener('change', handleChange)
75-
// initial call : if system theme is not dark then light mode is choosen
76-
callback(darkMediaQuery.matches ? 'dark': 'light')
77-
// remove event from window
78-
return () => darkMediaQuery.removeEventListener('change', handleChange)
73+
const handleChange = (event) => {
74+
const newColorScheme = event?.matches ? 'dark' : 'light'
75+
callback(newColorScheme)
7976
}
77+
darkMediaQuery.addEventListener('change', handleChange)
78+
// initial call : if system theme is not dark then light mode is choosen
79+
callback(darkMediaQuery.matches ? 'dark' : 'light')
80+
// remove event from window
81+
return () => darkMediaQuery.removeEventListener('change', handleChange)
82+
}
8083

81-
function updateThemeIcon (theme) {
82-
const sun = document.getElementById('icon-sun');
83-
const moon = document.getElementById('icon-moon');
84-
if (!sun || !moon) return;
85-
86-
const isDark = theme === 'dark';
84+
function updateThemeIcon(theme) {
85+
const sun = document.getElementById('icon-sun');
86+
const moon = document.getElementById('icon-moon');
87+
const themeBtn = document.querySelector('#theme-toggle');
88+
if (!sun || !moon) return;
8789

88-
// hide or show icon
89-
sun.hidden = !isDark;
90-
moon.hidden = isDark;
91-
// improve accessibility for screen readers
92-
sun.setAttribute('aria-hidden', isDark ? 'false' : 'true');
93-
moon.setAttribute('aria-hidden', isDark ? 'true' : 'false');
94-
// change label on btn click
95-
themeBtn.setAttribute('aria-label', isDark ? 'Switch to light mode' : 'Switch to dark mode');
96-
};
97-
});
90+
const isDark = theme === 'dark';
91+
92+
// hide or show icon
93+
sun.hidden = !isDark;
94+
moon.hidden = isDark;
95+
// improve accessibility for screen readers
96+
sun.setAttribute('aria-hidden', isDark ? 'false' : 'true');
97+
moon.setAttribute('aria-hidden', isDark ? 'true' : 'false');
98+
// change label on btn click
99+
themeBtn.setAttribute('aria-label', isDark ? 'Switch to light mode' : 'Switch to dark mode');
100+
};

0 commit comments

Comments
 (0)