Design System

Audit & governance

The results of the full design-system audit — what was inspected, what was found and what was corrected — together with the rules for contributing to the system.

Changelog

Controlled changes to the system, newest first.

  • V2.0
    • Standardized every component family against the V2 rules, from buttons through data visualization.
    • Cross-component QA: zero axe violations and zero horizontal overflow on every route at desktop, tablet and mobile, in light and dark.
    • Keyboard QA: guarded dialogs route Escape through the unsaved-changes guard, and every scroll region is reachable.
    • RELEASE BASELINE (frozen): 58 reference patterns covered — 46 exact, 12 with variants, 0 partial, 0 missing, 0 accidental duplicates. Visual, accessibility, responsive and compliance QA passed with no genuine defects. No new components, tokens or visual changes after this point; future screens consume these canonical components.
  • V1.1
    • Changed the design system typography to Nunito as the unified font family.
    • No other visual system changes were made.
  • V1.0
    • First frozen release: tokens, primitives, composites, patterns, reference screens and documentation.

V2 cross-component QA

The V2 quality pass. Every documentation and reference route was measured at desktop, tablet and mobile, in light and dark, with axe-core and keyboard-only interaction. Every listed issue is fixed; no component was redesigned and no new token was introduced.

QA areas with the method used, what it surfaced and the correction applied.
AreaHow it was checkedWhat it surfacedCorrection
Responsive behaviourEvery route measured at 1280px, 834px and 390px for horizontal page overflow, clipped controls and collapsed layouts.Search inputs collapsed to 54px inside narrow filter rows, ToggleGroup and ButtonGroup pushed 46px of page overflow, and Field could not shrink inside grid parents.Narrow search slots go full width before flexing, grouped controls wrap and carry min-w-0, and Field shrinks instead of forcing its parent wider. Overflow is now 0 on every route at all three widths.
Accessibility (WCAG 2.2 AA)axe-core run against every route at all three widths, in light and dark, using the wcag2a / 2aa / 21aa / 22aa rule sets.Unlabelled mobile search, invalid aria-readonly on picker triggers, an out-of-list ListHeader, tabs without panels, non-focusable scroll regions, unnamed chart symbols and an unnamed slider thumb.Labels added, picker state moved to aria-disabled plus data-readonly, list semantics corrected, every tab wired to a panel, scroll regions made focusable and labelled, chart plots excluded from the accessibility tree behind their data-table alternative, and the slider thumb named. Zero violations remain.
ContrastComputed ratios for text, disabled text, brand text on dark surfaces, semantic fills, trend indicators and chart legends in both themes.Brand text on dark surfaces at 3.52:1, disabled text below the readability bar on disabled surfaces, and subtle trend / legend states diluted by opacity.Brand text on dark surfaces uses the subtle-foreground role, disabled text tokens moved to values that clear 4.9:1 in both themes, and subtle states use semantic foregrounds instead of opacity.
Keyboard & focusDialogs, drawers, menus, tabs, tables and charts driven by keyboard only: Tab, Enter, arrow keys and Escape, checking focus order, trapping and restoration.A guarded form dialog swallowed Escape, leaving keyboard users with no exit, and several scrollable regions could not be reached by Tab.Escape and outside click now route through the same unsaved-changes guard as Cancel, and every scroll region is focusable with a visible ring. Every interactive control paints a focus style.
Touch targetsInteractive controls measured against WCAG 2.5.8 at mobile width.Chip and user-select dismiss buttons and the input-group stepper sat below 24px.All three raised to the ds-target minimum without changing field heights.
Content lengthsTitles, labels, cells and metadata replaced with very long unbroken strings across cards, tables, lists, forms and charts.Long single words could push card text past its container.Card title, description and content wrap long words; tables keep their horizontal scroll region; truncated text keeps its tooltip.
Motion & tokensStatic scan for raw hex, rgb(), hsl(), arbitrary z-index and one-off font values, plus a reduced-motion render pass.No raw values outside the token definitions; nothing animated under prefers-reduced-motion.No changes required.

Design system guidelines

Read this before adding to the system. Consistency, accessibility, reusability and token governance come before new surface area.

Do

  • Reuse existing components.
  • Use semantic tokens.
  • Compose components.
  • Follow the spacing scale.
  • Use approved typography.
  • Maintain accessibility.
  • Prefer existing patterns.

Don't

  • Hardcode colours.
  • Create duplicate components.
  • Add arbitrary spacing.
  • Create one-off variants.
  • Use colour as the only status indicator.
  • Override tokens locally without a valid reason.

Design system audit

Fifteen categories inspected across the token layer, every component and every documentation route. 1 category still needs attention; the rest pass. Only categories that were actually inspected are listed.

