79 lines
1.8 KiB
TypeScript
79 lines
1.8 KiB
TypeScript
/**
|
|
* Theme utilities for dark/light mode
|
|
*/
|
|
|
|
export type Theme = 'light' | 'dark';
|
|
|
|
/**
|
|
* Get the current theme from localStorage or system preference
|
|
*/
|
|
export function getInitialTheme(): Theme {
|
|
// Check localStorage first
|
|
const savedTheme = localStorage.getItem('theme') as Theme;
|
|
if (savedTheme) {
|
|
return savedTheme;
|
|
}
|
|
|
|
// Check system preference
|
|
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
|
return 'dark';
|
|
}
|
|
|
|
// Default to light
|
|
return 'light';
|
|
}
|
|
|
|
/**
|
|
* Apply theme to document
|
|
*/
|
|
export function applyTheme(theme: Theme): void {
|
|
const root = document.documentElement;
|
|
|
|
if (theme === 'dark') {
|
|
root.classList.add('dark');
|
|
} else {
|
|
root.classList.remove('dark');
|
|
}
|
|
|
|
// Save to localStorage
|
|
localStorage.setItem('theme', theme);
|
|
}
|
|
|
|
/**
|
|
* Initialize theme on page load
|
|
*/
|
|
export function initializeTheme(): void {
|
|
const theme = getInitialTheme();
|
|
applyTheme(theme);
|
|
}
|
|
|
|
/**
|
|
* Toggle between light and dark themes
|
|
*/
|
|
export function toggleTheme(): Theme {
|
|
const currentTheme = getInitialTheme();
|
|
const newTheme = currentTheme === 'light' ? 'dark' : 'light';
|
|
applyTheme(newTheme);
|
|
return newTheme;
|
|
}
|
|
|
|
/**
|
|
* Listen for system theme changes
|
|
*/
|
|
export function watchSystemTheme(callback: (theme: Theme) => void): () => void {
|
|
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|
|
|
const handleChange = (e: MediaQueryListEvent) => {
|
|
// Only update if user hasn't set a preference in localStorage
|
|
if (!localStorage.getItem('theme')) {
|
|
const theme = e.matches ? 'dark' : 'light';
|
|
callback(theme);
|
|
applyTheme(theme);
|
|
}
|
|
};
|
|
|
|
mediaQuery.addEventListener('change', handleChange);
|
|
|
|
// Return cleanup function
|
|
return () => mediaQuery.removeEventListener('change', handleChange);
|
|
} |