Root cause: the [data-theme-toggle] button existed in ASW's baseof.html but had no JavaScript attached to it — clicking it did nothing. Fix: - static/js/theme-toggle.js — click handler, localStorage persistence, prefers-color-scheme fallback, dynamic button icon + aria-label - static/css/garden.css — full html[data-theme="light"] variable block (garden + ASW tokens) so light mode actually looks different from dark - layouts/partials/head.html — include theme-toggle.js with defer Light palette: near-white indigo bg (96%), dark indigo text (20%), violet accents. ASW's @media (prefers-color-scheme) doesn't match programmatic data-theme toggle, so garden.css provides duplicating overrides on html[data-theme="light"].
71 lines
No EOL
2.7 KiB
JavaScript
71 lines
No EOL
2.7 KiB
JavaScript
/**
|
|
* theme-toggle.js — dark/light toggle for Vigo's garden.
|
|
*
|
|
* Handles the [data-theme-toggle] button in the nav (from ASW's baseof.html).
|
|
* Persists preference to localStorage. Falls back to prefers-color-scheme,
|
|
* then to dark (the garden default).
|
|
*/
|
|
|
|
(function () {
|
|
'use strict';
|
|
|
|
var STORAGE_KEY = 'garden-theme';
|
|
var HTML = document.documentElement;
|
|
|
|
// ── Icons ──────────────────────────────────────────────────────────
|
|
var ICONS = {
|
|
dark: '\u{1F31B}', // crescent moon — current theme is light, click to go dark
|
|
light: '\u{2600}\u{FE0F}', // sun — current theme is dark, click to go light
|
|
};
|
|
|
|
// ── Labels (accessibility) ─────────────────────────────────────────
|
|
var LABELS = {
|
|
dark: 'Switch to dark theme',
|
|
light: 'Switch to light theme',
|
|
};
|
|
|
|
// ── Resolve initial theme ──────────────────────────────────────────
|
|
function getInitialTheme() {
|
|
var saved = localStorage.getItem(STORAGE_KEY);
|
|
if (saved === 'dark' || saved === 'light') return saved;
|
|
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches) {
|
|
return 'light';
|
|
}
|
|
return 'dark'; // garden default
|
|
}
|
|
|
|
// ── Apply theme ────────────────────────────────────────────────────
|
|
function applyTheme(theme, button) {
|
|
HTML.setAttribute('data-theme', theme);
|
|
var other = theme === 'dark' ? 'light' : 'dark';
|
|
if (button) {
|
|
button.textContent = ICONS[other];
|
|
button.setAttribute('aria-label', LABELS[other]);
|
|
}
|
|
}
|
|
|
|
// ── Boot ───────────────────────────────────────────────────────────
|
|
function init() {
|
|
var button = document.querySelector('[data-theme-toggle]');
|
|
if (!button) return;
|
|
|
|
// Apply saved/system theme on load
|
|
var theme = getInitialTheme();
|
|
applyTheme(theme, button);
|
|
localStorage.setItem(STORAGE_KEY, theme);
|
|
|
|
// Click handler
|
|
button.addEventListener('click', function () {
|
|
var current = HTML.getAttribute('data-theme') || 'dark';
|
|
var next = current === 'dark' ? 'light' : 'dark';
|
|
applyTheme(next, button);
|
|
localStorage.setItem(STORAGE_KEY, next);
|
|
});
|
|
}
|
|
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', init);
|
|
} else {
|
|
init();
|
|
}
|
|
})(); |