feat: implement color theme switcher with dynamic button colors
Complete color theme system (light/dark/auto) with dynamic UI: Features: - Color theme switcher with auto/light/dark modes - Dynamic button colors on hover (purple/yellow/blue per theme) - localStorage persistence across sessions - Proper button positioning (desktop and mobile) - Mobile: 5-button layout with theme before info button Fixes: - CSP updated to allow jsDelivr CDN for iconify icons - Button repositioning: Download PDF and Print Friendly at top - Hover-only colors (not persistent) - Mobile button order corrected Files: - static/css/color-theme.css - Theme system with CSS variables - static/js/color-theme.js - Theme switching logic - templates/partials/color-theme-switcher.html - Button component - internal/middleware/security.go - CSP fix for jsDelivr - tests/mjs/13-color-theme-switcher.test.mjs - Comprehensive test - tests/TEST-SUMMARY.md - Updated test documentation
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* COLOR THEME SYSTEM
|
||||
* Pure JavaScript implementation (replacing hyperscript due to parsing issues)
|
||||
* Handles light/dark/auto theme switching
|
||||
*/
|
||||
|
||||
// Set color theme
|
||||
function setColorTheme(mode) {
|
||||
// Save preference to localStorage
|
||||
localStorage.setItem('color-theme-mode', mode);
|
||||
|
||||
// Apply theme to document
|
||||
document.documentElement.setAttribute('data-color-theme', mode);
|
||||
|
||||
// Update button icon and color based on mode
|
||||
const themeButton = document.querySelector('#color-theme-switcher');
|
||||
const themeIcon = document.querySelector('#themeIcon');
|
||||
|
||||
if (themeButton) {
|
||||
// Set data attribute for CSS styling
|
||||
themeButton.setAttribute('data-theme-mode', mode);
|
||||
}
|
||||
|
||||
if (themeIcon) {
|
||||
if (mode === 'light') {
|
||||
themeIcon.setAttribute('icon', 'mdi:white-balance-sunny');
|
||||
} else if (mode === 'dark') {
|
||||
themeIcon.setAttribute('icon', 'mdi:moon-waning-crescent');
|
||||
} else {
|
||||
themeIcon.setAttribute('icon', 'mdi:theme-light-dark');
|
||||
}
|
||||
}
|
||||
|
||||
// Update button active states (for hidden compatibility buttons)
|
||||
const buttons = document.querySelectorAll('.theme-option-btn');
|
||||
buttons.forEach(btn => {
|
||||
if (btn.getAttribute('data-theme-mode') === mode) {
|
||||
btn.classList.add('active');
|
||||
} else {
|
||||
btn.classList.remove('active');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize color theme
|
||||
function initColorTheme() {
|
||||
// Get saved preference or default to 'auto'
|
||||
const savedTheme = localStorage.getItem('color-theme-mode') || 'auto';
|
||||
setColorTheme(savedTheme);
|
||||
}
|
||||
|
||||
// Setup button click handler
|
||||
function setupColorThemeButton() {
|
||||
const button = document.querySelector('#color-theme-switcher');
|
||||
if (button) {
|
||||
button.addEventListener('click', () => {
|
||||
// Get current theme
|
||||
const currentTheme = localStorage.getItem('color-theme-mode') || 'auto';
|
||||
|
||||
// Cycle: auto → light → dark → auto
|
||||
if (currentTheme === 'auto') {
|
||||
setColorTheme('light');
|
||||
} else if (currentTheme === 'light') {
|
||||
setColorTheme('dark');
|
||||
} else {
|
||||
setColorTheme('auto');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Watch system theme changes (optional enhancement)
|
||||
function watchSystemTheme() {
|
||||
const darkModeQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
|
||||
darkModeQuery.addEventListener('change', () => {
|
||||
const currentMode = localStorage.getItem('color-theme-mode');
|
||||
if (currentMode === 'auto' || currentMode === null) {
|
||||
// Theme will automatically update via CSS
|
||||
// Just ensure the UI reflects the current state
|
||||
setColorTheme('auto');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize on DOM ready
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
initColorTheme();
|
||||
setupColorThemeButton();
|
||||
watchSystemTheme();
|
||||
});
|
||||
} else {
|
||||
initColorTheme();
|
||||
setupColorThemeButton();
|
||||
watchSystemTheme();
|
||||
}
|
||||
Reference in New Issue
Block a user