MCPInstall

shadcn-ui

shadcn/ui component patterns with Radix primitives and Tailwind styling. Use when building UI components, using CVA variants, implementing compound components, or styling with data-slot attributes. Triggers on shadcn, cva, cn(), data-slot, Radix, Button, Card, Dialog, VariantProps.

Installs
351
Last 24h
—
Trending rank
—
Security
Not audited

Install

Works with every agent the skills CLI supports.

npx skills add https://github.com/existential-birds/beagle --skill shadcn-ui
  1. 01

    Install

    Run the command in your project. The CLI asks which agents to install for.

  2. 02

    Describe the task

    Ask your agent for something this skill covers. It loads shadcn-ui automatically when relevant.

  3. 03

    Review the result

    The agent follows the SKILL.md steps, scripts and references bundled with the skill.

SKILL.md

The instructions your agent reads when the skill is triggered.

shadcn/ui Component Development

Contents

CLI Commands

Initialize shadcn/ui

npx shadcn@latest init

This creates a components.json configuration file and sets up:

  • Tailwind CSS configuration
  • CSS variables for theming
  • cn() utility function
  • Required dependencies

Add Components

# Add a single component
npx shadcn@latest add button

# Add multiple components
npx shadcn@latest add button card dialog

# Add all available components
npx shadcn@latest add --all

Important: The package name changed in 2024:

  • Old (deprecated): npx shadcn-ui@latest add
  • Current: npx shadcn@latest add

Common Options

  • -y, --yes - Skip confirmation prompt
  • -o, --overwrite - Overwrite existing files
  • -c, --cwd <cwd> - Set working directory
  • --src-dir - Use src directory structure

Gates (CLI and file changes)

Run these in order before init / add (skip only when you are not running the CLI—e.g. copying snippets from this skill):

  1. Working directory: Pass: pwd and package.json at that path identify the app root that should receive components/ and components.json (use -c <cwd> if the shell is elsewhere).
  2. After init: Pass: components.json exists at that app root (or the documented path for your monorepo layout).
  3. Before --overwrite: Pass: you can list which tracked files will be replaced, or version control shows the change is intentional and recoverable.

Quick Reference

cn() Utility

import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}

Basic CVA Pattern

import { cva, type VariantProps } from "class-variance-authority"

const buttonVariants = cva(
  "base-classes-applied-to-all-variants",
  {
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground",
        outline: "border bg-background",
      },
      size: {
        sm: "h-8 px-3",
        lg: "h-10 px-6",
      },
    },
    defaultVariants: {
      variant: "default",
      size: "sm",
    },
  }
)

function Button({
  variant,
  size,
  className,
  ...props
}: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants>) {
  return (
    <button
      className={cn(buttonVariants({ variant, size }), className)}
      {...props}
    />
  )
}

export { Button, buttonVariants }

Component Anatomy

Props Typing Patterns

// HTML elements
function Component({ className, ...props }: React.ComponentProps<"div">) {
  return <div className={cn("base-classes", className)} {...props} />
}

// Radix primitives
function Component({ className, ...props }: React.ComponentProps<typeof RadixPrimitive.Root>) {
  return <RadixPrimitive.Root className={cn("base-classes", className)} {...props} />
}

// With CVA variants
function Component({
  variant, size, className, ...props
}: React.ComponentProps<"button"> & VariantProps<typeof variants>) {
  return <button className={cn(variants({ variant, size }), className)} {...props} />
}

asChild Pattern

Enables polymorphic rendering via @radix-ui/react-slot:

import { Slot } from "@radix-ui/react-slot"

function Button({
  asChild = false,
  className,
  variant,
  size,
  ...props
}: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & { asChild?: boolean }) {
  const Comp = asChild ? Slot : "button"
  return (
    <Comp
      data-slot="button"
      className={cn(buttonVariants({ variant, size }), className)}
      {...props}
    />
  )
}

Usage:

<Button>Click me</Button>                           // Renders <button>
<Button asChild><a href="/home">Home</a></Button>   // Renders <a> with button styling
<Button asChild><Link href="/dash">Dash</Link></Button>  // Works with Next.js Link

data-slot Attributes

Every component includes data-slot for CSS targeting:

function Card({ ...props }) { return <div data-slot="card" {...props} /> }
function CardHeader({ ...props }) { return <div data-slot="card-header" {...props} /> }

CSS/Tailwind targeting:

[data-slot="button"] { /* styles */ }
[data-slot="card"] [data-slot="button"] { /* nested targeting */ }
<div className="[&_[data-slot=button]]:shadow-lg">
  <Button>Automatically styled</Button>
</div>

Conditional layouts with has():

<div
  data-slot="card-header"
  className={cn(
    "grid gap-2",
    "has-data-[slot=card-action]:grid-cols-[1fr_auto]"
  )}
/>

Component Patterns

Compound Components

export { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter }

function Card({ className, ...props }: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="card"
      className={cn("bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm", className)}
      {...props}
    />
  )
}

function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
  return <div data-slot="card-header" className={cn("grid gap-2 px-6", className)} {...props} />
}

