Files
ccs/ui/docs/design-decisions.md
T
Tam Nhu Tran 1a2fd848f0 refactor(ui): revert home/cliproxy migrations and restructure design system
User feedback caught a Phase 2 mistake: forcing home and cliproxy into
a one-size-fits-all PageShell + PageHeader chrome regressed density on
both pages.

- home: original 1-row hero (logo + title + version + 4 inline stats)
  was split into PageHeader + KpiRow, doubling vertical footprint
- cliproxy: original rail-anchored brand was duplicated by a top
  PageHeader, stealing ~80px from the 3-pane body

Resolution: revert both pages to dev-branch state, then restructure
ui/docs/design-system.md to extract THREE identity-strip patterns from
the canonical references rather than imposing one:

  1. HeroBar       (1-row dense)             -> home pattern
  2. Rail-anchored (no top chrome)           -> cliproxy pattern
  3. PageHeader    (title + description)     -> health pattern

Health stays migrated -- the Monitor archetype + PageHeader is a real
improvement there because the gauge + KPI row + group cards don't fit
the HeroBar pattern.

Future page migrations adapt to whichever identity-strip pattern fits
the page's content shape, not the other way around. design-decisions.md
gets a v1.1 revision row capturing the rationale.
2026-04-25 13:34:43 -04:00

3.0 KiB

Design System — Decisions Log

The 6 open questions from the brainstorm phase, resolved before implementation.

# Question Decision Rationale
1 Storybook vs in-app /_styleguide In-app /_styleguide Zero-config, lives in the repo, gated by import.meta.env.DEV. Storybook is a heavy second build pipeline for marginal benefit at this scale.
2 Archetype B name (Monitor vs Dashboard) Monitor "Dashboard" is the whole product. "Monitor" matches existing health/analytics framing and avoids overloading the term.
3 JsonPane editability scope Read-only by default, opt-in editable prop Cliproxy is the only page that genuinely needs in-pane editing today. Opt-in keeps the API safe for codex/copilot/cursor (read-only).
4 Health terminal aesthetic Keep as MonitorCard variant="terminal" Preserves the ccs health --watch feel. Implemented as opt-in variant, not a separate primitive.
5 i18n key namespace convention Per-page namespaces (pages.<name>.*) + shared (common.*) Current i18n already uses ad-hoc per-page keys; this just formalizes it. Primitives use common.* so they're translation-stable across pages.
6 SectionRail activation Scroll-spy via IntersectionObserver Preserves long-form config feel + shows all validation errors at once. Click-to-switch hides errors in inactive sections, which is worse UX for forms.

v1.1 revision (2026-04-25) — identity-strip patterns

Phase 2 attempted to migrate home and cliproxy to a one-size-fits-all PageShell + PageHeader chrome. Both regressed on density:

  • home had a single-row hero (logo + title + version + 4 inline stats) — splitting it into a stacked PageHeader + KpiRow doubled vertical footprint and lost scannability
  • cliproxy had identity in the left rail — adding a top PageHeader duplicated branding and stole ~80px from the 3-pane body

Resolution: the design system is restructured around three identity-strip patterns extracted from the existing canonical references:

# Pattern Reference When
7a HeroBar (1-row dense) pages/home.tsx Dashboard pages with ≤4 hero stats
7b Rail-anchored identity (no top chrome) pages/cliproxy.tsx Multi-entity Config pages where rail carries brand
7c PageHeader (current) pages/health.tsx Pages where description / status info is non-redundant

Phase 2's home + cliproxy migrations are reverted. Health stays migrated (Monitor archetype + PageHeader works there). Future page migrations adapt to whichever pattern fits, NOT the other way around.

Why bottom-up: the existing references already proved their patterns work in production. The job of the design system is to formalize what works, not impose what should.


How to revisit

If a decision turns out wrong in practice, update this doc and bump the affected primitive — don't silently drift. Each row above should be appended with a "Revised: · " line if changed.