shadcn/ui
Accessible UI components you own — copy-paste into your project, customize freely, no dependency lock-in.
Read this to understand how Catalyst handles UI components.
Useful when adding components, customizing styles, or extending functionality.
Why shadcn/ui
shadcn/ui is not a component library — it's a collection. You copy components into your project and own them completely. No version conflicts, no waiting for fixes, no abstraction layers.
Components are built on Radix UI primitives for accessibility and styled with Tailwind CSS. They're designed to be customized — the code in your project is the source of truth.
Key Concepts
What makes shadcn/ui different:
You Own the Code
Components live in your repo. Customize freely, fix bugs immediately, extend as needed.
Accessible by Default
Built on Radix UI. Keyboard navigation, screen readers, and ARIA attributes handled.
Tailwind Styled
Utility classes throughout. Consistent with the rest of your Tailwind codebase.
Catalyst Patterns
How Catalyst organizes shadcn components:
Component Location
All shadcn components live in components/ui/
components/ ├── ui/ # shadcn components │ ├── button.tsx │ ├── input.tsx │ ├── dialog.tsx │ └── ... ├── core/ # Catalyst primitives (Stack, Text, etc.) ├── shared/ # App-specific components └── vendor/ # Third-party wrappers
CVA Variants
Components use class-variance-authority for variant props
import { cva } from "class-variance-authority"
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-md",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground",
outline: "border border-input bg-background",
ghost: "hover:bg-accent",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 px-3",
lg: "h-11 px-8",
},
},
}
)Composition Pattern
Complex components use compound pattern
// Compound components for flexibility
<Card>
<CardHeader>
<CardTitle>Title</CardTitle>
<CardDescription>Description</CardDescription>
</CardHeader>
<CardContent>Content here</CardContent>
<CardFooter>Actions</CardFooter>
</Card>Adding Components
Add new shadcn components with the CLI:
Terminal
# Add a single component pnpm dlx shadcn@latest add dialog # Add multiple components pnpm dlx shadcn@latest add dialog sheet tooltip # See available components pnpm dlx shadcn@latest add
The CLI copies components to components/ui/ and installs any required dependencies.
Key Files
components/ui/All shadcn components — button, input, dialog, etc.
components.jsonshadcn CLI configuration — paths, aliases, style
lib/utils.tscn() utility for merging Tailwind classes
Customization
Since you own the code, customize directly:
Change default styles
Edit the component file directly. Change colors, sizes, or behaviors.
Add new variants
Add to the CVA variants object. New props available immediately.
Extend functionality
Add props, composition, or wrap with additional logic.
Fix bugs
Don't wait for upstream — fix issues directly in your code.
Learn More
For AI Agents
Key rules:
- Never use raw HTML elements when a shadcn component exists
- Check
components/ui/before creating new components - Use
pnpm dlx shadcn@latest add [component]to add new ones - Customize by editing the component file directly
- Follow the CVA pattern for new variants
- Read
components/COMPONENTS.mdfor folder conventions
Next Steps
Related packages: