Files
rippr/docs/ui-redesign/UI-08-theme-modern-professional-dark.md
uhryniuk 822003ed38 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.
2026-08-23 18:25:35 -05:00

5.6 KiB

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.