feat(theme): two-layer theme + accent picker, app-wide (MAPPS-259) #262
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/MAPPS-259-theme-picker"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements MAPPS-259: a two-layer theme picker for the entire Mokosh SPA.
What it adds (3 commits):
Phase 2 (named palettes like Sepia/Midnight/Forest) is deferred and purely additive on the same token layer.
Verified in the dev container: cargo check --target wasm32-unknown-unknown, cargo test (146 passed, incl the accent AA suite), cargo clippy --all-targets -D warnings, just css-build, and the theme-token guard.
Depends on mokosh-server PMS-410 (PR !301) for the per-user fields; merge/deploy that first so the account sync has somewhere to read/write.
#MAPPS-259
Add a semantic CSS-variable token layer in input.css mapped through Tailwind v4 `@theme inline` (bg-surface, bg-surface-2, text-content, text-muted, border-line, bg-accent, text-on-accent, ring-accent, bg-accent-{50..950}); light values on :root, dark on .dark, default Teal accent. Components now read tokens instead of hardcoded colors. Add modules/theme: a curated 14-accent catalog (canonical ramp + per-base fill/on-accent) plus WCAG contrast math. Tests assert every accent meets AA on both light and dark bases, so the picker's auto-fit-shade guarantee holds and no curated swatch locks. Extend hooks/theme.rs to persist and apply the accent (inject the ramp/fill/on-accent as inline <html> CSS vars; base surfaces stay class-driven), with current_accent/set_accent/current_is_dark. Add the shared ThemePicker component (segmented base mode, locked phase-2 palette tiles, accent grid with a runtime contrast lock, live preview) and a SwatchIcon. Surface it from a top-bar swatch modal next to the bell and from a new Settings > Appearance page (Route::SettingsAppearance); supersede the profile Light/Dark radios with a pointer to the picker. Base mode is Light/Dark/System now; named palettes are deferred (phase 2). Per-user account sync of the preference is tracked separately (PMS-410). The ~38-file component migration off hardcoded colors and a lint guard follow in subsequent commits. #MAPPS-259 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>Migrate ~37 SPA files (~510 class strings) from hardcoded neutral grays and the brand blue to the semantic token utilities (bg-app, bg-surface, bg-surface-2, bg-raised, text-content, text-muted, text-subtle, border-line, bg-accent, text-on-accent, text-accent, border-accent, ring-accent, bg-accent-{50..950}), so a theme or accent change recolors the entire app live. The nav chrome (sidebar + top bar) now follows the base mode and the active nav indicator uses the accent. Migrate the shared style layer in input.css to tokens too: .card, .btn-primary/secondary, .badge-blue/gray, .table-header/cell, form inputs, the focus ring, and the global scrollbars. Keep semantic state colors (red danger, green success, yellow/amber/orange warning), status and data-viz palettes, overlay scrims, and the public marketing hero as intentional exceptions. The few genuine neutral exceptions (event-type dot palette, a neutral status-bar fill, the two overlay scrims, the marketing CTAs) are annotated `// theme-guard-allow`. Add scripts/check-theme-tokens.sh and a `just check-theme-tokens` recipe (wired into `just check`) that fails on new hardcoded neutral color classes outside the allowlist, so coverage stays complete over time. Verified in the dev container: cargo check (wasm32), cargo test (146 passed), cargo clippy --all-targets -D warnings, just css-build, and the token guard all pass. #MAPPS-259 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>