From dcf54cad8529526fd7f8d9d4b84b63ccb3fa9630 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Sun, 5 Apr 2026 08:40:09 +0200 Subject: feat: add JavaScript modules (theme toggle, matrix rain, progress tracking, copy-to-clipboard) Implement all 4 JavaScript modules: - theme-toggle.js: Theme switching with localStorage persistence - matrix-rain.js: Animated matrix-style rain effect on canvas - progress-bar.js: Reading progress tracking during scroll - copy-code.js: Copy-to-clipboard functionality for code blocks Co-Authored-By: Claude Haiku 4.5 --- assets/js/theme-toggle.js | 83 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 assets/js/theme-toggle.js (limited to 'assets/js/theme-toggle.js') diff --git a/assets/js/theme-toggle.js b/assets/js/theme-toggle.js new file mode 100644 index 0000000..9f0fd5a --- /dev/null +++ b/assets/js/theme-toggle.js @@ -0,0 +1,83 @@ +// theme-toggle.js +(function() { + const STORAGE_KEY = 'danix-theme'; + const DARK_CLASS = 'theme-dark'; + const LIGHT_CLASS = 'theme-light'; + + // Initialize theme on page load + function init() { + const saved = localStorage.getItem(STORAGE_KEY); + const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; + const isDark = saved === null ? prefersDark : saved === 'dark'; + + applyTheme(isDark ? 'dark' : 'light'); + } + + // Apply theme to document + function applyTheme(theme) { + const html = document.documentElement; + + html.classList.remove(DARK_CLASS, LIGHT_CLASS); + + if (theme === 'dark') { + html.classList.remove(LIGHT_CLASS); + localStorage.setItem(STORAGE_KEY, 'dark'); + } else { + html.classList.add(LIGHT_CLASS); + localStorage.setItem(STORAGE_KEY, 'light'); + } + } + + // Get current theme + function getCurrentTheme() { + return document.documentElement.classList.contains(LIGHT_CLASS) ? 'light' : 'dark'; + } + + // Toggle theme + function toggleTheme() { + const current = getCurrentTheme(); + const next = current === 'dark' ? 'light' : 'dark'; + applyTheme(next); + + // Dispatch custom event for other scripts to listen + window.dispatchEvent(new CustomEvent('theme-changed', { detail: { theme: next } })); + } + + // Setup toggle button + function setupToggleButton() { + const btn = document.getElementById('theme-toggle-btn'); + if (btn) { + btn.addEventListener('click', toggleTheme); + updateToggleButtonLabel(); + + // Listen for theme changes to update button label + window.addEventListener('theme-changed', updateToggleButtonLabel); + } + } + + function updateToggleButtonLabel() { + const btn = document.getElementById('theme-toggle-btn'); + if (btn) { + const current = getCurrentTheme(); + btn.textContent = current === 'dark' ? '☀️ light' : '🌙 dark'; + } + } + + // Initialize on DOMContentLoaded + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', function() { + init(); + setupToggleButton(); + }); + } else { + init(); + setupToggleButton(); + } + + // Expose to global scope for testing + window.ThemeToggle = { + toggle: toggleTheme, + set: applyTheme, + get: getCurrentTheme, + }; +})(); -- cgit v1.2.3