Goal
Build a new UI component that integrates seamlessly with the design system.
Pre-Requisites
Before creating a new component:
1. Verify It Doesn't Already Exist
- Check system/components/ for existing component
- Check system/patterns/component-match.md for similar components
- Search codebase for similar implementations
2. Identify Composition Opportunities
- Can existing components be composed instead of building from scratch?
- Check individual component pages for existing composition examples
Workflow
Step 1: Understand Requirements
- What problem does this component solve?
- What variants are needed?
- What states must it support? (loading, error, disabled, etc.)
- What accessibility requirements exist?
Step 2: Check Design Source
- Is there a Figma design for this component?
- What tokens does the design use?
- Are there responsive requirements?
Step 3: Plan the API
- What props are needed?
- What's the composition model? (slots, children, compound components?)
- What are sensible defaults?
Step 4: Build with System Tokens
Reference these files while building:
- tokens/colors.md - Color tokens (use semantic, never raw hex)
- tokens/typography.md - Font sizes, weights
- tokens/spacing.md - Padding, margins, gaps
- tokens/radii.md - Border radius
- tokens/shadows.md - Elevation
- tokens/motion.md - Animations, transitions
Step 5: Implement Accessibility
Reference rules/accessibility.md:
- Semantic HTML elements
- Keyboard navigation
- ARIA attributes where needed
- Focus management
Component Structure Template
// components/ui/[component-name].tsx
import * as React from "react"
import { cn } from "@/lib/utils"
// Define variants (if applicable)
const variants = {
default: "...",
secondary: "...",
}
// Define sizes (if applicable)
const sizes = {
sm: "...",
md: "...",
lg: "...",
}
interface ComponentNameProps {
variant?: keyof typeof variants
size?: keyof typeof sizes
className?: string
children?: React.ReactNode
}
export function ComponentName({
variant = "default",
size = "md",
className,
children,
...props
}: ComponentNameProps) {
return (
<div
className={cn(
// Base styles
"...",
// Variant styles
variants[variant],
// Size styles
sizes[size],
// Custom classes
className
)}
{...props}
>
{children}
</div>
)
}
Validation Checklist
Before considering the component complete:
Design System Compliance
- Uses semantic color tokens (no hardcoded hex values)
- Uses system typography tokens
- Uses system spacing tokens
- Uses system border radius tokens
- Follows existing component patterns
Accessibility
- Keyboard navigable
- Has appropriate ARIA attributes
- Focus states are visible
- Color contrast meets WCAG AA (4.5:1)
Code Quality
- TypeScript types are complete
- Props have sensible defaults
- Component is composable
- No
anytypes
Common Mistakes to Avoid
| Mistake | Correct Approach |
|---|---|
Using bg-[#19518B] | Use bg-primary |
Using text-[14px] | Use text-sm |
Using p-[10px] | Use nearest token p-2.5 or p-3 |
| Creating custom icon | Use Lucide React icon |
| Building without checking existing components | Always check component inventory first |
overflow-x-auto on its own | It computes overflow-y to auto too, making the box a scroll container on both axes. Set the vertical axis explicitly — see CSS Behaviours That Have Bitten Us |
After Creating
- Document the component - See document-component.md
- Add to component inventory - Update
system/components/if needed - Record any decisions - If new patterns were established, document in
system/decisions/
Related Context
Last updated: February 4, 2026