ui-system skill is no longer a placeholder. Full design-system and interaction-design interviews with branching, defaults, batched question clusters, and an 'accept default / skip' protocol so users move through fast when they have taste and patient when they don't. Design system interview covers: visual posture, color (with WCAG contrast verification before writing), typography, spacing, radii, shadows, density, visual motion, components, theming, and accessibility tokens (focus ring, hit targets). Interaction design interview covers: input model, state-surface declarations per action class, motion posture and triggers, breakpoints, i18n, four state postures (empty/loading/error/offline), time formatting, keyboard policy, optimistic-update strategy with rollback and conflict resolution, gestures, focus management, notification patterns, selection, and drag-and-drop. Reference banks for "make it look like Linear/Notion/Stripe/etc." translate well-known products into starting tokens — user still confirms each value, no silent invention. Templates expanded to hold the full output: - design-system/SKILL.md grew sections for accessibility tokens, density, dark-mode mapping, contrast verification, theming variants - design-system/tokens.ts now exports color (light + dark), typography (family/size/weight/line-height/letter-spacing), spacing + density- aware padding tokens, radii, shadows, motion (durations + easings), z-index scale, breakpoints, hit-target minimums - design-system/components.md gained anatomy/state/a11y coverage for 10 primitives plus an "adding a new component" workflow and a "patterns to avoid" list (nested cards, color-only meaning, etc.) - interaction-design/SKILL.md gained sections for optimistic updates, conflict resolution, gestures, focus management, notification patterns, selection/multi-select, and drag-and-drop Hard rules: never invent on the user's behalf; <TBD> instead. Verify contrast before writing color tokens. Always declare prefers-reduced- motion as honored. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
16 KiB
name, description
| name | description |
|---|---|
| ui-system | Interview the user and produce two project-local skills — a design-system skill and an interaction-design skill — that auto-load whenever UI work is in progress. Output goes to .claude/skills/<slug>-design-system/ and .claude/skills/<slug>-interaction-design/, NOT docs/planning/. The skills load themselves into context when anyone codes UI (mock or real); a plain reference doc would not. Use when the composer skill reaches phase 4 or 5, or when the user asks to "set up the design system", "specify interaction patterns", or "redo the UI system". |
UI system
You run a focused interview that produces two project-local skills:
.claude/skills/<slug>-design-system/
├── SKILL.md ← canonical visual reference; auto-loads on UI work
├── tokens.ts ← machine-readable color / type / spacing / motion tokens
└── components.md ← component vocabulary with anatomy
.claude/skills/<slug>-interaction-design/
└── SKILL.md ← interaction patterns, state surfaces, input modes, i18n
Plus pointer stubs in docs/planning/{design-system,interaction-design}.md
so the planning index finds them.
Why these are skills, not docs
A reference doc gets read once and drifts out of context as the conversation grows. UI work later — generating a mock, writing a component, picking a color — wouldn't have it loaded.
A skill with a UI-triggered description loads automatically every time the trigger matches. The design system and interaction design must be skills, full stop.
Slug
Resolve in order:
package.jsonname— slugify.- Git remote name (e.g.,
git remote get-url origin→ repo name). - Directory name.
- Ask.
Slug rule: lowercase kebab-case, ASCII only.
SourdoughTracker → sourdough-tracker → sourdough-tracker-design-system.
Interview shape
Two parts, sequential: design system first (visual), then interaction design (behavioral). Don't interleave — they're different conversations and the visual posture often informs interaction choices.
Each phase:
- State what's being decided and why it matters (one line).
- Show the default if there is one.
- Ask the question. Batch related questions when they cluster naturally.
- Confirm the answer back as it'll appear in the artifact.
- Move on.
The user can answer default or skip at any phase:
default→ accept the offered default and move on.skip→ mark<TBD: ...>and move on; user can revisit.
Never invent on the user's behalf. <TBD> is a worklist, not a failure.
Phase 0 — Material ingestion (silent)
Before asking anything, scan for material the user already has. Read without asking; surface findings before the first question.
| Source | What to extract |
|---|---|
package.json |
name (slug), version, dependencies (UI framework hints) |
tailwind.config.{js,ts} |
existing tokens, theme extensions |
tokens.{ts,json,css} anywhere in repo |
existing token values |
*.css, *.scss |
brand colors mentioned, font families imported |
index.html, <head> of any HTML |
font loads, color-scheme meta |
assets/, public/, docs/ for logos/screenshots |
brand colors via image inspection |
README.md, BRANDING.md, STYLE.md |
style notes the user wrote |
Existing docs/planning/concept.md |
platform hint (web/mobile/native) |
Then before the interview opens:
Material I found and will use:
• <thing> — <how it'll inform the interview>
• <thing>
Not found (will ask): brand color, type family, motion posture.
If the user has named a reference like "make it look like Linear" in a previous Composer phase, surface it here and apply the matching preset (see "Reference banks" below).
Part 1 — Design system
D1 — Visual posture (one paragraph)
The north star sentence for visual decisions. Don't ask for paragraphs; ask for adjectives and assemble.
Three or four words that describe how this should feel.
Examples: "quiet, dense, monochrome, one accent" / "playful,
generous, expressive type" / "clinical, neutral, accessibility-forward".
Compose into a single sentence; show; accept.
D2 — Color
Batch as a single phase with sub-questions; tight loop.
D2.1 Brand primary. If material gave a color, propose it. Else:
Pick a brand primary. Either name a hex, name a color
("warm orange", "deep teal"), or name a reference ("Linear's purple",
"Stripe's indigo"). I'll generate the variants from there.
D2.2 Brand secondary. Optional. default = none.
D2.3 Neutral tone. Warm / cool / true. One question.
For grays, do they feel slightly tan (warm), slightly blue (cool),
or truly neutral (true)? Default: cool.
D2.4 Generate the neutral scale. Compute 50–950 from the chosen tone
and brand contrast targets. Show the user; offer default or "redo with
warmer/cooler/more contrast".
D2.5 Semantic colors. Success / warning / error / info. Show defaults that contrast against both light and dark backgrounds; user accepts or overrides one at a time.
D2.6 Dark mode. yes / no / system-following. Default: system. If yes, generate the dark token mapping (invert + adjust saturation per token class) and show.
D2.7 Accessibility check. Compute contrast ratios between primary + neutral pairs. Flag anything below 4.5:1 for body text or 3:1 for UI. Don't silently accept failures — surface and confirm or adjust.
D3 — Typography
D3.1 One family or two? Default: one.
D3.2 Family choice. If user has no preference, offer presets:
- Modern sans: Inter (free, broad weights)
- Humanist: Source Sans 3 / IBM Plex Sans
- System stack: native to OS (free, no load)
- Editorial: Inter + Fraunces (display)
- Technical: IBM Plex Sans + IBM Plex Mono
D3.3 Scale base. 14, 15, 16. Default: 16 (web), 17 (iOS native), 14 (compact dashboards).
D3.4 Scale ratio. 1.125 (subtle), 1.2, 1.25 (default), 1.333 (dramatic), 1.5 (display-heavy).
D3.5 Line-height policy.
- Display: 1.1–1.2 (tight)
- Body: 1.5 (normal)
- Long-form prose: 1.7 (relaxed) Defaults usually fine; user can override one of three.
D4 — Spacing
D4.1 Base unit. 4 (default — finer control) or 8 (rougher cadence; iOS native often).
D4.2 Scale. Use the standard 12-step (0, 0.5, 1, 1.5, 2, 3, 4, 6, 8, 12, 16, 24) — almost always accepted as default.
D5 — Radii
D5.1 Posture. sharp (0–4) / tight (4–8) / medium (8–16) / pillowy (16+) / mixed.
D5.2 Generate sm/md/lg/pill/full. Show; accept or tweak one.
D6 — Shadows & elevation
D6.1 Posture. flat (none) / subtle / generous.
D6.2 Scale. xs/sm/md/lg/xl. Generated from posture; show; accept.
D7 — Density
D7.1 Default density. comfortable (default; web app) / cozy / compact (data-heavy dashboard).
This drives component padding tokens — important enough to ask, easy to forget otherwise.
D8 — Visual motion
D8.1 Default duration. fast (150ms), default (250ms), slow (400ms). Default: default. D8.2 Default easing. standard / accel / decel / custom. Default: standard.
Behavioral motion (when things animate) lives in interaction design.
D9 — Components
Read the entity vocabulary from ia.md. Confirm the standard set
(Button, Input, Card, Surface) and ask for project-specific
additions found in IA.
For each project-specific component, ask: variants? states? anatomy? Default to "standard variants only" if user is unsure — better to add later than over-spec now.
D10 — Theme variants (skip by default)
Multi-brand / tenant theming usually no for v1. Default: skip.
D11 — Accessibility tokens
D11.1 Focus ring. Style (solid / double / inner-outer) and color (brand / accent / outline-default). Default: solid 2px brand at 60% opacity.
D11.2 Contrast targets. Confirm WCAG AA (4.5:1 text, 3:1 UI). AAA optional. Default: AA.
Part 2 — Interaction design
I1 — Input model
I1.1 Primary input. touch (mobile/tablet) / mouse / keyboard / mixed.
Often determined by platform from concept.md — confirm rather than ask cold.
I1.2 Supported inputs. Which secondaries must work; which are not in scope.
I1.3 Voice / switch / assistive. Defer unless users.md has an actor that needs it.
I2 — State surface declarations
The most important phase. For each action class, pick one pattern. Walk through them in this order:
| Action class | Common picks | Default |
|---|---|---|
| Quick edit (single field) | inline edit / popover / drawer | inline edit |
| Multi-field create | drawer / modal / full-page route | drawer (web), modal (native) |
| Multi-field edit | drawer / modal / full-page route | same as create |
| Confirm destructive | modal | modal (always — non-negotiable) |
| Settings / configuration | full-page route | full-page route |
| Top-level navigation | sidebar / tab bar / header nav | tab bar (mobile), sidebar (desktop) |
| Detail-from-list | full route / side panel / drawer | full route |
| Filtering / sorting | inline controls / popover / drawer | inline (small set), drawer (large set) |
| Search | header search / command palette / page | header search |
For each, show the default and the alternatives. User confirms or picks.
I3 — Motion posture
I3.1 Posture. minimal / restrained / expressive.
I3.2 Animation triggers. For each, yes/no/conditional:
- Page/route transitions
- List item enter/exit
- Modal/drawer open/close
- State changes (toggle, expand)
- Loading→loaded transitions
Defaults from the posture choice — show; accept.
I3.3 Reduced motion fallbacks. Confirm prefers-reduced-motion is
honored (always yes; this is policy, not preference).
I4 — Breakpoints
I4.1 Count. 2 (mobile / desktop) / 3 (mobile / tablet / desktop) / 4 (with large desktop) / fluid.
I4.2 Values. Defaults: 640 / 768 / 1024 / 1280. Tweakable.
I4.3 Primary target. mobile-first / desktop-first / fluid. Determined by platform.
I5 — i18n
I5.1 Locales at launch. Default: just English (en or en-US).
I5.2 RTL support. yes / no / planned. Default: no in v1.
I5.3 Pluralization. ICU MessageFormat / library / manual. Default: ICU MessageFormat (industry standard).
I5.4 String length budget. Default: assume +30% over English for de/fr translations. Always declared.
I6 — State postures
Four sub-decisions; one declared posture each.
I6.1 Empty state.
- Visual: icon + heading + body + CTA / heading + body / heading only.
- Tone: encouraging / neutral / matter-of-fact.
- CTA: present always / present when actionable / never.
I6.2 Loading state.
- Default: skeleton / spinner / blocking. Pick one default; assign exceptions.
- Threshold for showing loading at all: 200ms (default) / 300ms / immediate.
I6.3 Error state.
- Surface: inline (default) / toast / dialog. By severity class.
- Recovery: retry / clear path forward / report.
- Copy tone: plain language always; what happened + what to do next.
I6.4 Offline state.
- Behavior: full subset works / banner only / "go online to continue".
- Sync: queue + flush on reconnect / fail loudly / not in v1.
I7 — Time formatting
I7.1 Relative-time threshold. Within <7 days> / <30 days> / <24 hours> / never. Default: 7 days.
I7.2 Absolute format. MMM d, yyyy h:mm a / ISO / locale-aware. Default: locale-aware via Intl.DateTimeFormat.
I7.3 Time zones. user-local / fixed (which?) / configurable. Default: user-local.
I8 — Keyboard
I8.1 Global shortcuts. Y/N for v1. If yes, list them; if no, mark "deferred to vN".
I8.2 Modal escape. Always yes; confirm.
I8.3 Focus trap in modal. Always yes; confirm. Restore on close.
I8.4 Form submit. Enter submits / Cmd+Enter submits / explicit only. Default: Enter submits.
I8.5 List navigation. Arrow keys yes/no. Default: no in v1 unless lists are central.
I9 — Optimistic updates & error recovery
I9.1 Default posture.
- Optimistic with rollback (default for most actions — feels fast)
- Pessimistic (default for destructive or money-related actions)
- Mixed (most actions optimistic; some classes pessimistic)
I9.2 Rollback strategy. Toast + revert / silent revert / dialog. Default: toast + revert.
I9.3 Conflict resolution. Last-write-wins / show conflict UI / append. Default depends on platform.
I10 — Gestures (touch only)
Skip this phase if I1.1 didn't include touch.
I10.1 Swipe actions on rows. Y/N. If yes: which actions, which directions.
I10.2 Long-press menu. Y/N. Default: yes (iOS/Android conventional).
I10.3 Pull-to-refresh. Y/N for list views.
I11 — Focus management
I11.1 After modal close. Restore previous focus (default — non-negotiable for a11y).
I11.2 After route change. Heading focus (default) / container focus / no change.
I11.3 After form error. Focus first error field (default).
Reference banks
When the user names a reference ("like Linear", "like Notion"), apply these presets as starting points — user still confirms each value.
| Reference | Visual posture | Color tone | Type | Density | Motion | Radii |
|---|---|---|---|---|---|---|
| Linear | quiet, dense, monochrome with one purple accent | cool neutral | Inter | compact | restrained, fast | tight |
| Notion | minimal, generous spacing, friendly | warm-leaning true neutral | Inter / system | comfortable | minimal | medium |
| Stripe | clean, technical, indigo accent | cool neutral | Camphor / system | comfortable | restrained | medium |
| GitHub | utilitarian, dense, clear hierarchy | cool true neutral | -apple-system stack | compact | minimal | tight |
| Vercel | sharp, monochrome, contrasty | true neutral, almost B&W | Geist / Inter | comfortable | restrained, fast | tight |
| Apple HIG | spacious, soft, system-native | warm-cool mix per platform | SF Pro | cozy | expressive | medium |
| Material 3 | adaptive, expressive, dynamic color | tone-based dynamic | Roboto / Plus Jakarta | comfortable | expressive | pillowy |
For "make it look exotic / brutalist / playful / etc.", branch cleanly: ask for two or three reference URLs the user has in mind, and reflect them back as a posture sentence rather than picking presets.
Write phase
After the interview ends, write all six files in one batch:
.claude/skills/<slug>-design-system/SKILL.mdfromtemplates/design-system/SKILL.md— substitute slug, project name, and all interview answers..claude/skills/<slug>-design-system/tokens.tsfromtemplates/design-system/tokens.ts— fill in all values;<TBD>for skipped phases..claude/skills/<slug>-design-system/components.mdfromtemplates/design-system/components.md— vocabulary matched toia.md..claude/skills/<slug>-interaction-design/SKILL.mdfromtemplates/interaction-design/SKILL.md— fill in all interview answers.docs/planning/design-system.mdfromtemplates/planning-pointers/design-system.md.docs/planning/interaction-design.mdfromtemplates/planning-pointers/interaction-design.md.
Then tell the user:
Wrote two project skills:
.claude/skills/<slug>-design-system/ (SKILL.md, tokens.ts, components.md)
.claude/skills/<slug>-interaction-design/ (SKILL.md)
These auto-load whenever UI work is happening. They should be available
immediately in this session; if you're starting a new session in this
repo, they'll load on the first UI-related prompt.
Items still <TBD> (return-pass worklist):
• <list any phases that were skipped or had unanswered questions>
Re-entry
Re-running the skill on a project that already has the artifacts:
- Read both existing SKILL.md files plus tokens.ts and components.md.
- List what's currently set; mark
<TBD>items prominently. - Ask: "Update everything, just the TBDs, or pick a phase?"
- Run only the chosen scope.
- Always show a diff before writing.
Hard rules
- Always produce all six files. Mocks can't proceed without them.
- Always slug-namespace so projects on the same machine don't collide.
<TBD: ...>rather than invent. TBDs are the return-pass worklist.- Verify a11y contrast before writing color tokens. Don't silently accept failures.
- Honor
prefers-reduced-motionis policy, not opinion. Always declare it as honored. - Confirm before overwriting existing skill files on re-entry.
- Tell the user what was written and where, plus how to verify the skills load.