5.8 KiB
Design-system architecture
ARC-14; PRES-E08 and all consumers, especially PRES-J05, PRES-C06–PRES-C09 and PRES-S03. Retain MUI/Emotion, MUI icons and existing theme providers. No evidence justifies a competing library or state/router replacement.
Foundation and ownership
theme.ts already supplies palettes, typography, custom shadows, CSS variables, breakpoints and MUI overrides. themePrefs/themeBootstrap/ThemeProvider preserve initial paint and light/dark/system selection. AppShell currently has separate hardcoded navy/indigo constants; migrate them to semantic theme roles deliberately after shared-state contrast proof.
Use the existing theme as the token authority; page CSS variables may alias it. No parallel JSON token compiler, token package or generic design-system runtime. Typed augmentation only for small roles the current theme cannot express. Existing MUI Button/TextField/Select/Dialog APIs remain; do not wrap every primitive merely to rename it.
Token proposal
Values below are working architecture proposals, to validate in P4 fixtures. Final brand hue/logo is not selected.
| Family | Planned roles / scale | Usage |
|---|---|---|
| Brand | primary main/on-primary, interaction hover/selected/focus | One hue; keep current #5B5BD6 as provisional continuity, not final approved identity |
| Text | primary, secondary, muted, disabled, inverse, link | Explicit foreground/background pairs; avoid arbitrary opacity for required copy |
| Surfaces | canvas, content, subtle, raised, overlay, navigation | Light neutral canvas with content layer; dark layered neutral surfaces rather than inversion |
| Borders | subtle separator, control boundary, strong/selected, error, focus | Separator need not meet same contrast as an essential form boundary |
| Status | info/success/warning/error plus neutral; each background/text/icon/border | Pipeline text and icon alongside color; no identical semantic mapping assumed across unrelated domains |
| Typography | body 14/20, dense/support 13/18, caption 12/16; section 18/24, page 28/34 desktop and 24/30 phone; weights 400/600/700 | Preserve Archivo/system stack and æ/ø/å; numerals tabular where useful; rem sizing, no fixed-height clipping |
| Spacing | 4, 8, 12, 16, 24, 32, 48 px equivalents | Related controls vs sections; reuse existing page/card/gap variables |
| Radii | control 8, panel 12, overlay 16; pill only for small status/tag | Subtle distinction without every surface being a nested rounded card |
| Elevation | flat/base, subtle raised, overlay | Borders/surface contrast carry dark-mode depth; no glow/glass dependency |
| Motion | immediate feedback, ~120–180 ms disclosure, ≤220 ms overlays as proposal | No animated metric counters; reduced-motion removes nonessential movement |
| Layout | existing responsive breakpoints; page max-width by reading/data/editor mode | Reading content bounded, tables/editor can use width; no one-width-fits-all |
| Density | Comfortable/Compact spacing variants | Application surfaces only; separate from CV document density |
Retain existing heading semantics separately from style variants: a page can be h1 with page-title styling rather than inheriting a marketing hero size. Do not change font loading/hosting or add a typeface dependency in foundations.
Light and dark
Choose and test both schemes as first-class palettes. Navigation can retain a distinct tonal surface while honoring mode and contrast; no assumption that current fixed navy is inaccessible everywhere. Dark hover/selected/focus layers need visible borders/outlines without washing out content. Avoid gradients and glass in core product surfaces; any existing public marketing treatment can wait for its own migration.
One semantic role may need different foregrounds in different modes. Never compute on-primary/alert text by blindly lightening/darkening one color and assume it meets contrast. P4 explicitly verifies actual rendered pairs, including disabled-adjacent explanations and focus indicators. Prefer outline + offset for focus over low-opacity shadow alone.
Component variants and state contract
Use contained primary for one main action, outlined secondary and text tertiary. Destructive confirm is explicit and labelled; red is not the default presentation of ordinary rejection outcomes. Pro/AI unavailable controls need visible reasons and manual alternatives, not only disabled opacity.
Buttons, inputs, selects/comboboxes, checkboxes, switches, tabs, table headers/rows, badges, alerts, menus, dialogs and drawers need default/hover/focus/selected/disabled/error/loading definitions. Focus is distinguishable from selected. Form label/error/help IDs stay linked. Placeholder is a hint, not a label.
Empty/error/loading states use the existing ViewStateNotice and MUI primitives with consistent semantics. Keep old content while refreshing where the owner currently supports it, but clearly mark a refresh failure; never replace an error with fake zero metrics.
Page primitives
Minimal set: PageHeader (heading/description/actions), WorkspaceHeader (identified resource/scope/state), PageSection (optional heading, no mandatory card), and a small data/reading/editor width contract. Reuse existing Shell/SectionCard patterns only where source repetition warrants extraction. See Component architecture for owners and explicit deferred additions.
Phase 4 acceptance
First establish semantic state pairs and visible focus with a loaded representative form/table/alert fixture in both schemes and locales. Keep current brand and route tree. Later adjust typography/layout primitives only after responsive checks. Test meaningful interaction/contrast, not snapshots of CSS or token names. No visual identity sign-off, accessibility certification or production release is implied by this planning package.