38 lines
1.0 KiB
TypeScript
38 lines
1.0 KiB
TypeScript
import { browser } from '$app/environment';
|
|
|
|
export type ThemePref = 'auto' | 'light' | 'dark';
|
|
|
|
let pref = $state<ThemePref>('auto');
|
|
let systemDark = $state(false);
|
|
|
|
if (browser) {
|
|
const stored = localStorage.getItem('theme');
|
|
if (stored === 'light' || stored === 'dark') pref = stored;
|
|
const mq = window.matchMedia('(prefers-color-scheme: dark)');
|
|
systemDark = mq.matches;
|
|
mq.addEventListener('change', (e) => (systemDark = e.matches));
|
|
}
|
|
|
|
function apply() {
|
|
if (!browser) return;
|
|
if (pref === 'auto') delete document.documentElement.dataset.theme;
|
|
else document.documentElement.dataset.theme = pref;
|
|
}
|
|
apply();
|
|
|
|
export const theme = {
|
|
get pref(): ThemePref {
|
|
return pref;
|
|
},
|
|
/** the resolved mode, following the system when pref is "auto" */
|
|
get isDark(): boolean {
|
|
return pref === 'dark' || (pref === 'auto' && systemDark);
|
|
},
|
|
cycle(): void {
|
|
pref = pref === 'auto' ? 'light' : pref === 'light' ? 'dark' : 'auto';
|
|
if (pref === 'auto') localStorage.removeItem('theme');
|
|
else localStorage.setItem('theme', pref);
|
|
apply();
|
|
}
|
|
};
|