Skip to content

Commit 1ff9973

Browse files
committed
fix bugs and refactor theme.js
1 parent ea489a4 commit 1ff9973

3 files changed

Lines changed: 90 additions & 105 deletions

File tree

_includes/header.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,9 +247,9 @@
247247
</ul>
248248
</nav>
249249
<div class="header-right">
250-
<button id="theme-toggle" type="button" class="theme-btn" title="change theme" aria-label="Toggle light or dark mode">
250+
<button id="theme-toggle" type="button" class="theme-btn" title="change theme" aria-label="Switch to dark mode">
251251
<span id="icon-moon">{% include icons/moon.svg %}</span>
252-
<span id="icon-sun" style="display: none;">{% include icons/sun.svg %}</span>
252+
<span id="icon-sun">{% include icons/sun.svg %}</span>
253253
</button>
254254
{% include language-picker.html %}
255255
{% include language-picker-mobile.html %}

css/style.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,11 @@ button.theme-btn {
775775
align-items: center;
776776
}
777777

778+
#icon-moon[hidden],
779+
#icon-sun[hidden] {
780+
display: none;
781+
}
782+
778783
button.lang-btn {
779784
appearance: none;
780785
background-color: inherit;

js/theme.js

Lines changed: 83 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,117 +1,97 @@
1-
const themeWatcher = watchColorSchemeChange((colorScheme) => {
2-
if (!hasLocalStorage()) {
3-
document?.addEventListener('DOMContentLoaded', () => {
4-
// remove icon - toggle not supported
5-
document.querySelector('#theme-toggle').remove()
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
68
setTheme(colorScheme);
7-
})
8-
} else {
9-
// user's PS system theme settings
10-
const systemTheme = localStorage.getItem('system-theme')
11-
// setting stored in local storage
12-
const localTheme = localStorage.getItem('local-theme')
13-
// // if no local theme set - system is default
14-
if (localTheme === null) {
15-
setTheme(colorScheme)
16-
localStorage.setItem('system-theme', colorScheme || 'light')
17-
// page load - load any stored themes or set theme
9+
themeBtn.remove(); // Hide toggle
1810
} else {
19-
// listen for system changes, update if any
20-
if (colorScheme != systemTheme) {
21-
setTheme(colorScheme)
22-
localStorage.setItem('system-theme', colorScheme || 'light')
23-
// override local theme
24-
localStorage.removeItem('local-theme')
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
2515
} else {
26-
// else load local theme
27-
if (localTheme === 'light') {
28-
lightModeOn()
29-
} else if (localTheme === 'dark') {
30-
darkModeOn()
31-
}
16+
setTheme(localTheme); // use previous theme
3217
}
18+
19+
// add click event on theme loggle btn
20+
themeBtn.addEventListener('click', toggleLocalStorageTheme);
21+
// set accessibility on page load
22+
themeBtn.setAttribute('aria-label', colorScheme === 'dark' ? 'Switch to light mode' : 'Switch to dark mode');
3323
}
34-
// wait for load then and add listner on button
35-
document.addEventListener('DOMContentLoaded', () => {
24+
});
3625

37-
document
38-
.querySelector('#theme-toggle')
39-
.addEventListener('click', toggleLocalStorageTheme)
40-
})
41-
}
42-
})
43-
// set the theme to given value
44-
function setTheme(theme) {
45-
// only support dark else any other defaults to light
46-
if (theme === 'dark') {
47-
darkModeOn()
48-
} else {
49-
lightModeOn()
50-
}
51-
}
52-
// toggle btwn themes or set a theme if none set
53-
function toggleLocalStorageTheme(e) {
54-
const localTheme = localStorage.getItem('local-theme')
55-
if (localTheme === 'light') {
56-
localStorage.setItem('local-theme', 'dark')
57-
darkModeOn()
58-
} else if (localTheme === 'dark') {
59-
localStorage.setItem('local-theme', 'light')
60-
lightModeOn()
61-
// localTheme still null
62-
} else {
63-
// need to check page state then set
64-
if (darkModeState()) {
65-
localStorage.setItem('local-theme', 'light')
26+
// apply given theme
27+
function setTheme(theme) {
28+
if (theme === 'dark') {
29+
darkModeOn()
30+
} else {
6631
lightModeOn()
32+
}
33+
}
34+
// toggle theme btn or set a theme if none set
35+
function toggleLocalStorageTheme() {
36+
let nextTheme;
37+
const localTheme = localStorage.getItem('local-theme');
38+
39+
if (localTheme === 'light') {
40+
nextTheme = 'dark';
41+
} else if (localTheme === 'dark') {
42+
nextTheme = 'light';
6743
} else {
68-
localStorage.setItem('local-theme', 'dark')
69-
darkModeOn()
44+
nextTheme = darkModeState() ? 'light' : 'dark';
7045
}
46+
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');
7154
}
72-
}
73-
function darkModeOn() {
74-
document?.documentElement?.classList?.remove('light-mode')
75-
document?.documentElement?.classList?.add('dark-mode')
76-
updateThemeIcon('dark');
77-
}
78-
function lightModeOn() {
79-
document?.documentElement?.classList.remove('dark-mode')
80-
document?.documentElement?.classList?.add('light-mode')
81-
updateThemeIcon('light');
82-
}
83-
function darkModeState() {
84-
return document?.documentElement?.classList.contains('dark-mode')
85-
}
86-
function hasLocalStorage() {
87-
return typeof Storage !== 'undefined'
88-
}
89-
function watchColorSchemeChange(callback) {
90-
// query user's machine for system setting & use that
91-
const darkMediaQuery = window?.matchMedia('(prefers-color-scheme: dark)')
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)')
9269

93-
const handleChange = (event) => {
94-
const newColorScheme = event?.matches ? 'dark' : 'light'
95-
callback(newColorScheme)
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)
9679
}
97-
darkMediaQuery.addEventListener('change', handleChange)
98-
// handle init load value
99-
callback(darkMediaQuery.matches ? 'dark': 'light')
100-
// Return a function to remove the event listener
101-
return () => darkMediaQuery.removeEventListener('change', handleChange)
102-
}
10380

104-
function updateThemeIcon (theme) {
105-
const sun = document.getElementById('icon-sun');
106-
const moon = document.getElementById('icon-moon');
107-
if (!sun || !moon) return;
108-
109-
const isDark = theme === 'dark';
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';
11087

111-
// Show the icon representing the *next* theme
112-
sun.style.display = isDark ? 'block' : 'none'; // Show sun in dark mode
113-
moon.style.display = isDark ? 'none' : 'block'; // Show moon in light mode
114-
// improve accessibility for screen readers
115-
sun.setAttribute('aria-hidden', isDark ? 'false' : 'true');
116-
moon.setAttribute('aria-hidden', isDark ? 'true' : 'false');
117-
};
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+
});

0 commit comments

Comments
 (0)