← Corpus / dididecks-ai / sitemap
runtime/mode-switcher — TS factory createModeSwitcher({client, defaultMode, respectSystemPreference}); per-client localStorage namespace
Three-mode state machine factory, namespaced to `{client}:mode` in localStorage and installed as a `window.modeSwitcher` singleton.
- Path
- sitemap/runtime/mode-switcher.md
- Authors
- Michael Staton
runtime/mode-switcher
Why per-client namespace
Multiple decks deploying on overlapping preview domains (e.g. *.vercel.app) collide on localStorage keys. The chroma-decks:mode vs humain-vc-decks:mode namespace prevents accidental cross-talk where opening one preview deck changes another’s persisted mode.
Singleton discipline
createModeSwitcher() returns the existing window.modeSwitcher if one is already installed — multiple ModeToggle instances on the same page call it on mount, but only the first call actually constructs. Subsequent calls just return the existing singleton. This is what lets a landing page with one ModeToggle plus a scroll-page mounted as a fragment with another ModeToggle share consistent state.
Default-mode + prefers-color-scheme
defaultMode is the per-client brand canon (light for chroma + humain; could be dark for a darker-canon brand). respectSystemPreference is opt-in — off by default because brand canon usually beats OS preference (a vibrant-brand site looking dark just because the user’s MacBook is in dark mode is wrong by default).
When respectSystemPreference: true AND no stored mode AND prefers-color-scheme: dark matches → mode boots to dark instead of defaultMode.
Status
- ✅ Shipped — humain consumes via ScrollDeckPage → ModeToggle; chroma consumes via local shim file
Related
- [[../components/ModeToggle]] — the UI surface that invokes this factory
- [[../components/ScrollDeckPage]] — bundles ModeToggle (and therefore this runtime)
- [[../../agent-skills/theme-system/SKILL.md]] — three-mode theme architecture
- [[../../plans/Lift-Chroma-Decks-Generic-Code-into-Shared-Shell]]