Design-to-Component Translator
Convert design specifications into pixel-perfect, production-ready React components.
Core Workflow Analyze design specs: Extract spacing, colors, typography, dimensions Map to tokens: Convert design values to design system tokens Generate structure: Create semantic HTML structure Apply styles: Implement Tailwind/CSS with exact measurements Add states: Include hover, focus, active, disabled states Handle responsive: Implement breakpoint-specific rules Ensure accessibility: Add ARIA labels, keyboard navigation Document variants: List all visual states and props Design Spec Analysis Extract from Figma/Design
Spacing & Layout:
Padding: p-4 (16px), px-6 (24px horizontal) Margin: m-2 (8px), mt-4 (16px top) Gap: gap-3 (12px between flex items) Width/Height: w-64 (256px), h-10 (40px)
Typography:
Font family: font-sans, font-mono Font size: text-sm (14px), text-base (16px), text-lg (18px) Font weight: font-normal (400), font-medium (500), font-semibold (600) Line height: leading-tight, leading-normal, leading-relaxed Letter spacing: tracking-tight, tracking-normal, tracking-wide
Colors:
Background: bg-blue-500, bg-gray-100 Text: text-gray-900, text-white Border: border-gray-300, border-blue-600 Opacity: bg-opacity-50, text-opacity-75
Borders & Radius:
Border width: border, border-2, border-t-4 Border radius: rounded (4px), rounded-md (6px), rounded-lg (8px), rounded-full
Shadows:
shadow-sm, shadow, shadow-md, shadow-lg, shadow-xl Design Token Mapping Create Token System // tokens.ts export const tokens = { colors: { primary: { 50: "#eff6ff", 100: "#dbeafe", 500: "#3b82f6", 600: "#2563eb", 700: "#1d4ed8", }, gray: { 100: "#f3f4f6", 300: "#d1d5db", 500: "#6b7280", 700: "#374151", 900: "#111827", }, }, spacing: { xs: "0.25rem", // 4px sm: "0.5rem", // 8px md: "1rem", // 16px lg: "1.5rem", // 24px xl: "2rem", // 32px }, 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" }], }, borderRadius: { sm: "0.25rem", // 4px md: "0.375rem", // 6px lg: "0.5rem", // 8px full: "9999px", }, shadows: { sm: "0 1px 2px 0 rgb(0 0 0 / 0.05)", md: "0 4px 6px -1px rgb(0 0 0 / 0.1)", lg: "0 10px 15px -3px rgb(0 0 0 / 0.1)", }, };
Tailwind Config // tailwind.config.js module.exports = { theme: { extend: { colors: { primary: { 50: "#eff6ff", 100: "#dbeafe", 500: "#3b82f6", 600: "#2563eb", 700: "#1d4ed8", }, }, spacing: { 18: "4.5rem", 88: "22rem", }, fontSize: { "2xs": "0.625rem", }, }, }, };
Component Translation Examples Button from Figma Spec
Figma Specs:
Height: 40px Padding: 12px 24px Border radius: 6px Font: Inter Medium 14px Background: #3B82F6 Text: #FFFFFF Hover: #2563EB Shadow: 0 1px 3px rgba(0,0,0,0.1)
Translated Component:
import { cn } from "@/lib/utils";
interface ButtonProps extends React.ButtonHTMLAttributes
export const Button = ({ variant = "primary", size = "md", className, children, ...props }: ButtonProps) => { return ( ); };
Card from Design Spec
Figma Specs:
Padding: 24px Border radius: 12px Background: #FFFFFF Border: 1px solid #E5E7EB Shadow: 0 1px 3px rgba(0,0,0,0.1) Max width: 400px
Translated Component:
interface CardProps extends React.HTMLAttributes
export const Card = ({ elevated = false, className, children, ...props }: CardProps) => { return (
Interaction States Hover States // Figma: Background changes from #3B82F6 to #2563EB on hover className={cn( 'bg-primary-500', 'hover:bg-primary-600', 'transition-colors duration-200' )}
Focus States // Accessible focus ring className={cn( 'focus:outline-none', 'focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2' )}
Active/Pressed States // Figma: Slightly darker on click className={cn( 'active:bg-primary-700', 'active:scale-[0.98]', // Slight scale down 'transition-all duration-100' )}
Disabled States // Figma: 50% opacity, no interactions className={cn( 'disabled:opacity-50', 'disabled:cursor-not-allowed', 'disabled:pointer-events-none' )}
Responsive Design Translation Breakpoint Mapping // Figma artboards → Tailwind breakpoints // Mobile (375px): default (no prefix) // Tablet (768px): md: // Desktop (1024px): lg: // Wide (1280px): xl:
Responsive Typography // Figma mobile: 14px, desktop: 16px
Responsive Heading
Responsive Spacing // Figma mobile: 16px padding, desktop: 24px
Design System Integration Using shadcn/ui Patterns // Leveraging shadcn's composable approach import { cn } from "@/lib/utils";
const buttonVariants = cva( "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background", { variants: { variant: { default: "bg-primary text-primary-foreground hover:bg-primary/90", destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90", outline: "border border-input hover:bg-accent hover:text-accent-foreground", secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80", ghost: "hover:bg-accent hover:text-accent-foreground", link: "underline-offset-4 hover:underline text-primary", }, size: { default: "h-10 py-2 px-4", sm: "h-9 px-3 rounded-md", lg: "h-11 px-8 rounded-md", icon: "h-10 w-10", }, }, defaultVariants: { variant: "default", size: "default", }, } );
Color System Translation From Figma to CSS Variables / Figma colors → CSS variables / :root { / Primary from Figma #3B82F6 / --primary: 221 83% 60%; --primary-foreground: 0 0% 100%;
/ Secondary from Figma #6B7280 / --secondary: 220 9% 46%; --secondary-foreground: 0 0% 100%;
/ Backgrounds / --background: 0 0% 100%; --foreground: 222 47% 11%;
/ Borders / --border: 220 13% 91%; --input: 220 13% 91%; --ring: 221 83% 60%;
/ Radius from Figma / --radius: 0.5rem; }
Using in Components
Animation & Transitions Micro-interactions from Figma // Figma: Button scales slightly on hover
// Figma: Card lifts on hover
// Figma: Fade in on mount
Measurement Conversion Figma Pixels → Tailwind Classes Figma Tailwind Value 2px 0.5 0.125rem 4px 1 0.25rem 8px 2 0.5rem 12px 3 0.75rem 16px 4 1rem 20px 5 1.25rem 24px 6 1.5rem 32px 8 2rem 40px 10 2.5rem 48px 12 3rem Custom Values // Figma: 18px (not in default Tailwind)
Accessibility Mapping From Visual Design to A11y // Figma shows disabled state <button disabled={isDisabled} aria-disabled={isDisabled} className={cn( isDisabled && 'opacity-50 cursor-not-allowed' )}
Submit
// Figma shows error state
Common Patterns Form Input Translation
Figma Specs:
Height: 44px Padding: 12px 16px Border: 1px #D1D5DB Border radius: 8px Focus border: 2px #3B82F6
Icon Button Translation
Figma Specs:
Size: 40x40px Icon: 20x20px centered Border radius: 8px Background hover: #F3F4F6 <button className={cn( "flex h-10 w-10 items-center justify-center rounded-lg", "text-gray-700 transition-colors", "hover:bg-gray-100", "focus-visible:ring-2 focus-visible:ring-primary-500" )}
Best Practices Measure twice: Verify all measurements match Figma exactly Use design tokens: Map to tokens, not hardcoded values All states: Include hover, focus, active, disabled, error Responsive: Implement all breakpoints from design Accessibility: Add ARIA where Figma shows states Animations: Match transition timings to design Dark mode: If designs exist, implement with class variants Component variants: Create reusable variant props Documentation: Note any deviations from design Review: Get designer approval on implementation Output Checklist
Every design-to-component translation should include:
Exact spacing matching Figma measurements Typography scales and weights All color values from design system Border radius and shadows Hover state styling Focus state styling (accessible) Active/pressed state styling Disabled state styling Responsive breakpoint rules Design token mapping documented Accessibility attributes Component variants for states