46 lines
1.4 KiB
JavaScript
46 lines
1.4 KiB
JavaScript
/**
|
|
* theme.js
|
|
* --------
|
|
* Dark / light theme management.
|
|
*
|
|
* Reads the user's saved preference from localStorage and falls back to the
|
|
* OS-level prefers-color-scheme media query. Writes back on every change
|
|
* so the choice persists across page loads.
|
|
*
|
|
* Exports
|
|
* -------
|
|
* initTheme() — call once at startup; reads saved pref and applies it
|
|
* applyTheme() — apply a specific theme string ('dark' | 'light')
|
|
*/
|
|
|
|
import { els } from './state.js';
|
|
|
|
/**
|
|
* Apply *theme* to the document and persist the choice.
|
|
* @param {'dark'|'light'} theme
|
|
*/
|
|
export function applyTheme(theme) {
|
|
document.documentElement.setAttribute('data-theme', theme);
|
|
els.themeIcon.textContent = theme === 'dark' ? '☀' : '◑';
|
|
els.themeToggle.setAttribute(
|
|
'aria-label',
|
|
`Switch to ${theme === 'dark' ? 'light' : 'dark'} mode`,
|
|
);
|
|
localStorage.setItem('vp-theme', theme);
|
|
}
|
|
|
|
/**
|
|
* Read the saved theme preference (or detect from OS) and apply it.
|
|
* Attaches the toggle button's click listener.
|
|
* Call once during app initialisation.
|
|
*/
|
|
export function initTheme() {
|
|
const saved = localStorage.getItem('vp-theme');
|
|
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
applyTheme(saved || (prefersDark ? 'dark' : 'light'));
|
|
|
|
els.themeToggle.addEventListener('click', () => {
|
|
const current = document.documentElement.getAttribute('data-theme');
|
|
applyTheme(current === 'dark' ? 'light' : 'dark');
|
|
});
|
|
}
|