Template
Gate hardening:
- strict + noUncheckedIndexedAccess in tsconfig.app.json; fix resulting errors
- check-tokens.mjs: scan inline style={{ }} in ts/tsx, ban named colors and
rgb()/hsl()/oklch()/lab(), read multi-line values, fail on undefined var(--x)
- vitest (24 tests: overlay, icon-registry, useTimeout, token guard) wired into
npm run check; GitHub Actions CI workflow
Single-source refactors:
- new Overlay primitive owns focus trap/Escape/scroll-lock/focus-restore and
conditional aria-labelledby/aria-describedby; Dialog + Sheet are thin skins
(overlayBehavior.ts exports trapTabKey/useOverlayLifecycle for SearchPalette)
- icon-registry.ts is the one icon map: strict IconName, aliases typed, dev
throws on unknown names instead of silently rendering <Layers/>; IconMatrix
consumes the shared registry (41 curated)
- useTimeout hook replaces fire-and-forget setTimeout in DeploymentModal,
SettingsPanel, IconMatrix, CodeSample (timers die on close/unmount)
Bug fixes:
- SearchPalette: role=dialog/aria-modal, focus trap + restore, combobox/listbox
semantics, labelled input, selection clamped to results
- theme: pre-paint script in index.html (localStorage -> prefers-color-scheme ->
dark), useTheme no longer writes DOM during state init
- StatCard: direction (arrow) decoupled from trend (sentiment); latency drop
renders green "↓ -4.2ms" instead of "↑ -4.2ms"
- sidebar collapse button wired (aria-pressed + collapsed rail CSS); pattern
routing keys on patternId from library.ts, not English labels
- remove 25 dead legacy tokens (--panel*, --line*, --text-soft, --critical,
--pink, --blue, ...); migrate --bg/--text/--positive/--warning usages
- title "Northstar Design System", real README, AGENTS.md structure/theme/
overlay/registry/test docs updated; dev error sink (#dev-errors +
ErrorBoundary) so agents can read runtime errors via inspect
64 lines
2.2 KiB
Markdown
64 lines
2.2 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
npm install
|
|
npm run dev # dev server on 0.0.0.0:5173
|
|
```
|
|
|
|
## The quality gate
|
|
|
|
```bash
|
|
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
|
|
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`](./AGENTS.md) before changing anything — it documents the
|
|
token contract, the overlay/icon registries, and the parallel-subagent rules.
|