2025-12-11 17:17:01 +00:00
|
|
|
class ThemeSelector {
|
|
|
|
|
constructor() {
|
|
|
|
|
this.widget = document.querySelector('#theme-selector');
|
2026-08-22 18:14:08 +01:00
|
|
|
this.btnLight = this.widget.querySelector('#btn-light');
|
|
|
|
|
this.btnDark = this.widget.querySelector('#btn-dark');
|
|
|
|
|
this.status = this.widget.querySelector('#theme-status');
|
|
|
|
|
this.currentTheme = 'system';
|
2025-12-11 17:17:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setupEventListeners() {
|
2026-08-22 18:14:08 +01:00
|
|
|
this.btnLight.addEventListener('click', () => {
|
|
|
|
|
this.applyTheme(this.currentTheme === 'light' ? 'system' : 'light');
|
|
|
|
|
});
|
2025-12-11 17:17:01 +00:00
|
|
|
|
2026-08-22 18:14:08 +01:00
|
|
|
this.btnDark.addEventListener('click', () => {
|
|
|
|
|
this.applyTheme(this.currentTheme === 'dark' ? 'system' : 'dark');
|
|
|
|
|
});
|
|
|
|
|
}
|
2025-12-11 17:17:01 +00:00
|
|
|
|
2026-08-22 18:14:08 +01:00
|
|
|
applyTheme(theme) {
|
|
|
|
|
const selectedTheme = (theme === 'light' || theme === 'dark') ? theme : 'light dark';
|
2025-12-11 17:17:01 +00:00
|
|
|
|
2026-08-22 18:14:08 +01:00
|
|
|
const systemTheme = (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) ? 'dark' : 'light';
|
|
|
|
|
const html = document.documentElement;
|
|
|
|
|
let currentColorScheme = html.style.getPropertyValue('color-scheme');
|
|
|
|
|
if (currentColorScheme === '') {
|
|
|
|
|
currentColorScheme = 'light dark';
|
|
|
|
|
}
|
2025-12-11 17:17:01 +00:00
|
|
|
|
2026-08-22 18:14:08 +01:00
|
|
|
/* do we need to transition */
|
|
|
|
|
let doTransition = false;
|
2025-12-11 17:17:01 +00:00
|
|
|
|
2026-08-22 18:14:08 +01:00
|
|
|
if (selectedTheme !== currentColorScheme) {
|
|
|
|
|
if (selectedTheme === 'light dark') {
|
|
|
|
|
doTransition = currentColorScheme !== systemTheme;
|
|
|
|
|
} else if (currentColorScheme === 'light dark') {
|
|
|
|
|
doTransition = selectedTheme !== systemTheme;
|
2025-12-11 17:17:01 +00:00
|
|
|
} else {
|
2026-08-22 18:14:08 +01:00
|
|
|
doTransition = true;
|
2025-12-11 17:17:01 +00:00
|
|
|
}
|
2026-08-22 18:14:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const applyChange = () => {
|
|
|
|
|
this.currentTheme = theme;
|
|
|
|
|
html.style.setProperty('color-scheme', selectedTheme);
|
|
|
|
|
|
|
|
|
|
this.btnLight.setAttribute('aria-pressed', String(theme === 'light'));
|
|
|
|
|
this.btnDark.setAttribute('aria-pressed', String(theme === 'dark'));
|
|
|
|
|
this.status.textContent = theme === 'system' ? 'Theme set to system default' : '';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
html.style.viewTransitionName = 'changing-theme';
|
|
|
|
|
if (doTransition && document.startViewTransition) {
|
|
|
|
|
document.startViewTransition(applyChange);
|
|
|
|
|
} else {
|
|
|
|
|
applyChange();
|
|
|
|
|
}
|
2025-12-11 17:17:01 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export { ThemeSelector };
|