shadcn/ui: The Copy-Paste Model
shadcn/ui is a collection of pre-styled, accessible React components built on top of Radix UI primitives and Tailwind CSS. Unlike a traditional npm component library, components are distributed as copy-pasteable source code -- via a CLI -- directly into your project, not installed as an opaque node_modules dependency.
Adding a Component
npx shadcn init # generates components.json based on your
# project setup (Tailwind config, TS usage)
npx shadcn add button dialog card
# Copies the actual .tsx source for these components directly into
# components/ui/ -- NOT added to package.json as a versioned dependencyWhy Copy-Paste Instead of npm install
Since the component's actual source lives directly in your project, you can freely read, modify, and fully customize any part of it -- styling, behavior, structure -- without fighting a traditional library's theming API or waiting for an upstream maintainer. The tradeoff: your project now owns and must maintain its own copy of that code.
Built on Radix UI + Tailwind
// components/ui/button.tsx -- simplified
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/utils'
// cva structures a component's variants (variant, size) and the
// Tailwind classes each combination applies -- avoids a tangle of
// manual conditional className logic
const buttonVariants = cva(
'inline-flex items-center justify-center rounded-md text-sm font-medium',
{
variants: {
variant: {
default: 'bg-primary text-primary-foreground',
destructive: 'bg-destructive text-destructive-foreground',
},
size: {
sm: 'h-8 px-3',
lg: 'h-10 px-8',
},
},
}
)
export function Button({ className, variant, size, ...props }) {
return (
<button
className={cn(buttonVariants({ variant, size }), className)}
{...props}
/>
)
}Interactive Components Inherit Radix's Accessibility
A shadcn/ui Dialog correctly traps focus and supports Escape-to-close not because shadcn/ui reimplemented that logic, but because it's built directly on top of @radix-ui/react-dialog -- shadcn/ui's specific contribution is the visual styling layered on top of an already-correct accessible foundation.
Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free