Audit results by category, with the checks performed, the issues found and the corrections applied.
CategoryStatusInspectedIssues foundCorrections made
TokensPASSEvery file under src/design-system scanned for hex, rgb(), hsl(), arbitrary px/rem, arbitrary radius, shadow and duration values.One arbitrary shadow on the sticky table header and two arbitrary z-index values (table header, timeline marker).Sticky header now uses border-b + border-border-default; both z-[1] usages replaced with the scale value z-1.
ColoursPASSLocked primitives verified against the specification: blue-500 #006DEA, yellow-500 #F9C846, the full neutral 0–950 scale and the success / warning / error / info 100 / 500 / 700 ramps.Two components tinted a hover state with a raw black alpha (Alert dismiss, Banner dismiss).Both now derive the hover wash from the inherited foreground (bg-current/10), so solid variants stay on their own semantic foreground.
ContrastNEEDS ATTENTIONComputed WCAG 2.2 ratios for body, heading, secondary, tertiary and disabled text, links, primary and destructive buttons, all four semantic solid and subtle pairings, badges, inputs, focus ring, table headers, navigation active state and both glass surfaces, in light and dark.Disabled text sat at 2.34:1 in light and 1.93:1 in dark — exempt under WCAG but below the system's own readability bar.--color-text-disabled raised to dedicated shades in both themes (#5c6a7e light at 5:1, #7c8798 dark at 4.9:1) — stronger than neutral-500, which would have landed at 4.34:1 / 3.07:1. Everything else passes: text ≥ 4.76:1, white on every semantic -500 ≥ 4.60:1, accent solid 11.37:1 with dark text.
TypographyPASSFont families, weights (400/500/600/700) and the full scale from display-xl to caption and code, plus a scan for arbitrary text sizes and line heights.None — no component declares a font size outside the scale.None required. Nunito is the single family across display, headings and body/UI; base body 16px.
SpacingPASSButtons, inputs, forms, cards, tables, navigation, dialogs, drawers, layout primitives and the documentation shell checked against the 4px scale.None — no off-scale values such as 13px, 18px, 22px or 27px found.None required.
RadiusPASSRounding on buttons, inputs, cards, dialogs, badges, popovers and menus.One rounded-[inherit] in ScrollArea, which intentionally inherits its parent's token-driven radius rather than introducing a value.Kept — it resolves to a token, not a literal. Controls use radius-md, surfaces radius-lg, badges radius-full.
ElevationPASSAll shadow usage across surfaces and floating overlays.The arbitrary sticky-header shadow noted under Tokens was the only competing shadow style.Replaced with a border. Remaining shadows are shadow-xs/sm/md/lg plus the single approved overlay shadow.
MotionPASSduration-fast 150ms, duration-normal 200ms, duration-slow 300ms and their use in dialogs, drawers, popovers, dropdowns, toasts, hover and loading states; reduced-motion behaviour.None — no component hardcodes a duration.None required. prefers-reduced-motion collapses transitions system-wide.
ComponentsPASSEvery exported component name checked for duplicates and near-duplicates; prop signatures reviewed for styling booleans.No duplicates (no PrimaryButton / StatusBadge / CustomInput style forks). Remaining boolean props — showValueLabel, showCount, showFirstLast — are behavioural, not visual.None required. Visual variation stays on variant / size / appearance with CVA.
AccessibilityPASSKeyboard paths, focus-visible styling, ARIA wiring, semantic elements, form labelling, error messaging, touch targets, reduced motion and tab order across primitives, overlays, navigation, data and forms.Disabled-text legibility (fixed above) was the only finding; no colour-only status indicator found — every status pairs an icon or text with its colour.Contrast fix applied. Interaction and focus behaviour left to the Radix primitives already in use.
FormsPASSLabels, helper text, required and optional indicators, error / success / disabled / read-only states, field and section spacing, action rows, and the Complete form example composition.None — the example composes only production components and demonstrates each state.None required.
OverlaysPASSBlur, transparency, border, shadow, opaque fallback and contrast for Popover, DropdownMenu, ContextMenu, HoverCard, CommandMenu, Toast, Drawer, Dialog and AlertDialog in both themes.None — glass is scoped to floating, contextual surfaces.None required. Drawer keeps the subtle 8px treatment; Dialog and AlertDialog stay solid.
ResponsivePASSForms, tables, navigation, dialogs, drawers, cards, layouts, page headers and filter bars at mobile, tablet, desktop and large-desktop widths.None — filters collapse into a drawer, tables scroll within their container, headers reflow rather than shrink.None required.
Dark modePASSText, surfaces, borders, buttons, inputs, badges, alerts, tables, navigation, overlays, glass surfaces and focus rings under .dark.Disabled text was too dim (fixed above).Token updated. Dark remains a designed palette, not an inversion of light.
DocumentationPASSEvery documentation route for description, purpose, when to use / not to use, variants, sizes, states, accessibility notes, responsive notes and live examples.Governance rules and audit results were not documented anywhere.This page adds both, alongside the existing per-component documentation.