Files
design-system/README.md
T
developer d6c7464170 feat(app): add AppStateProvider for shared global settings
Central context for the settings a template app shares instead of prop
drilling: theme, viewMode, sidebarCollapsed and the search palette, with
the ⌘K/Ctrl+K shortcut moved out of App.

- settings persist on user action only (an effect-written theme would
  freeze the OS preference for users who never toggled)
- theme still boots from the <html data-theme> attribute the pre-paint
  script set; viewMode mirrors to data-view-mode as the audience-preset
  hook and deliberately gates nothing yet
- Topbar: viewMode segmented control, theme toggle and search now read
  the context; useAppState throws outside the provider
- tests/appState.test.tsx: defaults, persistence, rehydration, garbage
  storage values, ⌘K shortcut
2026-09-15 18:34:22 +00:00

2.3 KiB

Northstar Design System

A token-driven design system showcase built for AI-assisted development workflows. React 19 · Vite 8 · TypeScript (strict) · Vitest · oxlint.

Quick start

npm install
npm run dev        # dev server on 0.0.0.0:5173

The quality gate

npm run check

One command, four gates, in order:

  1. oxlint — lint over every source file.
  2. scripts/check-tokens.mjs — the token contract: bans hardcoded colors (hex / named / rgb() / hsl() / oklch() / lab()), px font sizes and undefined var(--x) references — in both CSS files and inline style={{ … }} objects. Values may span lines; comments are ignored.
  3. vitest run — unit + component tests (tests/).
  4. tsc -b && vite build — strict typecheck, then production build.

CI runs the same gate on every push and PR (.github/workflows/ci.yml).

Design tokens

src/tokens.css is the single source of truth. Every color, font size, spacing, radius and shadow goes through a var(--token) — components never hardcode values. Themes are plain CSS: :root[data-theme='light'] / .light and :root[data-theme='dark'] / .dark, with a pre-paint script in index.html that applies the saved (or OS-preferred) theme before first paint.

The global density knob is --root-font-size — one line scales the whole app.

Layout

src/
  tokens.css        ← lab() design tokens, dark & light themes
  index.css         ← fonts, token import, base resets
  utils.css         ← token-compliant utility classes
  App.css           ← application showcase styles
  app/              ← AppStateProvider + useAppState(): theme, viewMode, sidebar, ⌘K search
  components/
    ui/             ← composable primitives (Overlay, Dialog, Sheet, Tabs, Alert, …)
    icon-registry.ts← the one icon name → lucide component map
    examples/       ← reusable patterns (MetricsDashboard, SettingsPanel, …)
    dev/            ← ErrorBoundary + dev error sink (#dev-errors)
  utils/            ← cn(), useTimeout()
tests/              ← vitest suites (jsdom)
scripts/
  check-tokens.mjs  ← token contract guard

For agents

Read AGENTS.md before changing anything — it documents the token contract, the overlay/icon registries, and the parallel-subagent rules.