theme.js

 1// Theme toggle - supports light, dark, and system preference
 2
 3const STORAGE_KEY = 'impeccable-theme';
 4
 5function getStoredTheme() {
 6  return localStorage.getItem(STORAGE_KEY);
 7}
 8
 9function setStoredTheme(theme) {
10  localStorage.setItem(STORAGE_KEY, theme);
11}
12
13function applyTheme(theme) {
14  const html = document.documentElement;
15
16  // Remove both classes first
17  html.classList.remove('light', 'dark');
18
19  if (theme === 'light') {
20    html.classList.add('light');
21  } else if (theme === 'dark') {
22    html.classList.add('dark');
23  }
24  // 'system' = no class, falls back to media query
25
26  // Update active state on buttons
27  document.querySelectorAll('.theme-toggle-btn').forEach(btn => {
28    btn.classList.toggle('active', btn.dataset.theme === theme);
29  });
30}
31
32export function initThemeToggle() {
33  const toggle = document.querySelector('.theme-toggle');
34  if (!toggle) return;
35
36  // Get stored theme or default to system
37  const storedTheme = getStoredTheme() || 'system';
38  applyTheme(storedTheme);
39
40  // Handle button clicks
41  toggle.addEventListener('click', (e) => {
42    const btn = e.target.closest('.theme-toggle-btn');
43    if (!btn) return;
44
45    const theme = btn.dataset.theme;
46    setStoredTheme(theme);
47    applyTheme(theme);
48  });
49
50  // Listen for system preference changes (only matters when in 'system' mode)
51  window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
52    if (getStoredTheme() === 'system' || !getStoredTheme()) {
53      applyTheme('system');
54    }
55  });
56}