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>
8.2 KiB
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:
- Palette — raw colour values:
--color-blue-01,--color-grey-03, etc. Never reference these directly in components. - Semantic — purpose-based aliases:
--color-primary,--color-error,--color-text, etc. Use these for general UI. - 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.forwardReffor 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/utilsfor 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 totokens.cssfirst.
Stories
- Every component MUST have a Storybook story file.
- Include at minimum: a
Defaultstory, 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
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:
export { Button } from './Button'
export type { ButtonProps } from './Button'
Path Alias
Use @/ for imports from src/:
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/mcpalongside 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
- Use Figma MCP
get_design_contextto inspect a selected component or frame - Use
get_variable_defsto extract design variables (colours, typography, spacing) - Map variables to design tokens in
src/tokens/tokens.css - Build React component using design tokens
- 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