Component Development
Build components against their specifications with correct prop APIs, variant handling, accessibility attributes, and test coverage.
AI agents excel at component scaffolding once the spec is defined. Give the agent a component specification — prop interface, variant map, accessibility requirements — and let it generate the implementation. For repetitive families (form fields, table columns, modal variants), define the pattern once: "Generate all remaining [type] following this pattern." Always verify server/client boundary and token usage.
Implementation follows the component spec from Design & Architecture. Complete spec → mechanical implementation. Incomplete spec → inconsistent design decisions across developers.
Implementation Order
Build bottom-up: primitives → composites → sections. Never build sections before primitives — leads to inline styles, duplicated logic, mismatched tokens.
Design tokens — Define all tokens in globals.css
Primitives — Button, Input, Badge. All variants and states, full test coverage
Composites — FormField, DataTable. Built from primitives, no new base styles
Layout templates — DashboardLayout, AuthLayout. Slot-based, no business logic
Feature sections — ProjectCard, TaskList. Domain-aware, uses composites + primitives
Pages — Assemble sections into layouts, wire data
Server vs Client Components
Every component is a Server Component by default. Add "use client" only when needed.
| Server Component | Client Component |
|---|---|
| Fetching data directly from DB/API | useState, useEffect, useRef |
| Static or server-computed content | User events (onClick, onSubmit) |
| Server-only env vars | Browser APIs (localStorage, navigator) |
| Large dependencies that shouldn't ship to client | Third-party libs that require DOM |
| SEO-critical content | Interactive UI: forms, modals, dropdowns |
// app/dashboard/page.tsx — Server Component (default)
import { getProjects } from "@/lib/data"
import { ProjectList } from "@/components/projects/project-list"
export default async function DashboardPage() {
// Data fetching happens on the server — no useEffect needed
const projects = await getProjects()
return <ProjectList initialProjects={projects} />
}
// components/projects/project-list.tsx
"use client" // Only added because this component uses useState for filters
import { useState } from "react"
export function ProjectList({ initialProjects }) {
const [filter, setFilter] = useState("all")
// ...
}Variant Handling with CVA
Use class-variance-authority (CVA) for type-safe variant props, colocated with the component.
Accessibility in Implementation
Accessibility goes in at the component level, not retrofitted. Non-negotiable for every interactive component:
- Keyboard: all elements reachable via Tab, activated Enter/Space, dismissed Escape
- Focus: modal opens → focus moves in. Modal closes → focus returns to trigger
- ARIA: semantic HTML first (
button,nav,dialog). ARIA only when no native element fits - Live regions: dynamic updates (toasts, form errors) use
aria-live - Labels: every form control has an associated
<label>— not just placeholder
Error Boundaries
Wrap independent UI sections so one component failure doesn't crash the page. Use error.tsx for route-level boundaries, React's ErrorBoundary for component-level isolation.
"use client"
interface ErrorPageProps {
error: Error & { digest?: string }
reset: () => void
}
export default function DashboardError({ error, reset }: ErrorPageProps) {
return (
<div role="alert" className="flex flex-col items-center gap-4 py-16">
<h2 className="text-lg font-semibold">Something went wrong</h2>
<p className="text-sm text-muted-foreground max-w-md text-center">
{error.message || "An unexpected error occurred loading the dashboard."}
</p>
<button onClick={reset} className="text-sm underline underline-offset-4">
Try again
</button>
</div>
)
}Dark Mode & Theming
Design and implement theme-aware interfaces — token architecture, system detection, persistence, toggle patterns, testing, and visual asset considerations.
Design System Integration
Work with existing component libraries — shadcn/ui, Radix, Base UI, and others — to accelerate development without sacrificing design quality or customization.