121 lines
3.5 KiB
JavaScript
121 lines
3.5 KiB
JavaScript
// Theme Manager - Handles theme switching and persistence
|
|
|
|
class ThemeManager {
|
|
constructor() {
|
|
this.currentTheme = this.getStoredTheme() || 'dark';
|
|
this.themeToggle = document.getElementById('theme-toggle');
|
|
this.init();
|
|
}
|
|
|
|
init() {
|
|
// Apply stored theme on page load
|
|
this.applyTheme(this.currentTheme);
|
|
|
|
// Set up event listener for theme toggle
|
|
if (this.themeToggle) {
|
|
this.themeToggle.addEventListener('click', () => this.toggleTheme());
|
|
}
|
|
|
|
// Listen for system theme changes
|
|
if (window.matchMedia) {
|
|
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|
mediaQuery.addListener((e) => {
|
|
if (this.getStoredTheme() === 'system') {
|
|
this.applyTheme(e.matches ? 'dark' : 'light');
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
getStoredTheme() {
|
|
try {
|
|
return localStorage.getItem('spore-ledlab-theme');
|
|
} catch (e) {
|
|
console.warn('Could not access localStorage for theme preference');
|
|
return 'dark';
|
|
}
|
|
}
|
|
|
|
setStoredTheme(theme) {
|
|
try {
|
|
localStorage.setItem('spore-ledlab-theme', theme);
|
|
} catch (e) {
|
|
console.warn('Could not save theme preference to localStorage');
|
|
}
|
|
}
|
|
|
|
applyTheme(theme) {
|
|
// Update data attribute on html element
|
|
document.documentElement.setAttribute('data-theme', theme);
|
|
|
|
// Update theme toggle icon
|
|
this.updateThemeIcon(theme);
|
|
|
|
// Store the theme preference
|
|
this.setStoredTheme(theme);
|
|
|
|
this.currentTheme = theme;
|
|
|
|
// Dispatch custom event for other components
|
|
window.dispatchEvent(new CustomEvent('themeChanged', {
|
|
detail: { theme: theme }
|
|
}));
|
|
}
|
|
|
|
updateThemeIcon(theme) {
|
|
if (!this.themeToggle) return;
|
|
|
|
const svg = this.themeToggle.querySelector('svg');
|
|
if (!svg) return;
|
|
|
|
// Update the SVG content based on theme
|
|
if (theme === 'light') {
|
|
// Sun icon for light theme
|
|
svg.innerHTML = `
|
|
<circle cx="12" cy="12" r="5"/>
|
|
<path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>
|
|
`;
|
|
} else {
|
|
// Moon icon for dark theme
|
|
svg.innerHTML = `
|
|
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
|
|
`;
|
|
}
|
|
}
|
|
|
|
toggleTheme() {
|
|
const newTheme = this.currentTheme === 'dark' ? 'light' : 'dark';
|
|
this.applyTheme(newTheme);
|
|
|
|
// Add a subtle animation to the toggle button
|
|
if (this.themeToggle) {
|
|
this.themeToggle.style.transform = 'scale(0.9)';
|
|
setTimeout(() => {
|
|
this.themeToggle.style.transform = 'scale(1)';
|
|
}, 150);
|
|
}
|
|
}
|
|
|
|
// Method to get current theme (useful for other components)
|
|
getCurrentTheme() {
|
|
return this.currentTheme;
|
|
}
|
|
|
|
// Method to set theme programmatically
|
|
setTheme(theme) {
|
|
if (['dark', 'light'].includes(theme)) {
|
|
this.applyTheme(theme);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Initialize theme manager when DOM is loaded
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
window.themeManager = new ThemeManager();
|
|
});
|
|
|
|
// Export for use in other modules
|
|
if (typeof module !== 'undefined' && module.exports) {
|
|
module.exports = ThemeManager;
|
|
}
|