A collection of beautifully designed, accessible UI components built with Radix UI and Tailwind CSS
shadcn/ui is a collection of accessible and customizable UI components that you can copy and paste into your applications. It's built on top of Radix UI and Tailwind CSS, allowing you to build your own component library with beautiful defaults and complete customization.
# Initialize your project
npx shadcn@latest init
# Add components
npx shadcn@latest add button
npx shadcn@latest add card
npx shadcn@latest add input
Create a components.json file to customize your setup:
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "tailwind.config.js",
"css": "src/styles/globals.css",
"baseColor": "neutral",
"cssVariables": true
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui"
}
}
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
export default function Example() {
return (
<Card>
<CardHeader>
<CardTitle>Welcome</CardTitle>
</CardHeader>
<CardContent>
<Button>Get Started</Button>
</CardContent>
</Card>
);
}
# Add single component
npx shadcn@latest add button
# Add multiple components
npx shadcn@latest add button card input
# Add from custom registry
npx shadcn@latest add @v0/dashboard
Components use Class Variance Authority (CVA) for variants:
// Button with variants
<Button variant="destructive" size="sm">
Delete
</Button>
<Card className="shadow-lg">
<CardHeader>
<CardTitle>Custom Card</CardTitle>
</CardHeader>
</Card>
Add CSS variables for theming:
@layer base {
:root {
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96%;
--secondary-foreground: 222.2 47.4% 11.2%;
}
.dark {
--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 11.2%;
}
}
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
function FormField({ label, ...props }) {
return (
<div className="space-y-2">
<Label htmlFor={props.id}>{label}</Label>
<Input {...props} />
</div>
);
}
import {
AlertDialog,
AlertDialogAction,
AlertDialogContent,
} from "@/components/ui/alert-dialog";
function ConfirmDialog() {
return (
<AlertDialog>
<AlertDialogContent>
<AlertDialogAction>Confirm</AlertDialogAction>
</AlertDialogContent>
</AlertDialog>
);
}
breadcrumb - Navigation breadcrumbnavigation-menu - Dropdown navigationmenubar - Application menu barinput - Text input fieldbutton - Action buttonselect - Dropdown selectcheckbox - Checkbox inputradio-group - Radio button groupcard - Content containerdialog - Modal dialogsheet - Slide-out paneltabs - Tabbed contenttable - Data tablebadge - Status indicatoravatar - User avatarseparator - Visual dividertoast - Notification messagealert - Alert messageprogress - Progress indicatorspinner - Loading indicatorFor projects not using the CLI:
npm install class-variance-authority clsx tailwind-merge lucide-react
// src/lib/utils.ts
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}