Per plugin-structure spec, plugin-internal references in component
files (commands, agents, skills) must use \${CLAUDE_PLUGIN_ROOT} so
they resolve correctly regardless of where the plugin is installed
(local repo, marketplace cache, npm-installed, etc.).
Updated:
- symphony/skills/symphony-init/SKILL.md: WORKFLOW.md template ref
- composer/skills/ui-system/SKILL.md: all six template refs in the
Write phase
- composer/skills/composer/SKILL.md: added a Templates section that
enumerates each phase's template path with \${CLAUDE_PLUGIN_ROOT},
plus the ADR template ref in phase 8
Composer's CLAUDE.md gains a clarifying note that templates/design-
system/SKILL.md and templates/interaction-design/SKILL.md are template
skeletons, not actual plugin skills — they're copied into a consuming
project's .claude/skills/ at install-time of the design system. Per
the auto-discovery rule (scans skills/ only), they are not loaded as
plugin skills.
Removed empty composer/agents/ directory (composer has no agents;
workers are owned by symphony).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
421 lines
16 KiB
Markdown
421 lines
16 KiB
Markdown
---
|
||
name: ui-system
|
||
description: 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:
|
||
1. `package.json` `name` — slugify.
|
||
2. Git remote name (e.g., `git remote get-url origin` → repo name).
|
||
3. Directory name.
|
||
4. 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:
|
||
1. State what's being decided and why it matters (one line).
|
||
2. Show the default if there is one.
|
||
3. Ask the question. Batch related questions when they cluster naturally.
|
||
4. Confirm the answer back as it'll appear in the artifact.
|
||
5. 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:
|
||
|
||
1. `.claude/skills/<slug>-design-system/SKILL.md` from `${CLAUDE_PLUGIN_ROOT}/templates/design-system/SKILL.md` — substitute slug, project name, and all interview answers.
|
||
2. `.claude/skills/<slug>-design-system/tokens.ts` from `${CLAUDE_PLUGIN_ROOT}/templates/design-system/tokens.ts` — fill in all values; `<TBD>` for skipped phases.
|
||
3. `.claude/skills/<slug>-design-system/components.md` from `${CLAUDE_PLUGIN_ROOT}/templates/design-system/components.md` — vocabulary matched to `ia.md`.
|
||
4. `.claude/skills/<slug>-interaction-design/SKILL.md` from `${CLAUDE_PLUGIN_ROOT}/templates/interaction-design/SKILL.md` — fill in all interview answers.
|
||
5. `docs/planning/design-system.md` from `${CLAUDE_PLUGIN_ROOT}/templates/planning-pointers/design-system.md`.
|
||
6. `docs/planning/interaction-design.md` from `${CLAUDE_PLUGIN_ROOT}/templates/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:
|
||
|
||
1. Read both existing SKILL.md files plus tokens.ts and components.md.
|
||
2. List what's currently set; mark `<TBD>` items prominently.
|
||
3. Ask: "Update everything, just the TBDs, or pick a phase?"
|
||
4. Run only the chosen scope.
|
||
5. 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-motion` is 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.
|