shadcn/ui

Foundationlatest

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.json

shadcn CLI configuration — paths, aliases, style

lib/utils.ts

cn() 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.md for folder conventions

Next Steps

Related packages: