How to Build a Design System with Claude Code
Learn how to build a design system using Claude Code. Includes practical code examples and step-by-step guidance.
Streamlining Design System Construction With Claude Code
Building a design system involves a lot of work: defining tokens, implementing components, and writing documentation. With Claude Code, you can build a consistent design system in a systematic way.
Defining Design Tokens
Start by defining design tokens for things like color, font, and spacing.
> Define design tokens based on Tailwind CSS variables.
> Support both light and dark modes.
// tokens/colors.ts
export const colors = {
primary: {
50: "oklch(0.97 0.01 250)",
100: "oklch(0.93 0.03 250)",
200: "oklch(0.86 0.06 250)",
300: "oklch(0.76 0.10 250)",
400: "oklch(0.66 0.15 250)",
500: "oklch(0.55 0.20 250)",
600: "oklch(0.47 0.20 250)",
700: "oklch(0.39 0.18 250)",
800: "oklch(0.33 0.15 250)",
900: "oklch(0.27 0.12 250)",
},
gray: {
50: "oklch(0.98 0.00 0)",
100: "oklch(0.96 0.00 0)",
200: "oklch(0.91 0.00 0)",
300: "oklch(0.83 0.00 0)",
400: "oklch(0.71 0.00 0)",
500: "oklch(0.55 0.00 0)",
600: "oklch(0.45 0.00 0)",
700: "oklch(0.37 0.00 0)",
800: "oklch(0.27 0.00 0)",
900: "oklch(0.18 0.00 0)",
},
} as const;
// tokens/spacing.ts
export const spacing = {
xs: "0.25rem", // 4px
sm: "0.5rem", // 8px
md: "1rem", // 16px
lg: "1.5rem", // 24px
xl: "2rem", // 32px
"2xl": "3rem", // 48px
"3xl": "4rem", // 64px
} as const;
// tokens/typography.ts
export const typography = {
fontFamily: {
sans: '"Inter", system-ui, sans-serif',
mono: '"JetBrains Mono", monospace',
},
fontSize: {
xs: ["0.75rem", { lineHeight: "1rem" }],
sm: ["0.875rem", { lineHeight: "1.25rem" }],
base: ["1rem", { lineHeight: "1.5rem" }],
lg: ["1.125rem", { lineHeight: "1.75rem" }],
xl: ["1.25rem", { lineHeight: "1.75rem" }],
"2xl": ["1.5rem", { lineHeight: "2rem" }],
"3xl": ["1.875rem", { lineHeight: "2.25rem" }],
},
} as const;
Implementing Base Components
Let’s build a Button component with variant support.
import { type ButtonHTMLAttributes, forwardRef } from "react";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
{
variants: {
variant: {
primary: "bg-primary-600 text-white hover:bg-primary-700",
secondary: "bg-gray-100 text-gray-900 hover:bg-gray-200",
outline: "border border-gray-300 bg-transparent hover:bg-gray-50",
ghost: "hover:bg-gray-100",
danger: "bg-red-600 text-white hover:bg-red-700",
},
size: {
sm: "h-8 px-3 text-sm",
md: "h-10 px-4 text-sm",
lg: "h-12 px-6 text-base",
},
},
defaultVariants: {
variant: "primary",
size: "md",
},
}
);
export interface ButtonProps
extends ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
isLoading?: boolean;
}
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, isLoading, children, disabled, ...props }, ref) => {
return (
<button
ref={ref}
className={cn(buttonVariants({ variant, size }), className)}
disabled={disabled || isLoading}
{...props}
>
{isLoading && (
<svg className="animate-spin -ml-1 mr-2 h-4 w-4" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" fill="none" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
</svg>
)}
{children}
</button>
);
}
);
Button.displayName = "Button";
Input Component
import { type InputHTMLAttributes, forwardRef } from "react";
import { cn } from "@/lib/utils";
export interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
label?: string;
error?: string;
helperText?: string;
}
export const Input = forwardRef<HTMLInputElement, InputProps>(
({ className, label, error, helperText, id, ...props }, ref) => {
const inputId = id || label?.toLowerCase().replace(/\s/g, "-");
return (
<div className="space-y-1">
{label && (
<label htmlFor={inputId} className="block text-sm font-medium text-gray-700">
{label}
</label>
)}
<input
ref={ref}
id={inputId}
className={cn(
"block w-full rounded-md border px-3 py-2 text-sm shadow-sm transition-colors",
"focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-primary-500",
error ? "border-red-500" : "border-gray-300",
className
)}
aria-invalid={!!error}
aria-describedby={error ? `${inputId}-error` : undefined}
{...props}
/>
{error && (
<p id={`${inputId}-error`} className="text-sm text-red-500">{error}</p>
)}
{helperText && !error && (
<p className="text-sm text-gray-500">{helperText}</p>
)}
</div>
);
}
);
Input.displayName = "Input";
For dark mode support, see dark mode implementation, and for animations, see animation implementation. For effective Claude Code usage, see 10 productivity tips that 3x your output.
Summary
With Claude Code, you can efficiently build the foundations of a design system, from defining tokens and implementing components to designing variants. Variant management with CVA and accessibility support are all just a natural-language prompt away.
For details, see the official Claude Code documentation.
Free PDF: Claude Code Cheatsheet in 5 Minutes
Just enter your email and we'll send you the single-page A4 cheatsheet right away.
We handle your data with care and never send spam.
Level up your Claude Code workflow
50 battle-tested prompt templates you can copy-paste into Claude Code right now.
About the Author
Masa
Engineer obsessed with Claude Code. Runs claudecode-lab.com, a 10-language tech media with 2,000+ pages.
Related Posts
Safe Agent Harness Design for Claude Code and Codex: Permissions, Checks, and Rollback
Build a practical agent harness for Claude Code and Codex with policy, planning, verification, and recovery layers.
10 Powerful Subagent Patterns for Claude Code
Master Claude Code's subagent feature with 10 practical patterns. Learn how to use parallel processing, specialization, and context isolation to double your development speed.
Getting Started with Claude Code Agent SDK — Build Autonomous Agents Fast
Learn how to build autonomous AI agents with Claude Code Agent SDK. Covers setup, tool definitions, and multi-step execution with practical code examples.
Related Products
50 Battle-Tested Claude Code Prompt Templates
Copy, paste, ship. 50 production-ready prompts.
Use proven prompts for code review, refactoring, testing, documentation, debugging, architecture, and incident response.
The Complete Claude Code Setup & Configuration Guide
From install to team-ready workflow.
A practical guide to installation, CLAUDE.md, hooks, MCP servers, permissions, IDE setup, and CI/CD workflows.