Archived
2
0
This repository has been archived on 2025-07-16. You can view files and clone it, but cannot push or open issues or pull requests.
cc24-hub/src/js/theme.js
overcuriousity 64d5e75045 progress
2025-07-13 22:18:53 +02:00

141 lines
4.2 KiB
JavaScript

// File: ./src/js/theme.js
// Theme management functionality
(function() {
'use strict';
let currentTheme = 'auto';
let mediaQuery;
// Initialize theme system
function init() {
// Get stored theme or default to auto
currentTheme = localStorage.getItem('theme') || 'auto';
// Set up media query listener for auto mode
mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
mediaQuery.addEventListener('change', handleSystemThemeChange);
// Apply initial theme
applyTheme(currentTheme);
// Set up theme selector buttons
setupThemeSelector();
}
// Set up theme selector button event handlers
function setupThemeSelector() {
const themeButtons = document.querySelectorAll('.theme-btn');
themeButtons.forEach(button => {
const theme = button.getAttribute('data-theme');
// Set initial active state
button.classList.toggle('active', theme === currentTheme);
// Add click handler
button.addEventListener('click', () => {
setTheme(theme);
});
});
}
// Set theme and update UI
function setTheme(theme) {
if (!['light', 'dark', 'auto'].includes(theme)) {
console.warn('Invalid theme:', theme);
return;
}
currentTheme = theme;
// Store in localStorage
localStorage.setItem('theme', theme);
// Apply theme
applyTheme(theme);
// Update button states
updateThemeButtons();
}
// Apply theme to document
function applyTheme(theme) {
const html = document.documentElement;
// Update theme class
html.className = html.className.replace(/theme-\w+/g, '');
html.classList.add(`theme-${theme}`);
// Handle dark mode class
if (theme === 'auto') {
// Use system preference
const isDark = mediaQuery ? mediaQuery.matches :
window.matchMedia('(prefers-color-scheme: dark)').matches;
html.classList.toggle('dark', isDark);
} else {
// Use explicit theme
html.classList.toggle('dark', theme === 'dark');
}
}
// Handle system theme changes (for auto mode)
function handleSystemThemeChange(event) {
if (currentTheme === 'auto') {
document.documentElement.classList.toggle('dark', event.matches);
}
}
// Update theme button active states
function updateThemeButtons() {
const themeButtons = document.querySelectorAll('.theme-btn');
themeButtons.forEach(button => {
const theme = button.getAttribute('data-theme');
button.classList.toggle('active', theme === currentTheme);
});
}
// Get current effective theme (resolves 'auto' to actual theme)
function getEffectiveTheme() {
if (currentTheme === 'auto') {
return mediaQuery && mediaQuery.matches ? 'dark' : 'light';
}
return currentTheme;
}
// Toggle between light and dark (skips auto)
function toggleTheme() {
const effectiveTheme = getEffectiveTheme();
setTheme(effectiveTheme === 'dark' ? 'light' : 'dark');
}
// Keyboard shortcut support
function setupKeyboardShortcuts() {
document.addEventListener('keydown', (event) => {
// Ctrl/Cmd + Shift + T to toggle theme
if ((event.ctrlKey || event.metaKey) && event.shiftKey && event.key === 'T') {
event.preventDefault();
toggleTheme();
}
});
}
// Export functions for external use
window.themeManager = {
setTheme,
getTheme: () => currentTheme,
getEffectiveTheme,
toggleTheme
};
// Initialize when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
init();
setupKeyboardShortcuts();
});
} else {
init();
setupKeyboardShortcuts();
}
})();