function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
  return <div data-slot="card-title" className={cn("leading-none font-semibold", className)} {...props} />
}

Styling Techniques

CVA Variants

Multiple dimensions:

const buttonVariants = cva("base-classes", {
  variants: {
    variant: {
      default: "bg-primary text-primary-foreground",
      destructive: "bg-destructive text-white",
      outline: "border bg-background",
      ghost: "hover:bg-accent",
      link: "text-primary underline-offset-4 hover:underline",
    },
    size: {
      default: "h-9 px-4 py-2",
      sm: "h-8 px-3",
      lg: "h-10 px-6",
      icon: "size-9",
    },
  },
  defaultVariants: { variant: "default", size: "default" },
})

Compound variants:

compoundVariants: [
  { variant: "outline", size: "lg", class: "border-2" },
]

Type extraction:

type ButtonVariants = VariantProps<typeof buttonVariants>
// Result: { variant?: "default" | "outline" | ..., size?: "sm" | "lg" | ... }

Modern CSS Selectors in Tailwind

has() selector:

<button className="px-4 has-[>svg]:px-3">  // Adjusts padding when contains icon
<div className="has-data-[slot=action]:grid-cols-[1fr_auto]">  // Conditional layout

Group/peer selectors:

<div className="group" data-state="collapsed">
  <div className="group-data-[state=collapsed]:hidden">Hidden when collapsed</div>
</div>

<button className="peer/menu" data-active="true">Menu</button>
<div className="peer-data-[active=true]/menu:text-accent">Styled when sibling active</div>

Container queries:

<div className="@container/card">
  <div className="@md:flex-row">Responds to container width</div>
</div>

Accessibility States

className={cn(
  // Focus
  "outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
  // Invalid
  "aria-invalid:border-destructive aria-invalid:ring-destructive/20",
  // Disabled
  "disabled:pointer-events-none disabled:opacity-50",
)}

<span className="sr-only">Close</span>  // Screen reader only

Dark Mode

Semantic tokens adapt automatically:

className="bg-background text-foreground dark:bg-input/30 dark:hover:bg-input/50"

Tokens: bg-background, text-foreground, bg-primary, text-primary-foreground, bg-card, text-card-foreground, border-input, text-muted-foreground

Decision Tables

When to Use CVA

ScenarioUse CVAAlternative
Multiple visual variants (primary, outline, ghost)YesPlain className
Size variations (sm, md, lg)YesPlain className
Compound conditions (outline + large = thick border)YesConditional cn()
One-off custom stylingNoclassName prop
Dynamic colors from propsNoInline styles or CSS variables

When to Use Compound Components

ScenarioUse CompoundAlternative
Complex UI with multiple semantic partsYesSingle component with many props
Optional sections (header, footer)YesBoolean show/hide props
Different styling for each partYesCSS selectors
Shared state between partsYes + ContextProps drilling
Simple wrapper with childrenNoSingle component

When to Use asChild

ScenarioUse asChildAlternative
Component should work as link or buttonYesDuplicate component
Need button styles on custom elementYesExport variant styles
Integration with routing librariesYesWrapper components
Always renders same elementNoStandard component

When to Use Context

ScenarioUse ContextAlternative
Deep prop drilling (>3 levels)YesProps
State shared by many siblingsYesLift state up
Plugin/extension architectureYesProps
Simple parent-child communicationNoProps

Common Patterns

Form Input

function Input({ className, type, ...props }: React.ComponentProps<"input">) {
  return (
    <input
      type={type}
      data-slot="input"
      className={cn(
        "h-9 w-full rounded-md border px-3 py-1",
        "outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
        "aria-invalid:border-destructive aria-invalid:ring-destructive/20",
        "disabled:cursor-not-allowed disabled:opacity-50",
        "placeholder:text-muted-foreground dark:bg-input/30",
        className
      )}
      {...props}
    />
  )
}

Dialog Content

function DialogContent({ children, showCloseButton = true, ...props }) {
  return (
    <DialogPortal>
      <DialogOverlay />
      <DialogPrimitive.Content
        data-slot="dialog-content"
        className={cn(
          "fixed top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%] w-full max-w-lg",
          "bg-background border rounded-lg p-6 shadow-lg",
          "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
          "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
        )}
        {...props}
      >
        {children}
        {showCloseButton && (
          <DialogPrimitive.Close className="absolute top-4 right-4">
            <XIcon /><span className="sr-only">Close</span>
          </DialogPrimitive.Close>
        )}
      </DialogPrimitive.Content>
    </DialogPortal>
  )
}

Sidebar with Context

