Skip to main content
shadcn-ui shadcn/ui component library patterns. Covers CLI usage, installation, component categories, theming with CSS variables, dark mode setup, and integration with React Hook Form + Zod. Use when adding UI components, setting up design systems, or implementing forms with shadcn/ui.
Jump to install Skills Marketplace Discover and explore AI skills built by the community.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Copy promptShow prompt details A direct command skips the review prompt. Inspect the source before running it.
npx skills add https://github.com/MadAppGang/claude-code --skill shadcn-uiThe command stays on one line. Scroll horizontally to inspect it before copying.
Prefer a local copy? Download the files currently available to SkillsMP.
Download Zip Downloading... More from this repository
Based on SOC occupation classification
name shadcn-ui description shadcn/ui component library patterns. Covers CLI usage, installation, component categories, theming with CSS variables, dark mode setup, and integration with React Hook Form + Zod. Use when adding UI components, setting up design systems, or implementing forms with shadcn/ui.
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"
,
"hooks"
:
"@/hooks"
}
}
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
npx shadcn@latest add button
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 npm install tailwindcss @tailwindcss/vite
Step 3: Configure TypeScript paths
{
"files" : [ ] ,
"references" : [
{ "path" : "./tsconfig.app.json" } ,
{ "path" : "./tsconfig.node.json" }
] ,
"compilerOptions" : {
"baseUrl" : "." ,
"paths" : {
"@/*" : [ "./src/*" ]
}
}
}
{
"compilerOptions" : {
"baseUrl" : "." ,
"paths" : {
"@/*" : [ "./src/*" ]
}
}
}
npm install -D @types/node
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 add button
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) npm install class-variance-authority clsx tailwind-merge lucide-react tw-animate-css
Step 3: Configure path aliases
{
"compilerOptions" : {
"baseUrl" : "." ,
"paths" : {
"@/*" : [ "./*" ]
}
}
}
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 : oklch (0.97 0 0 );
--muted-foreground : oklch (0.556 0 0 );
--accent : oklch (0.97 0 0 );
--accent-foreground : oklch (0.205 0 0 );
--destructive : oklch (0.577 0.245 27.325 );
--destructive-foreground : oklch (0.577 0.245 27.325 );
--border : oklch (0.922 0 0 );
--input : oklch (0.922 0 0 );
--ring : oklch (0.708 0 0 );
--chart-1 : oklch (0.646 0.222 41.116 );
--chart-2 : oklch (0.6 0.118 184.704 );
--chart-3 : oklch (0.398 0.07 227.392 );
--chart-4 : oklch (0.828 0.189 84.429 );
--chart-5 : oklch (0.769 0.188 70.08 );
--radius : 0.625rem ;
--sidebar : oklch (0.985 0 0 );
--sidebar-foreground : oklch (0.145 0 0 );
--sidebar-primary : oklch (0.205 0 0 );
--sidebar-primary-foreground : oklch (0.985 0 0 );
--sidebar-accent : oklch (0.97 0 0 );
--sidebar-accent-foreground : oklch (0.205 0 0 );
--sidebar-border : oklch (0.922 0 0 );
--sidebar-ring : oklch (0.708 0 0 );
}
.dark {
--background : oklch (0.145 0 0 );
--foreground : oklch (0.985 0 0 );
--card : oklch (0.145 0 0 );
--card-foreground : oklch (0.985 0 0 );
--popover : oklch (0.145 0 0 );
--popover-foreground : oklch (0.985 0 0 );
--primary : oklch (0.985 0 0 );
--primary-foreground : oklch (0.205 0 0 );
--secondary : oklch (0.269 0 0 );
--secondary-foreground : oklch (0.985 0 0 );
--muted : oklch (0.269 0 0 );
--muted-foreground : oklch (0.708 0 0 );
--accent : oklch (0.269 0 0 );
--accent-foreground : oklch (0.985 0 0 );
--destructive : oklch (0.396 0.141 25.723 );
--destructive-foreground : oklch (0.637 0.237 25.331 );
--border : oklch (0.269 0 0 );
--input : oklch (0.269 0 0 );
--ring : oklch (0.439 0 0 );
--chart-1 : oklch (0.488 0.243 264.376 );
--chart-2 : oklch (0.696 0.17 162.48 );
--chart-3 : oklch (0.769 0.188 70.08 );
--chart-4 : oklch (0.627 0.265 303.9 );
--chart-5 : oklch (0.645 0.246 16.439 );
--sidebar : oklch (0.205 0 0 );
--sidebar-foreground : oklch (0.985 0 0 );
--sidebar-primary : oklch (0.488 0.243 264.376 );
--sidebar-primary-foreground : oklch (0.985 0 0 );
--sidebar-accent : oklch (0.269 0 0 );
--sidebar-accent-foreground : oklch (0.985 0 0 );
--sidebar-border : oklch (0.269 0 0 );
--sidebar-ring : oklch (0.439 0 0 );
}
@theme inline {
--color-background : var (--background);
--color-foreground : var (--foreground);
--color-card : var (--card);
--color-card-foreground : var (--card-foreground);
--color-popover : var (--popover);
--color-popover-foreground : var (--popover-foreground);
--color-primary : var (--primary);
--color-primary-foreground : var (--primary-foreground);
--color-secondary : var (--secondary);
--color-secondary-foreground : var (--secondary-foreground);
--color-muted : var (--muted);
--color-muted-foreground : var (--muted-foreground);
--color-accent : var (--accent);
--color-accent-foreground : var (--accent-foreground);
--color-destructive : var (--destructive);
--color-destructive-foreground : var (--destructive-foreground);
--color-border : var (--border);
--color-input : var (--input);
--color-ring : var (--ring);
--color-chart-1 : var (--chart-1 );
--color-chart-2 : var (--chart-2 );
--color-chart-3 : var (--chart-3 );
--color-chart-4 : var (--chart-4 );
--color-chart-5 : var (--chart-5 );
--radius-sm : calc (var (--radius) - 4px );
--radius-md : calc (var (--radius) - 2px );
--radius-lg : var (--radius);
--radius-xl : calc (var (--radius) + 4px );
--color-sidebar : var (--sidebar);
--color-sidebar-foreground : var (--sidebar-foreground);
--color-sidebar-primary : var (--sidebar-primary);
--color-sidebar-primary-foreground : var (--sidebar-primary-foreground);
--color-sidebar-accent : var (--sidebar-accent);
--color-sidebar-accent-foreground : var (--sidebar-accent-foreground);
--color-sidebar-border : var (--sidebar-border);
--color-sidebar-ring : var (--sidebar-ring);
}
@layer base {
* {
@apply border-border outline-ring/50 ;
}
body {
@apply bg-background text-foreground;
}
}
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" ,
"lib" : "@/lib" ,
"hooks" : "@/hooks"
} ,
"iconLibrary" : "lucide"
}
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:
Browse components from registries
Search components by name or description
Install components using natural language
Works with Claude Code, Cursor, VS Code, Codex
{
"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" > <IconName /> </Button >
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 : z.infer<typeof formSchema> ) {
console .log (values)
}
return (
<Form {...form }>
<form onSubmit ={form.handleSubmit(onSubmit)} className ="space-y-4" >
<FormField
control ={form.control}
name ="email"
render ={({ field }) => (
<FormItem >
<FormLabel > Email</FormLabel >
<FormControl >
<Input placeholder ="email@example.com" {...field } />
</FormControl >
<FormMessage />
</FormItem >
)}
/>
<FormField
control ={form.control}
name ="password"
render ={({ field }) => (
<FormItem >
<FormLabel > Password</FormLabel >
<FormControl >
<Input type = { } />
)}
/>
Submit
)
}
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% 9% ;
--destructive : 0 84.2% 60.2% ;
--destructive-foreground : 0 0% 98% ;
--border : 0 0% 89.8% ;
--input : 0 0% 89.8% ;
--ring : 0 0% 3.9% ;
--radius : 0.5rem ;
}
.dark {
--background : 0 0% 3.9% ;
--foreground : 0 0% 98% ;
}
}
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
Ensure Tailwind CSS is properly configured
Check that index.css imports are correct
Verify CSS variables are defined in :root
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
"password"
...field
</FormControl >
<FormMessage />
</FormItem >
<Button type ="submit" >
</Button >
</form >
</Form >