Template
4.5 KiB
4.5 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 comes from a token. The palette is defined in modern CSS Color 4lab(...)color space:- Dark theme (
.dark,[data-theme='dark']): Pitch black base (lab(0% 0 0)), deep cards (lab(.903296% 0 0)), radiant electric mint/cyan primary (lab(89.9321% -47.9163 -15.7303)), vivid destructive (lab(54.5811% 71.684 50.9279)), chart colors 1–5, and subtle dot grid (--dot-color). - Light theme (
:root,[data-theme='light']): Pure white daylight base (lab(100% 0 0)), crisp charcoal primary (lab(7.78201% -.0000149012 0)), and high-contrast surfaces.
- Dark theme (
- The guard
scripts/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(--primary) 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. Toggle synchronizes bothdocument.documentElement.dataset.themeand.dark/.lightclasses.
Smart Utils & AI Workflow
- Class helper:
src/utils/cn.ts— zero-dependency classnames merging utility for conditional component styles. - Smart CSS:
src/utils.css— ready-to-use helpers (.dot-canvas,.surface-card,.surface-sidebar,.badge-*,.hover-lift,.kbd-tag,.skeleton-pulse,.progress-*,.ui-table-*,.dialog-*,.sheet-*,.alert-*,.ui-tabs-*,.switch-*). - Composable Primitives:
src/components/ui/(Dialog,Sheet,Tabs,Alert,EmptyState,Table,Progress,Switch,Badge,Card,StatCard,Skeleton,Tooltip,Kbd,Icon). - Reusable Application Patterns:
src/components/examples/(MetricsDashboard,SettingsPanel,ServiceTable,DeploymentModal). - Icon Library:
lucide-react— 1,400+ tree-shaken SVGs with uniform stroke and color inheritance (<Icon name="..." />or direct import).
Structure
src/
tokens.css ← lab() design tokens + dark & light themes (edit this first)
utils.css ← token-compliant smart CSS utility classes
index.css ← fonts, tokens & utils import, base resets
App.css ← application component styles (token-driven, plain CSS)
App.tsx ← page composition & showcase layout
utils/
cn.ts ← conditional classnames utility
components/
ui/ ← composable UI primitives (Dialog, Sheet, Tabs, Alert, EmptyState, Table, Progress, Switch, Badge, Card, StatCard, Skeleton, Tooltip, Kbd, Icon)
examples/ ← reusable pattern components (MetricsDashboard, SettingsPanel, ServiceTable, DeploymentModal)
AIWorkflowSection.tsx ← interactive pattern switcher & showcase
IconMatrix.tsx ← interactive Lucide icon explorer & search
Topbar.tsx ← owns the theme toggle (.dark & data-theme)
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 and color token data 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.