function SidebarProvider({ defaultOpen = true, children }) {
  const isMobile = useIsMobile()
  const [open, setOpen] = React.useState(defaultOpen)

  React.useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === "b" && (e.metaKey || e.ctrlKey)) {
        e.preventDefault()
        setOpen(o => !o)
      }
    }
    window.addEventListener("keydown", handleKeyDown)
    return () => window.removeEventListener("keydown", handleKeyDown)
  }, [])

  const contextValue = React.useMemo(
    () => ({ state: open ? "expanded" : "collapsed", open, setOpen, isMobile }),
    [open, setOpen, isMobile]
  )

  return (
    <SidebarContext.Provider value={contextValue}>
      <div
        data-slot="sidebar-wrapper"
        style={{ "--sidebar-width": "16rem", "--sidebar-width-icon": "3rem" } as React.CSSProperties}
      >
        {children}
      </div>
    </SidebarContext.Provider>
  )
}

Reference Files

For comprehensive examples and advanced patterns:

  • components.md - Full implementations: Button, Card, Badge, Input, Label, Textarea, Dialog
  • cva.md - CVA patterns: compound variants, responsive variants, type extraction
  • patterns.md - Architectural patterns: compound components, asChild, controlled state, Context, data-slot, has() selectors

FAQ

What does the shadcn-ui skill do?

shadcn/ui component patterns with Radix primitives and Tailwind styling. Use when building UI components, using CVA variants, implementing compound components, or styling with data-slot attributes. Triggers on shadcn, cva, cn(), data-slot, Radix, Button, Card, Dialog, VariantProps.

How do I install shadcn-ui?

Run npx skills add https://github.com/existential-birds/beagle --skill shadcn-ui in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/shadcn-ui/ (personal) or .claude/skills/shadcn-ui/ (project).

Which AI agents can use shadcn-ui?

Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.

Is shadcn-ui safe to install?

No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.

Who maintains shadcn-ui?

It is published by existential-birds in existential-birds/beagle. It has 351 recorded installs.

More from existential-birds/beagle

View all →

react-flow

existential-birds/beagle

React Flow (@xyflow/react) for workflow visualization with custom nodes and edges. Use when building graph visualizations, creating custom workflow nodes, implementing edge labels, or controlling viewport. Triggers on ReactFlow, @xyflow/react, Handle, NodeProps, EdgeProps, useReactFlow, fitView.

Frontend & Design1.3K installs

python-code-review

existential-birds/beagle

Reviews Python code for type safety, async patterns, error handling, and common mistakes. Use when reviewing .py files, checking type hints, async/await usage, or exception handling.

langgraph-code-review

existential-birds/beagle

Reviews LangGraph code for bugs, anti-patterns, and improvements. Use when reviewing code that uses StateGraph, nodes, edges, checkpointing, or other LangGraph features. Catches common mistakes in state management, graph structure, and async patterns.

tailwind-v4

existential-birds/beagle

Tailwind CSS v4 with CSS-first configuration and design tokens. Use when setting up Tailwind v4, defining theme variables, using OKLCH colors, or configuring dark mode. Triggers on @theme, @tailwindcss/vite, oklch, CSS variables, --color-, tailwind v4.

Frontend & Design812 installs

react-flow-advanced

existential-birds/beagle

Advanced React Flow patterns for complex use cases. Use when implementing sub-flows, custom connection lines, programmatic layouts, drag-and-drop, undo/redo, or complex state synchronization.

Frontend & Design631 installs

react-router-v7

existential-birds/beagle

React Router v7 best practices for data-driven routing. Use when implementing routes, loaders, actions, Form components, fetchers, navigation guards, protected routes, or URL search params. Triggers on createBrowserRouter, RouterProvider, useLoaderData, useActionData, useFetcher, NavLink, Outlet.

Frontend & Design573 installs

Popular frontend & design skills

View category →

setup-matt-pocock-skills

mattpocock/skills

Configure this repo for the engineering skills: set up its issue tracker, triage label vocabulary, and domain doc layout. Run once before first use of the other engineering skills.

Frontend & Design1.1M installs

frontend-design

anthropics/skills

Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one. Helps with aesthetic direction, typography, and making choices that don't read as templated defaults.

OfficialFrontend & Design1M installs

hyperframes-animation

heygen-com/hyperframes

All animation knowledge for HyperFrames — atomic motion rules, multi-phase scene blueprints, scene transitions, broader motion-design techniques, AND the seven runtime adapters (GSAP default, plus Lottie, Three.js, Anime.js, CSS keyframes, Web Animations API, TypeGPU). Use for any motion or animation task: pick 2-4 rules and compose, or load a blueprint, or look up runtime-specific API (e.g. GSAP eases / Lottie player / Three.js mixer). Also covers auditing an existing composition's choreography (animation map) and 24 named text-animation effects. HyperFrames-native: single paused timeline, seek-safe, deterministic.

prototype

mattpocock/skills

Build a throwaway prototype to answer a design question. Use when the user wants to sanity-check whether a state model or logic feels right, or explore what a UI should look like.

Frontend & Design999.2K installs

hyperframes-core

heygen-com/hyperframes

The HyperFrames composition contract — build one renderable project. Use for composition structure, the data- timing attributes, class="clip", tracks, sub-compositions, variables, framework-owned media playback, deterministic-render rules, and validation. Read before writing composition HTML.

Frontend & Design930.5K installs

vercel-react-best-practices

vercel-labs/agent-skills

React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.

OfficialFrontend & Design843.1K installs