fix dark/light theme toggle — was a dead button with no JS handler
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"].
This commit is contained in:
parent
00fa25f436
commit
148d6c9126
121 changed files with 295 additions and 0 deletions
|
|
@ -44,11 +44,64 @@
|
|||
--garden-wide-width: 80ch;
|
||||
}
|
||||
|
||||
/* ── Light theme ─────────────────────────────────────────── */
|
||||
/* Override garden's custom properties when theme is light.
|
||||
ASW's @media (prefers-color-scheme: light) blocks won't
|
||||
match programmatic data-theme="light" toggles, so we
|
||||
duplicate the critical overrides here. */
|
||||
html[data-theme="light"] {
|
||||
--garden-bg: oklch(96% 0.015 270); /* near-white indigo */
|
||||
--garden-surface: oklch(92% 0.02 270); /* light card bg */
|
||||
--garden-border: oklch(80% 0.02 270); /* subtle border */
|
||||
--garden-text: oklch(20% 0.025 270); /* dark indigo text */
|
||||
--garden-text-dim: oklch(45% 0.03 270); /* secondary */
|
||||
--garden-text-faint: oklch(60% 0.02 270); /* tertiary */
|
||||
--surface: oklch(96% 0.015 270);
|
||||
--surface-1: oklch(92% 0.02 270);
|
||||
--surface-2: oklch(88% 0.02 270);
|
||||
--surface-card: oklch(92% 0.02 270);
|
||||
--surface-hover: oklch(88% 0.02 270);
|
||||
--text: oklch(20% 0.025 270);
|
||||
--text-2: oklch(30% 0.025 270);
|
||||
--text-3: oklch(45% 0.03 270);
|
||||
--text-dim: oklch(60% 0.02 270);
|
||||
--border: oklch(80% 0.02 270);
|
||||
--border-subtle: oklch(88% 0.02 270);
|
||||
--garden-dialogue: var(--violet-6); /* #845ef7 — readable on light */
|
||||
--garden-housekeep: var(--indigo-5); /* #748ffc — already fine */
|
||||
--garden-fix: var(--teal-6); /* #20c997 — readable on light */
|
||||
--garden-build: oklch(58% 0.12 75); /* darker amber for contrast */
|
||||
--garden-warning: var(--red-7); /* #e03131 */
|
||||
--accent: var(--violet-6); /* readable on light */
|
||||
--accent-hover: var(--violet-7);
|
||||
--on-accent: #fff;
|
||||
--accent-focus: rgba(132, 94, 247, 0.25);
|
||||
--accent-subtle: rgba(132, 94, 247, 0.08);
|
||||
}
|
||||
|
||||
/* Light-mode adjustments for visual elements */
|
||||
html[data-theme="light"] .fragment[open] {
|
||||
background: color-mix(in srgb, var(--fragment-color) 8%, transparent);
|
||||
}
|
||||
html[data-theme="light"] pre {
|
||||
background: var(--surface-2);
|
||||
border-color: var(--border);
|
||||
}
|
||||
|
||||
/* ── Base ──────────────────────────────────────────────────── */
|
||||
html[data-theme="dark"] {
|
||||
background-color: var(--garden-bg);
|
||||
color: var(--garden-text);
|
||||
}
|
||||
html[data-theme="light"],
|
||||
/* also handle the initial state before JS runs:
|
||||
ASW baseof.html ships data-theme="dark" but JS may override
|
||||
to "light" after DOMContentLoaded — the default state here
|
||||
ensures no flash of wrong background if prefers-color-scheme is light */
|
||||
html:not([data-theme]) {
|
||||
background-color: var(--garden-bg);
|
||||
color: var(--garden-text);
|
||||
}
|
||||
/* Force body too — ASW sets background-color: var(--surface) */
|
||||
body {
|
||||
background-color: var(--garden-bg);
|
||||
|
|
|
|||
71
static/js/theme-toggle.js
Normal file
71
static/js/theme-toggle.js
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* 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();
|
||||
}
|
||||
})();
|
||||
Loading…
Add table
Add a link
Reference in a new issue