initial production version
This commit is contained in:
63
src/lib/stores/theme.svelte.ts
Normal file
63
src/lib/stores/theme.svelte.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { browser } from '$app/environment';
|
||||
|
||||
type Theme = 'light' | 'dark' | 'system';
|
||||
|
||||
class ThemeStore {
|
||||
current = $state<Theme>('system');
|
||||
|
||||
constructor() {
|
||||
if (browser) {
|
||||
const stored = localStorage.getItem('theme') as Theme | null;
|
||||
this.current = stored || 'system';
|
||||
this.applyTheme();
|
||||
|
||||
// Listen for system theme changes
|
||||
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
mediaQuery.addEventListener('change', () => {
|
||||
// Re-apply theme if in system mode
|
||||
if (this.current === 'system') {
|
||||
this.applyTheme();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private applyTheme() {
|
||||
if (!browser) return;
|
||||
|
||||
const isDark = this.current === 'dark' ||
|
||||
(this.current === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches);
|
||||
|
||||
if (isDark) {
|
||||
document.documentElement.classList.add('dark');
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark');
|
||||
}
|
||||
}
|
||||
|
||||
toggle() {
|
||||
// Cycle through: light -> dark -> system -> light
|
||||
if (this.current === 'light') {
|
||||
this.current = 'dark';
|
||||
} else if (this.current === 'dark') {
|
||||
this.current = 'system';
|
||||
} else {
|
||||
this.current = 'light';
|
||||
}
|
||||
|
||||
if (browser) {
|
||||
localStorage.setItem('theme', this.current);
|
||||
this.applyTheme();
|
||||
}
|
||||
}
|
||||
|
||||
set(theme: Theme) {
|
||||
this.current = theme;
|
||||
if (browser) {
|
||||
localStorage.setItem('theme', this.current);
|
||||
}
|
||||
this.applyTheme();
|
||||
}
|
||||
}
|
||||
|
||||
export const themeStore = new ThemeStore();
|
||||
Reference in New Issue
Block a user