What is shadcn/ui?
shadcn/ui is not a component library — it's a collection of reusable React components that you copy into your project. Unlike Material UI or Chakra where you depend on a package, shadcn/ui components live in YOUR codebase. You own them, customize them, and they never break due to library updates.
Why shadcn/ui?
- You own the code — components copied into your project, not imported from node_modules
- Built on Radix UI — accessible, unstyled primitives under the hood
- Tailwind CSS — style with utility classes, fully customizable
- TypeScript — full type safety out of the box
- CLI installer — add components with one command
- Beautiful defaults — looks professional without any customization
Quick Start
# Initialize in your Next.js/Vite project
npx shadcn@latest init
# Add components
npx shadcn@latest add button
npx shadcn@latest add card
npx shadcn@latest add dialog
npx shadcn@latest add form
npx shadcn@latest add table
Usage
import { Button } from '@/components/ui/button';
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
export function Dashboard() {
return (
<Card>
<CardHeader>
<CardTitle>Welcome Back</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<Input placeholder="Search..." />
<div className="flex gap-2">
<Button>Primary Action</Button>
<Button variant="outline">Secondary</Button>
<Button variant="destructive">Delete</Button>
<Button variant="ghost">Ghost</Button>
</div>
</CardContent>
</Card>
);
}
Forms with React Hook Form + Zod
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { Form, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
const schema = z.object({
email: z.string().email(),
password: z.string().min(8)
});
export function LoginForm() {
const form = useForm({ resolver: zodResolver(schema) });
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
<FormField control={form.control} name="email" render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<Input {...field} />
<FormMessage />
</FormItem>
)} />
<FormField control={form.control} name="password" render={({ field }) => (
<FormItem>
<FormLabel>Password</FormLabel>
<Input type="password" {...field} />
<FormMessage />
</FormItem>
)} />
<Button type="submit">Login</Button>
</form>
</Form>
);
}
Data Tables
import { DataTable } from '@/components/ui/data-table';
import { ColumnDef } from '@tanstack/react-table';
const columns: ColumnDef<User>[] = [
{ accessorKey: 'name', header: 'Name' },
{ accessorKey: 'email', header: 'Email' },
{ accessorKey: 'role', header: 'Role',
cell: ({ row }) => (
<Badge variant={row.getValue('role') === 'admin' ? 'default' : 'secondary'}>
{row.getValue('role')}
</Badge>
)
},
];
export function UsersTable({ data }: { data: User[] }) {
return <DataTable columns={columns} data={data} />;
}
Theming
/* globals.css — customize your design system */
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
--destructive: 0 84.2% 60.2%;
--radius: 0.5rem;
}
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
}
}
shadcn/ui vs Alternatives
| Feature | shadcn/ui | Material UI | Chakra UI | Ant Design |
|---|---|---|---|---|
| Code ownership | You own it | Package dep | Package dep | Package dep |
| Customization | Full control | Theme + sx | Theme + props | Less config |
| Bundle size | Only what you use | 300KB+ | 200KB+ | 400KB+ |
| Accessibility | Radix primitives | Built-in | Built-in | Partial |
| Styling | Tailwind | Emotion/styled | Emotion | Less/CSS |
| Breaking updates | Never | Major versions | Major versions | Frequent |
Real-World Impact
A team used Material UI v4. When MUI v5 launched with breaking changes, the migration took 3 weeks — every styled component had to be rewritten. With shadcn/ui: the components are in YOUR codebase. There are no library updates to break things. When the team wanted to change the button style, they edited one file — not fought with theme overrides.
Building modern React UIs? I help teams set up design systems that scale. Contact spinov001@gmail.com or explore my data tools on Apify.
Top comments (0)