Skip to content
Back to skills

Library Shadcn

ASecurity

Provides shadcn/ui component patterns for React including installation, theming, dark mode, CVA variants, and accessibility with Radix UI primitives. Use when the user asks about building UIs with shadcn/ui, setting up component libraries, customizing themes or dark mode, or composing form patterns. Triggers: shadcn, shadcn/ui, radix, tailwind components, ui library, component library, dark mode.

  • 3 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 2, 2026
ai-agentsgobashreactvueangularnextjstestingfrontend

Works with

  • cursor
  • cli

Security analysis

A100/100

Scanned September 29, 2026

npx -y skills add Yoodaddy0311/artibot --skill library-shadcn --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Library Shadcn?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Library Shadcn
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/yoodaddy0311-library-shadcn/badge)](https://www.skillsdirectory.com/skills/yoodaddy0311-library-shadcn)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
context: fork
name: library-shadcn
description: "Provides shadcn/ui component patterns for React including installation, theming, dark mode, CVA variants, and accessibility with Radix UI primitives. Use when the user asks about building UIs with shadcn/ui, setting up component libraries, customizing themes or dark mode, or composing form patterns. Triggers: shadcn, shadcn/ui, radix, tailwind components, ui library, component library, dark mode."
lang: [en]
level: 2
triggers: ["shadcn", "shadcn/ui", "radix", "tailwind components", "ui library", "component library", "dark mode"]
agents: ["frontend-developer", "architect"]
tokens: "~4K"
category: "library"
platforms: [claude-code, gemini-cli, codex-cli, cursor]
sources:
  - "https://ui.shadcn.com/docs"
  - "https://www.radix-ui.com/primitives/docs/overview/introduction"
version: "1.0.0"
lastVerified: "2026-06-08"
source_hash: 4dcfbe9a
whenNotToUse: "Non-React frontend stacks (Vue, Svelte, Angular) or projects that do not use Tailwind CSS, where shadcn/ui component patterns cannot be directly applied."
---

# shadcn/ui Component Patterns

## Contents
- [When This Skill Applies](#when-this-skill-applies)
- [Core Guidance](#core-guidance)
- [Anti-Patterns](#anti-patterns)
- [Quick Reference](#quick-reference)

## When This Skill Applies
- Building React UIs with shadcn/ui components
- Setting up theming and dark mode support
- Composing complex UI patterns from primitive components
- Customizing component variants with Tailwind CSS
- Ensuring accessibility compliance in component usage
- Integrating shadcn/ui with Next.js, Remix, or Vite projects

## Core Guidance

### 1. Installation & Setup

**Initialize in a project**:
```bash
npx shadcn@latest init
```

**Add individual components** (not installed as dependency -- copied into your project):
```bash
npx shadcn@latest add button
npx shadcn@latest add dialog
npx shadcn@latest add form
```

**Key Principle**: shadcn/ui copies component source code into your project. You own the code and can customize freely. This is not a traditional npm package.

**Project Structure**:
```
src/
  components/
    ui/           # shadcn/ui primitives (auto-generated)
      button.tsx
      dialog.tsx
      input.tsx
    custom/       # Your compositions using ui primitives
      user-form.tsx
      data-table.tsx
  lib/
    utils.ts      # cn() utility for class merging
```

### 2. Theming System

**CSS Variables** (defined in `globals.css`):
```css
@layer base {
  :root {
    --background: 0 0% 100%;
    --foreground: 222.2 84% 4.9%;
    --primary: 222.2 47.4% 11.2%;
    --primary-foreground: 210 40% 98%;
    --muted: 210 40% 96.1%;
    --muted-foreground: 215.4 16.3% 46.9%;
    --border: 214.3 31.8% 91.4%;
    --radius: 0.5rem;
  }

  .dark {
    --background: 222.2 84% 4.9%;
    --foreground: 210 40% 98%;
    --primary: 210 40% 98%;
    --primary-foreground: 222.2 47.4% 11.2%;
  }
}
```

**Theme Customization Rules**:
- Modify CSS variables, not component source (when possible)
- Use HSL format without the `hsl()` wrapper for variable values
- All shadcn components reference these variables via Tailwind classes
- Generate custom themes at ui.shadcn.com/themes

### 3. Dark Mode Implementation

**Next.js with next-themes**:
```tsx
// app/layout.tsx
import { ThemeProvider } from 'next-themes'

export default function RootLayout({ children }) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body>
        <ThemeProvider attribute="class" defaultTheme="system" enableSystem>
          {children}
        </ThemeProvider>
      </body>
    </html>
  )
}
```

**Theme Toggle Component**:
```tsx
import { Moon, Sun } from 'lucide-react'
import { useTheme } from 'next-themes'
import { Button } from '@/components/ui/button'

export function ThemeToggle() {
  const { setTheme, theme } = useTheme()
  return (
    <Button
      variant="ghost"
      size="icon"
      onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}
    >
      <Sun className="h-5 w-5 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
      <Moon className="absolute h-5 w-5 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
      <span className="sr-only">Toggle theme</span>
    </Button>
  )
}
```

### 4. Component Composition Patterns

**Form with Validation** (React Hook Form + Zod):
```tsx
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { z } from 'zod'
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form'
import { Input } from '@/components/ui/input'
import { Button } from '@/components/ui/button'

const schema = z.object({
  email: z.string().email(),
  name: z.string().min(2).max(50),
})

export function UserForm() {
  const form = useForm({ resolver: zodResolver(schema) })

  return (
    <Form {...form}>
      <form onSubmit={form.handleSubmit(onSubmit)}>
        <FormField
          control={form.control}
          name="email"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Email</FormLabel>
              <FormControl>
                <Input placeholder="user@example.com" {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        <Button type="submit">Submit</Button>
      </form>
    </Form>
  )
}
```

**Data Table Pattern**:
```tsx
import { DataTable } from '@/components/ui/data-table'
import { columns } from './columns'

// columns.tsx defines column config with @tanstack/react-table
// DataTable wraps Table, TableHeader, TableBody, TableRow, TableCell
```

**Dialog with Form**:
```tsx
<Dialog>
  <DialogTrigger asChild>
    <Button>Open</Button>
  </DialogTrigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>Edit Profile</DialogTitle>
      <DialogDescription>Update your information below.</DialogDescription>
    </DialogHeader>
    <UserForm />
  </DialogContent>
</Dialog>
```

### 5. Component Variants with CVA

**Class Variance Authority** (used internally by shadcn):
```tsx
import { cva, type VariantProps } from 'class-variance-authority'

const badgeVariants = cva(
  'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold',
  {
    variants: {
      variant: {
        default: 'border-transparent bg-primary text-primary-foreground',
        secondary: 'border-transparent bg-secondary text-secondary-foreground',
        destructive: 'border-transparent bg-destructive text-destructive-foreground',
        outline: 'text-foreground',
      },
    },
    defaultVariants: { variant: 'default' },
  }
)
```

**Extending Components**:
```tsx
// Add custom variants by modifying the copied component source
// Or compose with wrapper components for project-specific patterns
```

### 6. Tailwind CSS Integration

**The `cn()` Utility** (essential for class merging):
```tsx
import { clsx, type ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'

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

// Usage: cn('px-4 py-2', isActive && 'bg-primary', className)
```

**Responsive Design**:
```tsx
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
  <Card className="col-span-1 md:col-span-2 lg:col-span-1">
    {/* Content */}
  </Card>
</div>
```

### 7. Accessibility Guidelines

**Built-in Accessibility** (via Radix UI primitives):
- Keyboard navigation (Tab, Enter, Escape, Arrow keys)
- Focus management and focus trapping in modals
- ARIA attributes automatically applied
- Screen reader announcements for dynamic content

**Your Responsibilities**:
- Always provide `DialogTitle` and `DialogDescription` for dialogs
- Use `sr-only` class for icon-only buttons: `<span className="sr-only">Close</span>`
- Set `aria-label` on interactive elements without visible text
- Maintain color contrast ratios (4.5:1 for normal text, 3:1 for large text)
- Test with keyboard navigation (no mouse)
- Verify with screen reader (VoiceOver, NVDA)

**Focus Management**:
```tsx
// Dialog auto-focuses first focusable element
// Sheet auto-manages focus trap
// Popover returns focus to trigger on close
// Use autoFocus={false} to override default focus behavior
```

### 8. Common Component Patterns

| Pattern | Components Used | Use Case |
|---------|----------------|----------|
| CRUD Table | DataTable + Dialog + Form | Admin panels, data management |
| Command Palette | Command + CommandInput + CommandList | Search, navigation |
| Settings Page | Tabs + Form + Switch + Select | User preferences |
| Dashboard | Card + Chart + Table + Badge | Analytics, overview |
| Auth Pages | Card + Form + Input + Button | Login, signup |
| Navigation | NavigationMenu + Sheet (mobile) | Site header, sidebar |

## Anti-Patterns

- Installing shadcn/ui as an npm package (it copies source files, not a dependency)
- Overriding component styles with `!important` instead of modifying source
- Not using the `cn()` utility for conditional classes
- Forgetting `asChild` prop when wrapping triggers with custom elements
- Missing `DialogTitle` causing accessibility warnings
- Hardcoding colors instead of using CSS variable tokens

## Quick Reference

**Add Component**: `npx shadcn@latest add [component-name]`
**Class Merging**: Always use `cn()` for conditional and merged classes
**Theming**: Modify CSS variables in `globals.css`, not component source
**Dark Mode**: `next-themes` + `attribute="class"` + `.dark` CSS scope
**Forms**: React Hook Form + Zod + shadcn Form components
**Accessibility**: Radix handles ARIA; you handle labels, contrast, and keyboard testing

## Rationalizations
> 이 절은 참고 자료다 — 아래 변명·반박은 모델이 작업 중 스스로 지름길을 점검하는 데 쓰고, 사용자에게 묻는 질문 목록이나 별도 게이트로 쓰지 않는다. 반박에 비추어 스스로 바로잡을 수 없으면 이 스킬의 Step·Checkpoint 규칙을 따른다.

The following table captures common excuses agents make to skip the rigor of this skill, paired with factual rebuttals.

| Excuse | Rebuttal |
|--------|----------|
| "I will build my own components" | shadcn gives you accessible Radix primitives — reinventing means reinventing a11y bugs |
| "copy-paste components are a mess" | shadcn is not a dependency — owning the source is the feature, not the bug |
| "CVA variants are overkill" | variants centralize style decisions; without them you get prop-drilling className everywhere |
| "dark mode with Tailwind is enough" | semantic CSS variables beat dark: prefixes at scale — use shadcn tokens |
| "I will skip Radix and use divs" | divs are not accessible by default — Radix gives you keyboard nav and ARIA for free |

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.