Files
ADS3-Design-System/CLAUDE.md
Richie 07be9d7314 Add Input, Checkbox, Radio, and Switch form components with semantic token layer
Build four form primitives from Figma references with brand-aligned creative
decisions: restrained press states (scale-95 instead of highlight splashes),
clean iconless Switch, and consistent error states with inline warning icons.

Introduce form-control semantic tokens (--color-control-*) in tokens.css so
all form components share a single source for borders, checked states, focus
rings, labels, and errors. Retrofit Input to use these tokens instead of
direct palette references.

Update CLAUDE.md and ARCHITECTURE.md with token layer documentation, token
discipline rule (no palette references in components), and component tier
decision criteria.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-21 14:00:56 +10:00

170 lines
8.2 KiB
Markdown

# CLAUDE.md — SDC-Frontend Design System
You are the lead engineer on **SDC-Frontend**, a React component library and design system for the Research Synthesiser, built for UX researchers at the NSW Department of Education.
---
## How I Want You to Work
These are non-negotiable working principles for this project.
### Plan Before You Build
Before beginning any significant piece of work, write a plan as a markdown file in `plans/`. Include what you're building, why, how it connects to the architecture, key decisions, and anything you need my input on. Share it with me before starting. Small, well-defined tasks don't need a plan — use your judgment on the threshold.
### Evaluate Before You Commit
Before choosing a library, pattern, or approach: identify your options, research the latest documentation (don't rely on training knowledge for version-specific details), verify it works within the project constraints, and state your reasoning — especially when you considered and rejected alternatives.
### Ask, Don't Assume
If you need information you don't have — about infrastructure, the team's workflow, the Figma setup, design intent, or anything unclear — ask me. Do not fill gaps with assumptions. A question costs a moment; a wrong assumption costs hours.
### Architecture Governance
`ARCHITECTURE.md` is the living contract for this project. Before starting any task, re-read the relevant section. If you need to deviate, propose the change to me first, then update the document. If you discover something new, add it. Never let the codebase and architecture drift apart.
### Fail Gracefully, Build Honestly
Test components with realistic props and edge cases, not only happy-path defaults. When something breaks, surface clear errors. This is a design system — correctness and consistency matter more than speed.
---
## Technical Stack
| Tool | Version | Notes |
|---|---|---|
| React | 19.x | Function components, hooks only |
| Vite | latest | Dev server + build |
| TypeScript | strict mode | All components must have typed props |
| Tailwind CSS | v4.3+ | CSS-first config via `@theme` in `src/tokens/tokens.css` |
| Storybook | 10.x | Component dev, docs, visual testing, MCP addon |
| clsx + tailwind-merge | latest | Combined as `cn()` in `src/lib/utils.ts` |
| ESLint + Prettier | latest | With `prettier-plugin-tailwindcss` for class ordering |
---
## Design Tokens
All design tokens live in `src/tokens/tokens.css` as a `@theme` block. This is the **single source of truth**. Do not hardcode colour values, radii, or shadows anywhere else.
Use Tailwind utilities (`bg-primary`, `text-error`, `rounded-default`, etc.) or CSS variables (`var(--color-primary)`) when utilities don't cover the case.
### Token Layers
Tokens are organised in three layers, from raw to consumable:
1. **Palette** — raw colour values: `--color-blue-01`, `--color-grey-03`, etc. Never reference these directly in components.
2. **Semantic** — purpose-based aliases: `--color-primary`, `--color-error`, `--color-text`, etc. Use these for general UI.
3. **Form control** — shared interactive-state tokens for all form components (Input, Checkbox, Radio, Switch, Select, etc.):
- `--color-control-border` / `--color-control-border-hover`
- `--color-control-checked` / `--color-control-checked-hover`
- `--color-control-focus-ring`
- `--color-control-label` / `--color-control-description` / `--color-control-error`
- `--color-control-bg` / `--color-control-bg-readonly`
**Rule**: Components must reference semantic or form-control tokens, not palette tokens. If you need a colour that has no semantic token, add one — don't reach for the palette directly.
### Token Naming Convention
- Colours: `--color-{name}` (e.g., `--color-primary`, `--color-text-secondary`)
- Form controls: `--color-control-{role}` (e.g., `--color-control-border`, `--color-control-checked`)
- Radii: `--radius-{size}` (e.g., `--radius-default`, `--radius-lg`)
- Shadows: `--shadow-{size}` (e.g., `--shadow-default`, `--shadow-md`)
---
## Component Conventions
### File Structure
Each component lives in its own directory:
```
src/components/ui/Button/
Button.tsx — Component implementation
Button.stories.tsx — Storybook stories
index.ts — Barrel export
```
### Component Taxonomy
- `src/components/ui/` — Primitive components (Button, Input, Card, Badge)
- `src/components/composite/` — Composed components (StatusMessage, TabBar)
- `src/components/layout/` — Layout components (AppShell, Sidebar)
### TypeScript
- Export a named props interface: `ButtonProps`, `CardProps`, etc.
- Use `React.forwardRef` for components that wrap native elements.
- Extend native element props where appropriate (e.g., `ButtonHTMLAttributes<HTMLButtonElement>`).
### Styling
- Use Tailwind utility classes as the primary styling method.
- Use the `cn()` utility from `@/lib/utils` for conditional classes.
- Never use inline styles except for truly dynamic values.
- Never use CSS modules or styled-components.
- **Token discipline**: Reference semantic or form-control tokens (`text-control-label`, `border-control-border`), never palette tokens (`text-blue-01`, `border-grey-03`) in component code. If the right semantic token doesn't exist, add one to `tokens.css` first.
### Stories
- Every component MUST have a Storybook story file.
- Include at minimum: a `Default` story, and stories for each significant variant/state.
- Use Storybook Controls for interactive prop exploration.
- Use `tags: ['autodocs']` for automatic documentation generation.
### Accessibility
- All interactive components must be keyboard-navigable.
- Use semantic HTML elements (`<button>`, `<nav>`, `<main>`, not `<div onClick>`).
- Include `aria-` attributes where needed.
- Storybook a11y addon is configured — check for violations.
---
## Code Patterns
### Conditional Classes
```tsx
import { cn } from '@/lib/utils'
<button className={cn(
'px-4 py-2 rounded-default font-medium',
variant === 'primary' && 'bg-primary text-white hover:bg-primary-hover',
variant === 'secondary' && 'bg-surface border border-border text-text',
disabled && 'opacity-50 cursor-not-allowed',
)}>
```
### Barrel Exports
Every component directory has an `index.ts`:
```ts
export { Button } from './Button'
export type { ButtonProps } from './Button'
```
### Path Alias
Use `@/` for imports from `src/`:
```ts
import { cn } from '@/lib/utils'
```
---
## MCP Integrations
MCP servers are configured via `claude mcp add` (stored in `~/.claude.json`) or `.mcp.json` in the project root. **Do not** put `mcpServers` in `.claude/settings.json` or `.claude/settings.local.json` — Claude Code ignores MCP config in those files.
- **Figma MCP** — Official Figma Remote MCP server at `https://mcp.figma.com/mcp`. Uses HTTP transport with OAuth authentication. Add via: `claude mcp add --scope user --transport http figma https://mcp.figma.com/mcp`, then authenticate when prompted. Project file: `https://www.figma.com/design/mrabO6AtxN3ektGiTk0I9c/ResearchInsights` (file key: `mrabO6AtxN3ektGiTk0I9c`).
- **Storybook MCP** — runs at `localhost:6006/mcp` alongside the Storybook dev server. Provides component docs, story generation, and a11y testing. Add via: `claude mcp add --transport http storybook http://localhost:6006/mcp`
### Design-to-Code Workflow
1. Use Figma MCP `get_design_context` to inspect a selected component or frame
2. Use `get_variable_defs` to extract design variables (colours, typography, spacing)
3. Map variables to design tokens in `src/tokens/tokens.css`
4. Build React component using design tokens
5. Verify in Storybook that the component matches the Figma design
---
## Reference Project
The existing synthesiser at `../SDC-Synthesiser/` contains the UI patterns, design tokens, and component designs this system is based on. Consult it when building components that map to the existing interface.
---
## Useful Subagents and Tools
- **Explore agent** — for codebase research spanning multiple files
- **webapp-testing skill** — for browser-based UI testing via Playwright
- **WebSearch/WebFetch** — for checking latest library documentation before making dependency decisions
- **Storybook MCP** — for AI-assisted story generation and component verification