41 lines
1.8 KiB
JavaScript
41 lines
1.8 KiB
JavaScript
(() => {
|
|
const root = document.documentElement;
|
|
const preferredTheme = () => localStorage.getItem('uniformflow-theme')
|
|
|| (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
|
|
|
|
const applyTheme = theme => {
|
|
root.dataset.theme = theme;
|
|
localStorage.setItem('uniformflow-theme', theme);
|
|
document.querySelectorAll('[data-theme-toggle]').forEach(button => {
|
|
const nextTheme = theme === 'dark' ? 'light' : 'dark';
|
|
button.setAttribute('aria-label', `Switch to ${nextTheme} theme`);
|
|
button.setAttribute('title', `Switch to ${nextTheme} theme`);
|
|
button.setAttribute('aria-pressed', theme === 'dark' ? 'true' : 'false');
|
|
});
|
|
};
|
|
|
|
applyTheme(root.dataset.theme || preferredTheme());
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
applyTheme(root.dataset.theme || preferredTheme());
|
|
document.querySelectorAll('[data-theme-toggle]').forEach(button => button.addEventListener('click', () => {
|
|
const nextTheme = root.dataset.theme === 'dark' ? 'light' : 'dark';
|
|
const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
|
|
if (reducedMotion) {
|
|
applyTheme(nextTheme);
|
|
return;
|
|
}
|
|
|
|
root.classList.add('theme-changing');
|
|
if (document.startViewTransition) {
|
|
document.startViewTransition(() => applyTheme(nextTheme)).finished.finally(() => {
|
|
window.setTimeout(() => root.classList.remove('theme-changing'), 120);
|
|
});
|
|
} else {
|
|
requestAnimationFrame(() => applyTheme(nextTheme));
|
|
window.setTimeout(() => root.classList.remove('theme-changing'), 420);
|
|
}
|
|
}));
|
|
});
|
|
})();
|