diff --git a/DESIGN.md b/DESIGN.md index 8ff8a57852..6eaa1e12cf 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -54,3 +54,5 @@ No visual redesign, no new colors or typefaces, no layout restructuring, no new ## Prior art (read before auditing) See `doc/design/PRIOR-ART.md` — a previous audit pass (PAP-280/283/284, on the `PAP-282-playground` branch, NOT on master) found that of ~220 hardcoded drift sites, only 6 were exact-value-mappable to existing tokens; expect the verbatim extraction to mint many new tokens that the human scale-collapse step later merges. It also drafted usage rules (radius tiers, CTA tiers, named type styles) that are good candidates for the post-audit scale decision. + +How-to guide for day-to-day UI changes: see `doc/design/CHANGING-THE-UI.md`. diff --git a/doc/design/CHANGING-THE-UI.md b/doc/design/CHANGING-THE-UI.md new file mode 100644 index 0000000000..5eab52f7aa --- /dev/null +++ b/doc/design/CHANGING-THE-UI.md @@ -0,0 +1,72 @@ +# Changing Paperclip's UI — a field guide + +How to make visual changes now that the design system exists. Written for everyone: designers, engineers, and AI agents (AGENTS.md points here via DESIGN.md). + +## The one-minute mental model + +Paperclip's look lives in **three layers**, and you almost always work in the first one: + +1. **Tokens** — every color, text size, spacing, radius, and shadow is a named value in `ui/src/index.css`. Change a token, and every surface using it follows. +2. **Components** — consume tokens, never raw values. One component per job (one Button, one Card, one ToggleSwitch). +3. **Screenshots** — 510 baseline images (255 stories × light/dark) in `tests/storybook-visual/__snapshots__/`. They are the proof of what the UI looks like. Any visual change shows up as a screenshot diff; no visual change proves itself the same way. + +The rules live in [`DESIGN.md`](../../DESIGN.md) (repo root). The reasoning behind past decisions lives in [`DECISION-SHEET.md`](DECISION-SHEET.md). If you disagree with a rule, change `DESIGN.md` first (with review) — don't quietly diverge in code. + +## The three commands + +```bash +pnpm check:token-gates # am I allowed to write this? (no hardcoded values) +pnpm test:storybook-visual # what does my change look like? (diff vs baseline) +pnpm test:storybook-visual:update # accept my intentional changes as the new baseline +``` + +## Recipe 1 — change how something looks everywhere + +*"Make the corners rounder." "That amber is too loud." "Bump the smallest text size."* + +1. Find the token in `ui/src/index.css` (they're named and commented: `--radius`, `--status-task-todo`, `--text-micro`, …). +2. Change the value. +3. `pnpm test:storybook-visual` — it will "fail" on every affected story. That's the point: each failure writes a before/actual/diff image triplet into `tests/storybook-visual/test-results/`. Review them (or `npx playwright show-report` from `tests/storybook-visual/` for a browsable version). +4. Happy? `pnpm test:storybook-visual:update`, commit the token edit **and** the updated snapshots together. + +Notable single-knob tokens: `--radius` drives the entire corner ladder (sm→4xl are derived); the `--status-task-*` / `--status-agent-*` family is the app-wide status vocabulary (chips, charts, bars, live dots all follow it). + +## Recipe 2 — retheme the whole app + +The core palette follows the shadcn token names, so a theme built at ui.shadcn.com/create applies as token values: + +```bash +cd ui && pnpm dlx shadcn@latest init --preset --force --no-reinstall +``` + +Then **review the git diff and keep only the CSS-variable value changes** — the CLI also tries to rewrite `components.json`, `lib/utils.ts`, and add dependencies; revert those (it once deleted 240 lines of our utils). Never use `shadcn apply --preset` (it overwrites component files). After the token diff is clean: Recipe 1 steps 3–4, plus a sanity pass on the Paperclip-specific tiers (agent gradients, WCAG-tuned status hues) for clashes. + +## Recipe 3 — build or style a component + +- **Values**: tokens only. No hex, no `text-[11px]`, no `p-[13px]`. If no token fits, **add a token** — that's a feature, not a workaround. +- **Type**: use the named ladder — `--text-nano` (10px) / `--text-micro` (11px) / Tailwind `text-xs` (12) / `--text-compact` (13) / `text-sm` (14). Letter-spacing: `--tracking-label` / `--tracking-eyebrow` / `--tracking-caps`. +- **Status**: anything that means running/idle/paused/error/todo/done/blocked uses the status system (`ui/src/lib/status-colors.ts` helpers or `--status-*` tokens). Liveness is always blue. +- **Primitives**: check `ui/src/components/ui/` and `doc/design/COMPONENT-INVENTORY.md` before writing a new component. Switches are `ToggleSwitch`; badges/chips route through `brandChipBadge`. +- **Give it a story.** New visual surface = new Storybook story = automatic screenshot coverage forever. +- `pnpm check:token-gates` before you push. If a value genuinely can't be a token (third-party config, canvas fills, intentional one-off decoration on demo pages), it goes on the allowlist **with an inline comment saying why**. + +## Recipe 4 — you changed something and snapshots failed + +That's the system working. Two cases: + +- **You meant it** → review the diffs (they're your design review), then `pnpm test:storybook-visual:update` and commit snapshots with the change. A PR with visual changes but no snapshot updates is incomplete; snapshot changes with no explanation is a red flag. +- **You didn't mean it** → you broke something. The diff images show you exactly where. Do not update the baseline to make it green. + +Three stories are known to flake under full parallel load (they pass in isolation — see DECISION-SHEET). Re-run a single story with `npx playwright test --config tests/storybook-visual/playwright.config.ts -g ""` before assuming a real failure. + +## For AI-agent sessions + +This system was built to be steered by instruction. "Make all running indicators blue" or "collapse these three grays into one" should land as a token edit or a small codemod plus a snapshot diff — not a manual hunt. If a change is mechanical and touches many files, write an idempotent script in `scripts/` (see `codemod-*.mjs` for the pattern) instead of hand-editing. DESIGN.md is loaded via AGENTS.md; follow it exactly, and record consequential choices in DECISION-SHEET.md. + +## What's deliberately not done yet (don't fix ad hoc) + +- **Tailwind palette classes** (`bg-red-500`, ~3,100 sites) — scheduled for a dedicated cluster-by-cluster conversion pass; piecemeal fixes will collide with it. +- **Hand-rolled cards/pills → `Card`/`Badge`**, sidebar agents-section unification — queued as a component-convergence pass with per-site snapshot verification. +- **ESLint ratchet** — will eventually enforce the token rules at lint time; until then `check:token-gates` is the gate. + +See `DECISION-SHEET.md` for the full ledger.