| name | shadcn-ui |
| description | Use when implementing UI components with shadcn/ui. Covers component installation, configuration with Vite/TanStack Router, CLI commands, and integration with Tailwind CSS. |
| updated | "2026-01-20T00:00:00.000Z" |
| keywords | shadcn, ui-components, tailwind, react, radix-ui, component-library |
shadcn/ui Component Library
shadcn/ui is a collection of beautifully-designed, accessible components and a code distribution platform. It is built with TypeScript, Tailwind CSS, and Radix UI primitives. It supports multiple frameworks including Next.js, Vite, Remix, Astro, and more. Open Source. Open Code. AI-Ready. It also comes with a command-line tool to install and manage components and a registry system to publish and distribute code.
Key Principles
- Open Code: Components are copied into your project, not installed as dependencies
- Composition: Build complex UIs by composing simple components
- Distribution: CLI and registry system for easy component management
- Beautiful Defaults: Production-ready styling out of the box
- AI-Ready: Designed to work well with AI assistants
Quick Reference
CLI Commands
npx shadcn@latest init
npx shadcn@latest add button
npx shadcn@latest add button card dialog
npx shadcn@latest add --all
npx shadcn@latest diff
npx shadcn@latest add
Configuration (components.json)
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "tailwind.config.js",
"css": "src/index.css",
"baseColor": "neutral",
"cssVariables": true
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib"
Documentation Index
Overview
Installation by Framework
Installation Instructions
TanStack Router (Recommended)
The fastest way to get started with shadcn/ui and TanStack Router:
npx create-tsrouter-app@latest my-app --template file-router --tailwind --add-ons shadcn
Then add components:
npx shadcn@latest add button
Usage in routes:
import { createFileRoute } from "@tanstack/react-router"
import { Button } from "@/components/ui/button"
export const Route = createFileRoute("/")({
component: App,
})
function App() {
return (
<div>
<Button>Click me</Button>
</div>
)
}
Vite Installation
Step 1: Create project
npm create vite@latest
Step 2: Add Tailwind CSS
npm install tailwindcss @tailwindcss/vite
Replace src/index.css:
@import "tailwindcss";
Step 3: Configure TypeScript paths
Edit tsconfig.json:
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
],
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}
Edit tsconfig.app.json:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}
Step 4: Configure Vite
npm install -D @types/node
Edit vite.config.ts:
import path from "path"
import tailwindcss from "@tailwindcss/vite"
import react from "@vitejs/plugin-react"
import { defineConfig } from "vite"
export default defineConfig({
plugins: [react(), tailwindcss()],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
})
Step 5: Initialize shadcn/ui
npx shadcn@latest init
Step 6: Add components
npx shadcn@latest add button
Usage:
import { Button } from "@/components/ui/button"
function App() {
return (
<div className="flex min-h-svh flex-col items-center justify-center">
<Button>Click me</Button>
</div>
)
}
export default App
Manual Installation (Without CLI)
Step 1: Add Tailwind CSS
Follow the Tailwind CSS installation guide.
Step 2: Add dependencies
npm install class-variance-authority clsx tailwind-merge lucide-react tw-animate-css
Step 3: Configure path aliases
In tsconfig.json:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./*"]
}
}
}
Step 4: Configure styles
Create src/styles/globals.css:
@import "tailwindcss";
@import "tw-animate-css";
@custom-variant dark (&:is(.dark *));
:root {
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--card: oklch(1 0 0);
--card-foreground: oklch(0.145 0 0);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.97 0 0);
--secondary-foreground: oklch(0.205 0 0);
--muted: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ;
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
}
{
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
: ( );
}
inline {
: (--background);
: (--foreground);
: (--card);
: (--card-foreground);
: (--popover);
: (--popover-foreground);
: (--primary);
: (--primary-foreground);
: (--secondary);
: (--secondary-foreground);
: (--muted);
: (--muted-foreground);
: (--accent);
: (--accent-foreground);
: (--destructive);
: (--destructive-foreground);
: (--border);
: (--input);
: (--ring);
: (--chart-);
: (--chart-);
: (--chart-);
: (--chart-);
: (--chart-);
: ((--radius) - );
: ((--radius) - );
: (--radius);
: ((--radius) + );
: (--sidebar);
: (--sidebar-foreground);
: (--sidebar-primary);
: (--sidebar-primary-foreground);
: (--sidebar-accent);
: (--sidebar-accent-foreground);
: (--sidebar-border);
: (--sidebar-ring);
}
base {
* {
border-border outline-ring/;
}
{
bg-background text-foreground;
}
}
Step 5: Add cn() helper
Create lib/utils.ts:
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
Step 6: Create components.json
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "",
"css": "src/styles/globals.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
Step 7: Add components
npx shadcn@latest add button
Components Reference
Form & Input Components
Layout & Navigation Components
Overlay & Dialog Components
Feedback & Status Components
Display & Media Components
Miscellaneous Components
Dark Mode Setup
Forms Integration
Advanced Topics
MCP Server Integration
shadcn/ui provides an MCP (Model Context Protocol) server for AI integrations:
URL: https://ui.shadcn.com/docs/mcp
Features:
- Browse components from registries
- Search components by name or description
- Install components using natural language
- Works with Claude Code, Cursor, VS Code, Codex
Setup for Claude Code:
{
"mcpServers": {
"shadcn": {
"command": "npx",
"args": ["-y", "shadcn@canary", "mcp"]
}
}
}
Registry System
Registry Schemas
Common Patterns
Installing Components for a Feature
npx shadcn@latest add button input form label card
npx shadcn@latest add sidebar navigation-menu breadcrumb avatar dropdown-menu
npx shadcn@latest add table data-table pagination skeleton
npx shadcn@latest add form field input select checkbox radio-group switch calendar date-picker combobox
npx shadcn@latest add alert toast dialog alert-dialog
File Structure After Installation
src/
โโโ components/
โ โโโ ui/
โ โโโ button.tsx
โ โโโ card.tsx
โ โโโ dialog.tsx
โ โโโ ...
โโโ lib/
โ โโโ utils.ts # cn() utility function
โโโ index.css # Tailwind + CSS variables
The cn() Utility
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
<Button className={cn("w-full", isLoading && "opacity-50")} />
Button Variants
<Button variant="default">Default</Button>
<Button variant="destructive">Destructive</Button>
<Button variant="outline">Outline</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>
<Button size="default">Default</Button>
<Button size="sm">Small</Button>
<Button size="lg">Large</Button>
<Button size="icon">< />
Form with React Hook Form + Zod
import { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import * as z from "zod"
import { Button } from "@/components/ui/button"
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"
import { Input } from "@/components/ui/input"
const formSchema = z.object({
email: z.string().email(),
password: z.string().min(8),
})
export function LoginForm() {
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: { email: "", password: "" },
})
function onSubmit() {
.(values)
}
(
)
}
Data Table with TanStack Table
import { DataTable } from "@/components/ui/data-table"
import { ColumnDef } from "@tanstack/react-table"
type User = {
id: string
name: string
email: string
}
const columns: ColumnDef<User>[] = [
{ accessorKey: "name", header: "Name" },
{ accessorKey: "email", header: "Email" },
]
export function UsersTable({ data }: { data: User[] }) {
return <DataTable columns={columns} data={data} />
}
Theming
CSS Variables
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 0 0% 3.9%;
--card: 0 0% 100%;
--card-foreground: 0 0% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 0 0% 3.9%;
--primary: 0 0% 9%;
--primary-foreground: 0 0% 98%;
--secondary: 0 0% 96.1%;
--secondary-foreground: 0 0% 9%;
--muted: 0 0% 96.1%;
--muted-foreground: 0 0% 45.1%;
--accent: 0 0% 96.1%;
--accent-foreground: 0 0% ;
: ;
: ;
: ;
: ;
: ;
: ;
}
{
: ;
: ;
}
}
Using Theme Colors
<div className="bg-background text-foreground" />
<div className="bg-primary text-primary-foreground" />
<div className="bg-secondary text-secondary-foreground" />
<div className="bg-muted text-muted-foreground" />
<div className="bg-accent text-accent-foreground" />
<div className="bg-destructive text-destructive-foreground" />
<div className="border-border" />
<div className="ring-ring" />
Best Practices
1. Component Organization
src/components/
โโโ ui/ # shadcn/ui components (don't modify directly)
โ โโโ button.tsx
โ โโโ ...
โโโ forms/ # Form-specific compositions
โ โโโ login-form.tsx
โ โโโ ...
โโโ layout/ # Layout components
โ โโโ header.tsx
โ โโโ sidebar.tsx
โโโ features/ # Feature-specific components
โโโ dashboard/
2. Extending Components
import { Button } from "@/components/ui/button"
export function LoadingButton({ loading, children, ...props }) {
return (
<Button disabled={loading} {...props}>
{loading ? <Spinner className="mr-2" /> : null}
{children}
</Button>
)
}
3. Consistent Spacing
<div className="space-y-4"> {}
<Card className="p-6"> {}
<CardHeader className="pb-4"> {}
<CardContent className="pt-0">
</Card>
</div>
4. Responsive Design
<Dialog>
<DialogContent className="sm:max-w-[425px]">
{/* Mobile: full width, Desktop: max 425px */}
</DialogContent>
</Dialog>
<Sheet side="left" className="w-[300px] sm:w-[400px]">
{/* Responsive sidebar width */}
</Sheet>
Integration with This Plugin
This skill complements other frontend plugin skills:
- react-patterns: React 19 patterns work with shadcn/ui components
- tanstack-router: Type-safe routing with shadcn/ui layouts
- tanstack-query: Data fetching for Data Tables and forms
- api-integration: API types for form validation schemas
- tooling-setup: Vite + Tailwind setup for shadcn/ui
Recommended Installation Order
- Set up Vite + React + TypeScript + Tailwind (tooling-setup skill)
- Initialize shadcn/ui:
npx shadcn@latest init
- Install base components:
npx shadcn@latest add button card
- Set up TanStack Router (tanstack-router skill)
- Add form components as needed
Troubleshooting
Common Issues
"Cannot find module '@/components/ui/button'"
- Check
tsconfig.json paths alias matches components.json aliases
Components look unstyled
- Ensure Tailwind CSS is properly configured
- Check that
index.css imports are correct
- Verify CSS variables are defined in
:root
Dark mode not working
- Add
dark class to <html> element
- Use a theme provider (next-themes for Next.js)
TypeScript errors with form components
- Install
@hookform/resolvers and zod
- Ensure
react-hook-form is installed