Dark Mode
- Include
ThemeScriptbefore your content to prevent FOUC:
@layout.Base(layout.DefaultPageProps()) { @layout.ThemeScript("") {@content}}- Add the
@custom-variantdirective in your CSS:
@import "tailwindcss";@custom-variant dark (&:where(.dark, .dark *));- Optionally add a
ThemeToggle:
@layout.ThemeToggle("Toggle theme", "")How It Works
Section titled “How It Works”ThemeScriptruns before first paint, readslocalStorage, and adds the.darkclass to<html>.color-scheme: lighton:root,color-scheme: darkon.dark— native form controls render correctly in both modes.ThemeTogglesyncs across all instances on the page viaquerySelectorAll.
Color Convention
Section titled “Color Convention”| Context | Light | Dark |
|---|---|---|
| Semantic background | bg-blue-600 |
dark:bg-blue-500 |
| Semantic text | text-blue-600 |
dark:text-blue-400 |
| Neutral text | text-gray-500 |
dark:text-gray-400 |
Every neutral and semantic color class has a dark: variant — enforced by regression tests (TestDarkModeCompliance, TestDarkModeSemanticColors).
LocalStorage Guard
Section titled “LocalStorage Guard”ThemeScript and ThemeToggle both wrap localStorage access in try/catch to handle Safari private mode (QuotaExceededError).