Same shape as docs/v3/: Goal/Context/Design/Implementation/Acceptance/Tests/Risks/Out-of-scope, written before implementing. UI-01: persistent 4-tab shell (StatefulShellRoute) replacing the current push/pop stack rooted at Record, with a single shared background map dimmed behind every tab and no header anywhere. UI-02: animated skeleton map for the no-cache/no-network case, since the map is now a permanent background presence rather than opt-in per screen. UI-03: shared GlassPanel/FloatingPill/PulsingLocationMarker component kit. UI-04: draggable, resizable HUD telemetry widgets with a Settings visibility toggle -- split out from the screen redesign itself since it's a genuinely separate piece of engineering (a small widget-layout system, not a reskin). UI-05: Map HUD/Record screen redesign -- the design north star every other screen ticket restyles toward. UI-06: Plan & Route Planning -- correct in principle, explicitly restyled toward UI-05 rather than copying the Stitch export's drifted styling. UI-07: Rides History -- live dimmed map background (not the mockup's static image), search/filter, real per-ride map thumbnails, and real distinct summary stats (fixing the export's 4-identical-cards generation artifact). UI-08: theme migration to Modern Professional Dark, superseding V3-16's safety-orange direction. README documents the dependency order, and two categories worth keeping separate: what was named explicitly by the person commissioning this (map-on-every-tab, no header, offline skeleton, customizable HUD) versus what the mockups themselves got inconsistent (nav icon count, duplicate summary cards, wrong active-tab highlight) and should not be copied as intentional.
97 lines
5.6 KiB
Markdown
97 lines
5.6 KiB
Markdown
# UI-08 — Theme migration to Modern Professional Dark
|
|
|
|
**Depends on** nothing · **Size** S · **Status** Not started
|
|
|
|
## Goal
|
|
Replace `theme.dart`'s current safety-orange palette with "Modern Professional Dark" —
|
|
the design system actually backing every fetched Stitch screen — so every screen ticket
|
|
in this set has one settled palette to build against instead of guessing or patching
|
|
colors per screen.
|
|
|
|
## Context
|
|
V3-16 (last shipped) deliberately kept and refined the original safety-orange-on-warm-
|
|
charcoal identity, with an instrument-blue tertiary for reference readings. That work is
|
|
good and tested, but it is **not** the palette the Stitch mockups use — confirmed by
|
|
hex-matching every color in the four fetched screens' HTML against all three design
|
|
systems in the Stitch project (`docs/design/stitch-export/README.md`). If this redesign
|
|
ships, V3-16's direction is superseded, not extended.
|
|
|
|
Full spec: `docs/design/stitch-export/design-system-modern-professional-dark.md`.
|
|
|
|
## Design
|
|
- **Ground:** deep dark gray `#0a0a0c` (not pure black — "a true premium feel without
|
|
the harshness of pure black," per the design system's own doc), stepped up through
|
|
`#131313` (surface) and `#16161a` (cards) for elevation.
|
|
- **Primary:** Professional Blue — rendered as `#4090fe` (container) / `#aac7ff`
|
|
(on-dark-surface primary) / `#002f64` (on-primary text). This replaces safety-orange as
|
|
*the* accent everywhere: live telemetry, active nav indicator, primary buttons,
|
|
the user's own location dot.
|
|
- **Secondary/tertiary:** muted slate-blue (`#aec7f6`/`#2e476f`) and a warm orange
|
|
(`#ffb68c`/`#e3711f`) reserved for tertiary accents (the design system's own spec
|
|
doesn't define a strict "reference vs. live" split the way V3-16's tertiary did —
|
|
decide during implementation whether to keep that instinct using this palette's
|
|
secondary color, or drop it; either is defensible, but pick one and apply it
|
|
consistently rather than leaving it ambiguous per screen).
|
|
- **Typography:** Inter, exclusively, for every role (headline/body/label) — this drops
|
|
the multi-font split V3-16 and the original theme used (monospace for numbers via
|
|
`monoDigits` is a separate, orthogonal decision from V3-16 worth keeping regardless of
|
|
which color palette wins, since "digits must not jitter" is a real constraint, not a
|
|
branding choice — retain `monoDigits` layered under Inter-family theming).
|
|
- **Shape:** 8px rounding (`ROUND_EIGHT`), up from the current 4px.
|
|
- **Depth:** tonal layering + a soft blue glow on elevated/active elements, no shadows —
|
|
matches V3-16's existing "no shadows, translucency for depth" instinct, just with a
|
|
different accent color for the glow.
|
|
- **Contrast:** the design system's own doc claims AAA-level contrast for functional
|
|
text against the dark backdrop — verify this the same way V3-16 did (a
|
|
`contrastRatio()` helper and real assertions), don't take the claim on faith.
|
|
|
|
## Implementation
|
|
1. Update `theme.dart`'s `ripprColors`/`ColorScheme` to the Modern Professional Dark
|
|
values (ground, surface, cards, primary/secondary/tertiary, outline).
|
|
2. Update `bodyFont`/`headlineFont`/`labelFont` to Inter throughout; keep `monoDigits` as
|
|
a distinct style applied specifically to numeric displays, unchanged in spirit from
|
|
today.
|
|
3. Update `roundness` usage (button/card corner radii) from 4px to 8px.
|
|
4. Re-run V3-16's `contrastRatio()` assertions against the new palette; adjust any color
|
|
that fails AA before shipping, exactly as V3-16 did for the palette it replaces.
|
|
5. Decide and document the reference-vs-live color convention (see Design) rather than
|
|
leaving V3-16's tertiary-for-reference-readings instinct undecided under the new
|
|
palette.
|
|
6. **Mounted mode (V3-05) needs its own pass**, not an automatic inheritance — it's a
|
|
separate high-contrast daylight theme with its own palette, tuned against a real
|
|
sunlight/visor constraint. Confirm it still holds up in spirit (still legible, still
|
|
AA-compliant) under the new brand direction; V3-13's real-ride verification is still
|
|
the only way to confirm the *actual* sunlight legibility claim, same caveat V3-16
|
|
already recorded.
|
|
|
|
## Acceptance criteria
|
|
- [ ] `ripprColors` matches Modern Professional Dark's token values
|
|
- [ ] Every screen using `Theme.of(context).colorScheme` picks up the new palette with
|
|
no per-screen hardcoded color left over from the old theme
|
|
- [ ] `contrastRatio()` assertions pass against the new palette (AA normal/large, same
|
|
thresholds V3-16 established)
|
|
- [ ] `monoDigits` still applies to every numeric display
|
|
- [ ] Mounted mode re-verified against the new brand direction
|
|
|
|
## Tests
|
|
- All of V3-16's `theme_test.dart` contrast assertions, re-pointed at the new color
|
|
values, still pass
|
|
- The existing black-on-black regression guard (`text is legible against the dark
|
|
ground`) still passes
|
|
- Widget: a representative sample of screens render with the new palette (no leftover
|
|
hardcoded orange/old-tertiary-blue literals)
|
|
|
|
## Risks
|
|
- **Regressing the black-on-black guard is the named risk V3-16 itself called out** —
|
|
this ticket touches the same `textTheme`/`bodyColor`/`displayColor` wiring that bug
|
|
came from originally. Do not remove the explicit color-naming discipline while
|
|
restyling.
|
|
- Grep for hardcoded hex literals from the old palette (`0xFFFF5722` and friends) across
|
|
the UI layer before considering this done — a few call sites (e.g. `RideMap`'s speed
|
|
gradient) reference specific hex values directly rather than through the theme, and
|
|
those need a deliberate decision, not an accidental miss.
|
|
|
|
## Out of scope
|
|
Any screen-specific redesign (UI-05/06/07) — this ticket only changes the token layer
|
|
those screens then build against.
|