github.com/gemaraproj/gemara@v1.3.0

docs/assets/js/theme-toggle.js raw

 1// SPDX-License-Identifier: Apache-2.0
 2
 3/**
 4 * Theme Toggle Functionality
 5 * Handles dark/light mode switching with system preference detection and localStorage persistence
 6 */
 7
 8(function() {
 9  'use strict';
10
11  // Get theme toggle button and icon elements
12  const themeToggle = document.getElementById('theme-toggle');
13  const themeIcon = document.getElementById('theme-icon');
14
15  // Function to get system preference
16  function getSystemPreference() {
17    return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
18      ? 'dark'
19      : 'light';
20  }
21
22  // Function to get stored theme or system preference
23  function getTheme() {
24    const stored = localStorage.getItem('theme');
25    if (stored === 'dark' || stored === 'light') {
26      return stored;
27    }
28    return getSystemPreference();
29  }
30
31  // Function to set theme
32  function setTheme(theme) {
33    const root = document.documentElement;
34    if (theme === 'dark') {
35      root.setAttribute('data-theme', 'dark');
36      localStorage.setItem('theme', 'dark');
37      if (themeIcon) {
38        themeIcon.className = 'fa-solid fa-sun';
39      }
40    } else {
41      root.removeAttribute('data-theme');
42      localStorage.setItem('theme', 'light');
43      if (themeIcon) {
44        themeIcon.className = 'fa-solid fa-moon';
45      }
46    }
47  }
48
49  // Function to toggle theme
50  function toggleTheme() {
51    const currentTheme = document.documentElement.getAttribute('data-theme');
52    const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
53    setTheme(newTheme);
54  }
55
56  // Initialize theme on page load
57  function initTheme() {
58    const theme = getTheme();
59    setTheme(theme);
60  }
61
62  // Set initial theme immediately to prevent flash
63  initTheme();
64
65  // Add click event listener to toggle button
66  if (themeToggle) {
67    themeToggle.addEventListener('click', toggleTheme);
68  }
69
70  // Listen for system preference changes
71  if (window.matchMedia) {
72    const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
73    mediaQuery.addEventListener('change', function(e) {
74      // Only update if user hasn't manually set a preference
75      if (!localStorage.getItem('theme')) {
76        setTheme(e.matches ? 'dark' : 'light');
77      }
78    });
79  }
80})();
81