Add dark mode with toggle and localStorage persistence

Uses Tailwind v4 class-based dark mode with a Stimulus controller for
toggling. Respects prefers-color-scheme as default, prevents FOUC with
an inline script, and persists the user's choice in localStorage. All
views updated with dark: variants for backgrounds, text, borders,
badges, buttons, and form inputs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dan Milne
2026-03-22 00:37:58 +11:00
parent 43958f50ce
commit 3d98261a51
38 changed files with 744 additions and 636 deletions

View File

@@ -0,0 +1,27 @@
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = ["icon"]
connect() {
this.updateIcon()
}
toggle() {
document.documentElement.classList.toggle("dark")
const isDark = document.documentElement.classList.contains("dark")
localStorage.setItem("theme", isDark ? "dark" : "light")
this.updateIcon()
}
updateIcon() {
const isDark = document.documentElement.classList.contains("dark")
this.iconTargets.forEach(icon => {
if (icon.dataset.mode === "dark") {
icon.classList.toggle("hidden", !isDark)
} else {
icon.classList.toggle("hidden", isDark)
}
})
}
}