UI redesign: 8 tickets from the Stitch export analysis

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.
This commit is contained in:
2026-08-23 18:25:35 -05:00
parent 95a88fa383
commit 822003ed38
9 changed files with 823 additions and 0 deletions

View File

@@ -0,0 +1,96 @@
# 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.