Template
- tokens.css: full token layer (type scale rem-based, palette, spacing, radii) - App.css rebuilt token-driven; zero hardcoded colors/px font sizes - readability preset: --root-font-size 112%; button matrix scrolls when narrow - App.tsx split into real components (Hero, CodeSample, RightRail + reflow) - light theme via [data-theme=light] overrides; topbar sun/moon toggle persisted - scripts/check-tokens.mjs + npm run check (lint, token guard, tsc, build) - AGENTS.md: token contract, check gate, preview workflow
2.8 KiB
2.8 KiB
Northstar Design System — agent handbook
React 19 + Vite 8 + TypeScript design-system showcase. Dark-first, token-driven UI with a light theme.
Commands
| Task | Command |
|---|---|
| Dev server | npm run dev (vite.config.ts pins 0.0.0.0:5173) |
| Full gate: lint + token contract + typecheck + build | npm run check — run before declaring any change done |
| Lint only | npm run lint (oxlint) |
Sandboxed worker dev flow
vite.config.tsallows*.preview.k6n.net; expose port 5173 viarepo_instance_exposefor a preview URL.- Removing
allowedHostsbreaks preview ingress with a 403 ("host not allowed"). Don't.
Design tokens — the contract
- Single source of truth:
src/tokens.css. Every font size, color, spacing, radius, and shadow color insrc/App.csscomes from a token. The guardscripts/check-tokens.mjs(innpm run check) bans hardcoded hex colors, px font sizes, and rawrgba()in application CSS — new colors go in as tokens, accent washes usecolor-mix(in srgb, var(--accent) N%, transparent). - Typography scale (
--text-3xs…--text-2xl,--text-hero) is rem-based on a 9→28px grid. Longform body--text-md, buttons/nav--text-xs, meta/eyebrows--text-2xs/--text-3xs. - Global density knob:
--root-font-size(default112%readability preset, baseline 16px =100%). One line scales every token-driven size app-wide; spacing tokens follow. - Theming: components read only
var(--*)and never know the theme.:root[data-theme='light']in tokens.css holds the daylight palette. Toggle =document.documentElement.dataset.theme(Topbar's sun/moon button, persisted inlocalStorage['ns-theme']). Adding a third theme = one more token block. - "Make the small text a bit larger" = bump
--text-xs/--text-2xs. "Soften a surface" = its token. No grep, no per-component edits.
Structure
src/
tokens.css ← design tokens + light theme (edit this first)
index.css ← fonts, tokens import, base resets
App.css ← all component styles (token-driven, plain CSS)
App.tsx ← page composition only
components/ ← one component per file, readable multi-line JSX
Topbar.tsx ← owns the theme toggle (useTheme inside)
Hero.tsx, CodeSample.tsx, RightRail.tsx, ButtonMatrix.tsx,
Sidebar.tsx, Section.tsx, FormField.tsx, TokenGrid.tsx,
MarkdownRenderer.tsx, CodeEditor.tsx, Button.tsx, Icon.tsx
data/library.ts ← demo content for the showcase
scripts/check-tokens.mjs ← token contract guard (part of npm run check)
Iteration workflow for visual changes
- Change the token (or component markup) — never a literal.
npm run checkuntil green.- Verify live: dev server + preview URL; screenshot at desktop width; toggle light/dark via the topbar button.