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:
juanatsap
2025-11-18 15:49:30 +00:00
parent 481003fcf8
commit f3cce51fb3
13 changed files with 1193 additions and 41 deletions
+59
View File
@@ -0,0 +1,59 @@
-- COLOR THEME SYSTEM
-- Functions for light/dark/auto color theme switching
-- IMPORTANT: This is SEPARATE from layout theme (.theme-clean)
-- Color theme: Controls backgrounds, text colors (light/dark/auto)
-- Layout theme: Controls sidebars, layout structure (default/clean)
-- SET COLOR THEME
def setColorTheme(mode)
-- Save preference to localStorage
call localStorage.setItem('color-theme-mode', mode)
-- Apply theme to document
call document.documentElement.setAttribute('data-color-theme', mode)
-- Update button icon based on mode
if mode is 'light' then call document.querySelector('#themeIcon').setAttribute('icon', 'mdi:white-balance-sunny') end
if mode is 'dark' then call document.querySelector('#themeIcon').setAttribute('icon', 'mdi:moon-waning-crescent') end
if mode is 'auto' then call document.querySelector('#themeIcon').setAttribute('icon', 'mdi:theme-light-dark') end
-- Update button active states (for hidden compatibility buttons)
set buttons to .theme-option-btn
for btn in buttons
if btn's @data-theme-mode is mode
add .active to btn
else
remove .active from btn
end
end
end
-- INITIALIZE COLOR THEME
def initColorTheme()
-- Get saved preference or default to 'auto'
set savedTheme to localStorage['color-theme-mode'] or 'auto'
-- Save preference to localStorage
call localStorage.setItem('color-theme-mode', savedTheme)
-- Apply theme to document
call document.documentElement.setAttribute('data-color-theme', savedTheme)
-- Update button icon based on mode
if savedTheme is 'light' then call document.querySelector('#themeIcon').setAttribute('icon', 'mdi:white-balance-sunny') end
if savedTheme is 'dark' then call document.querySelector('#themeIcon').setAttribute('icon', 'mdi:moon-waning-crescent') end
if savedTheme is 'auto' then call document.querySelector('#themeIcon').setAttribute('icon', 'mdi:theme-light-dark') end
end
-- SYSTEM THEME CHANGE LISTENER (Optional Enhancement)
-- Listen for system theme changes when in 'auto' mode
-- This is automatically handled by CSS media queries, but we update UI
def watchSystemTheme()
set darkModeQuery to window.matchMedia('(prefers-color-scheme: dark)')
-- Update UI when system preference changes (if in auto mode)
on change from darkModeQuery
set currentMode to localStorage['color-theme-mode']
if currentMode is 'auto' or currentMode is null then call setColorTheme('auto') end
end
end