A quick overview of the basics of shadcn/ui (often colloquially called shad/ui) , bias Front-end engineering practice , suitable for people who already know React + Tailwind developers get started quickly.
1. What is shadcn/ui?
shadcn/ui ≠ component library
It is a component source code collection + CLI tool
Core features:
- ✅ Not a black box component installed by npm
- ✅ Copy the component code directly into your project
- ✅ Based on Radix UI (no style, high accessibility)
- ✅ Use Tailwind CSS to write styles
- ✅ Highly customizable and maintainable
In one sentence:
You own the component instead of relying on a component library
2. Core technology stack
| Technology | Function |
|---|---|
| React | Component System |
| Radix UI | Accessible interaction logic (Dialog / Dropdown / Popover, etc.) |
| Tailwind CSS | Style System |
| class-variance-authority (CVA) | Component variant management |
| lucide-react | default icon |
| clsx + tailwind-merge | className merge |
3. Installation and initialization (core process)
bash
npx shadcn@latest initThings you will do:
Check if you have Tailwind
Generate configuration file
components.jsonCreate directory:
components/ ui/ lib/ utils.ts
4. Where do the components come from?
bash
npx shadcn@latest add buttonResult:
components/ui/button.tsx👉 Source code directly into your project
tsx
// components/ui/button.tsx
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-md text-sm font-medium",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground",
outline: "border border-input bg-background",
},
size: {
sm: "h-9 px-3",
lg: "h-11 px-8",
},
},
defaultVariants: {
variant: "default",
size: "sm",
},
}
)5. CVA (Core Focus)
The soul of shadcn/ui
1️⃣ Why not use a bunch of classNames?
❌ Bad way:
tsx
<button className={`
px-4 py-2
${primary && "bg-blue-500"}
${size === "lg" && "text-lg"}
`} />✅ shadcn/ui:
tsx
<Button variant="outline" size="lg" />2️⃣ CVA principle
ts
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-md font-medium",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground",
outline: "border border-input",
ghost: "hover:bg-accent",
},
size: {
sm: "h-9 px-3",
md: "h-10 px-4",
lg: "h-11 px-8",
},
},
defaultVariants: {
variant: "default",
size: "md",
},
}
)Finally:
ts
buttonVariants({ variant: "outline", size: "lg" })6. The role of Radix UI
Radix offers:
- keyboard accessibility
- focus management
- ARIA
- behavioral logic
For example Dialog:
tsx
<Dialog>
<DialogTrigger>Open</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Title</DialogTitle>
</DialogHeader>
</DialogContent>
</Dialog>What shadcn/ui does:
- Give Radix component Set Tailwind style
- Unify API style
7. Theme system (CSS Variables)
shadcn/ui Don’t hardcode colors
css
:root {
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
}When using:
tsx
bg-primary text-primary-foregroundAdvantages:
- 🌗 Natural support for dark mode
- 🎨Theme switching cost is extremely low
8. Common directory structures
txt
components/
ui/
button.tsx
dialog.tsx
dropdown-menu.tsx
lib/
utils.ts // cn() 工具函数utils.ts:
ts
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}9. Use paradigm (very important)
1️⃣ Composition instead of inheritance
tsx
<Button asChild>
<Link href="/login">Login</Link>
</Button>asChild is based on Radix Slot
2️⃣ Do not change the UI component logic
❌
tsx
components/ui/button.tsx✅
tsx
components/common/submit-button.tsx10. What projects is it suitable for?
- ✅ Medium to large React / Next.js projects
- ✅ Design System / Design System
- ❌ Not suitable for novice projects that “install and use”
11. To what extent do you know how to learn?
You can do:
- Understand the shadcn/ui component source code
- Write a component with CVA yourself
- Encapsulating business components based on Radix
- Customize the theme instead of changing the class
12. Learning path suggestions (give you an advanced route)
- Familiar with Button/Input/Dialog source code
- Learn CVA
- Dive into Radix (Dialog/Popover/Dropdown)
- Encapsulate a component yourself (eg: DataTable)
- Design a set of theme variables