Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Add, manage, and compose shadcn/ui components with correct patterns, styling, and CLI workflows.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
SKILL.md
1---2name: shadcn3description: Manages shadcn components and projects — adding, searching, fixing, debugging, styling, and composing UI. Provides project context, component docs, and usage examples. Applies when working with shadcn/ui, component registries, presets, --preset codes, or any project with a components.json file. Also triggers for "shadcn init", "create an app with --preset", or "switch to --preset".4user-invocable: false5allowed-tools: Bash(npx shadcn@latest *), Bash(pnpm dlx shadcn@latest *), Bash(bunx --bun shadcn@latest *)6---78# shadcn/ui910A framework for building ui, components and design systems. Components are added as source code to the user's project via the CLI.1112> **IMPORTANT:** Run all CLI commands using the project's package runner: `npx shadcn@latest`, `pnpm dlx shadcn@latest`, or `bunx --bun shadcn@latest` — based on the project's `packageManager`. Examples below use `npx shadcn@latest` but substitute the correct runner for the project.1314## Current Project Context1516```json17!`npx shadcn@latest info --json`18```1920The JSON above contains the project config and installed components. Use `npx shadcn@latest docs <component>` to get documentation and example URLs for any component.2122## Principles23241. **Use existing components first.** Use `npx shadcn@latest search` to check registries before writing custom UI. Check community registries too.252. **Compose, don't reinvent.** Settings page = Tabs + Card + form controls. Dashboard = Sidebar + Card + Chart + Table.263. **Use built-in variants before custom styles.** `variant="outline"`, `size="sm"`, etc.274. **Use semantic colors.** `bg-primary`, `text-muted-foreground` — never raw values like `bg-blue-500`.2829## Critical Rules3031These rules are **always enforced**. Each links to a file with Incorrect/Correct code pairs.3233### Styling & Tailwind → [styling.md](./rules/styling.md)3435- **`className` for layout, not styling.** Never override component colors or typography.36- **No `space-x-*` or `space-y-*`.** Use `flex` with `gap-*`. For vertical stacks, `flex flex-col gap-*`.37- **Use `size-*` when width and height are equal.** `size-10` not `w-10 h-10`.38- **Use `truncate` shorthand.** Not `overflow-hidden text-ellipsis whitespace-nowrap`.39- **No manual `dark:` color overrides.** Use semantic tokens (`bg-background`, `text-muted-foreground`).40- **Use `cn()` for conditional classes.** Don't write manual template literal ternaries.41- **No manual `z-index` on overlay components.** Dialog, Sheet, Popover, etc. handle their own stacking.4243### Forms & Inputs → [forms.md](./rules/forms.md)4445- **Forms use `FieldGroup` + `Field`.** Never use raw `div` with `space-y-*` or `grid gap-*` for form layout.46- **`InputGroup` uses `InputGroupInput`/`InputGroupTextarea`.** Never raw `Input`/`Textarea` inside `InputGroup`.47- **Buttons inside inputs use `InputGroup` + `InputGroupAddon`.**48- **Option sets (2–7 choices) use `ToggleGroup`.** Don't loop `Button` with manual active state.49- **`FieldSet` + `FieldLegend` for grouping related checkboxes/radios.** Don't use a `div` with a heading.50- **Field validation uses `data-invalid` + `aria-invalid`.** `data-invalid` on `Field`, `aria-invalid` on the control. For disabled: `data-disabled` on `Field`, `disabled` on the control.5152### Component Structure → [composition.md](./rules/composition.md)5354- **Items always inside their Group.** `SelectItem` → `SelectGroup`. `DropdownMenuItem` → `DropdownMenuGroup`. `CommandItem` → `CommandGroup`.55- **Use `asChild` (radix) or `render` (base) for custom triggers.** Check `base` field from `npx shadcn@latest info`. → [base-vs-radix.md](./rules/base-vs-radix.md)56- **Dialog, Sheet, and Drawer always need a Title.** `DialogTitle`, `SheetTitle`, `DrawerTitle` required for accessibility. Use `className="sr-only"` if visually hidden.57- **Use full Card composition.** `CardHeader`/`CardTitle`/`CardDescription`/`CardContent`/`CardFooter`. Don't dump everything in `CardContent`.58- **Button has no `isPending`/`isLoading`.** Compose with `Spinner` + `data-icon` + `disabled`.59- **`TabsTrigger` must be inside `TabsList`.** Never render triggers directly in `Tabs`.60- **`Avatar` always needs `AvatarFallback`.** For when the image fails to load.6162### Use Components, Not Custom Markup → [composition.md](./rules/composition.md)6364- **Use existing components before custom markup.** Check if a component exists before writing a styled `div`.65- **Callouts use `Alert`.** Don't build custom styled divs.66- **Empty states use `Empty`.** Don't build custom empty state markup.67- **Toast via `sonner`.** Use `toast()` from `sonner`.68- **Use `Separator`** instead of `<hr>` or `<div className="border-t">`.69- **Use `Skeleton`** for loading placeholders. No custom `animate-pulse` divs.70- **Use `Badge`** instead of custom styled spans.7172### Icons → [icons.md](./rules/icons.md)7374- **Icons in `Button` use `data-icon`.** `data-icon="inline-start"` or `data-icon="inline-end"` on the icon.75- **No sizing classes on icons inside components.** Components handle icon sizing via CSS. No `size-4` or `w-4 h-4`.76- **Pass icons as objects, not string keys.** `icon={CheckIcon}`, not a string lookup.7778### CLI7980- **Never decode preset codes or build preset URLs manually.** Use `npx shadcn@latest preset decode <code>`, `preset url <code>`, or `preset open <code>`. For project-aware preset detection, use `npx shadcn@latest preset resolve`.81- **Apply preset codes directly with the CLI.** Use `npx shadcn@latest apply <code>` for existing projects, or `npx shadcn@latest init --preset <code>` when initializing.8283## Key Patterns8485These are the most common patterns that differentiate correct shadcn/ui code. For edge cases, see the linked rule files above.8687```tsx88// Form layout: FieldGroup + Field, not div + Label.89<FieldGroup>90<Field>91<FieldLabel htmlFor="email">Email</FieldLabel>92<Input id="email" />93</Field>94</FieldGroup>9596// Validation: data-invalid on Field, aria-invalid on the control.97<Field data-invalid>98<FieldLabel>Email</FieldLabel>99<Input aria-invalid />100<FieldDescription>Invalid email.</FieldDescription>101</Field>102103// Icons in buttons: data-icon, no sizing classes.104<Button>105<SearchIcon data-icon="inline-start" />106Search107</Button>108109// Spacing: gap-*, not space-y-*.110<div className="flex flex-col gap-4"> // correct111<div className="space-y-4"> // wrong112113// Equal dimensions: size-*, not w-* h-*.114<Avatar className="size-10"> // correct115<Avatar className="w-10 h-10"> // wrong116117// Status colors: Badge variants or semantic tokens, not raw colors.118<Badge variant="secondary">+20.1%</Badge> // correct119<span className="text-emerald-600">+20.1%</span> // wrong120```121122## Component Selection123124| Need | Use |125| -------------------------- | --------------------------------------------------------------------------------------------------- |126| Button/action | `Button` with appropriate variant |127| Form inputs | `Input`, `Select`, `Combobox`, `Switch`, `Checkbox`, `RadioGroup`, `Textarea`, `InputOTP`, `Slider` |128| Toggle between 2–5 options | `ToggleGroup` + `ToggleGroupItem` |129| Data display | `Table`, `Card`, `Badge`, `Avatar` |130| Navigation | `Sidebar`, `NavigationMenu`, `Breadcrumb`, `Tabs`, `Pagination` |131| Overlays | `Dialog` (modal), `Sheet` (side panel), `Drawer` (bottom sheet), `AlertDialog` (confirmation) |132| Feedback | `sonner` (toast), `Alert`, `Progress`, `Skeleton`, `Spinner` |133| Command palette | `Command` inside `Dialog` |134| Charts | `Chart` (wraps Recharts) |135| Layout | `Card`, `Separator`, `Resizable`, `ScrollArea`, `Accordion`, `Collapsible` |136| Empty states | `Empty` |137| Menus | `DropdownMenu`, `ContextMenu`, `Menubar` |138| Tooltips/info | `Tooltip`, `HoverCard`, `Popover` |139140## Key Fields141142The injected project context contains these key fields:143144- **`aliases`** → use the actual alias prefix for imports (e.g. `@/`, `~/`), never hardcode.145- **`isRSC`** → when `true`, components using `useState`, `useEffect`, event handlers, or browser APIs need `"use client"` at the top of the file. Always reference this field when advising on the directive.146- **`tailwindVersion`** → `"v4"` uses `@theme inline` blocks; `"v3"` uses `tailwind.config.js`.147- **`tailwindCssFile`** → the global CSS file where custom CSS variables are defined. Always edit this file, never create a new one.148- **`style`** → component visual treatment (e.g. `nova`, `vega`).149- **`base`** → primitive library (`radix` or `base`). Affects component APIs and available props.150- **`iconLibrary`** → determines icon imports. Use `lucide-react` for `lucide`, `@tabler/icons-react` for `tabler`, etc. Never assume `lucide-react`.151- **`resolvedPaths`** → exact file-system destinations for components, utils, hooks, etc.152- **`framework`** → routing and file conventions (e.g. Next.js App Router vs Vite SPA).153- **`packageManager`** → use this for any non-shadcn dependency installs (e.g. `pnpm add date-fns` vs `npm install date-fns`).154- **`preset`** → resolved preset code and values for the current project. Use `npx shadcn@latest preset resolve --json` when you only need preset information.155156See [cli.md — `info` command](./cli.md) for the full field reference.157158## Component Docs, Examples, and Usage159160Run `npx shadcn@latest docs <component>` to get the URLs for a component's documentation, examples, and API reference. Fetch these URLs to get the actual content.161162```bash163npx shadcn@latest docs button dialog select164```165166**When creating, fixing, debugging, or using a component, always run `npx shadcn@latest docs` and fetch the URLs first.** This ensures you're working with the correct API and usage patterns rather than guessing.167168## Workflow1691701. **Get project context** — already injected above. Run `npx shadcn@latest info` again if you need to refresh.1712. **Check installed components first** — before running `add`, always check the `components` list from project context or list the `resolvedPaths.ui` directory. Don't import components that haven't been added, and don't re-add ones already installed.1723. **Find components** — `npx shadcn@latest search`.1734. **Get docs and examples** — run `npx shadcn@latest docs <component>` to get URLs, then fetch them. Use `npx shadcn@latest view` to browse registry items you haven't installed. To preview changes to installed components, use `npx shadcn@latest add --diff`.1745. **Install or update** — `npx shadcn@latest add`. When updating existing components, use `--dry-run` and `--diff` to preview changes first (see [Updating Components](#updating-components) below).1756. **Fix imports in third-party components** — After adding components from community registries (e.g. `@bundui`, `@magicui`), check the added non-UI files for hardcoded import paths like `@/components/ui/...`. These won't match the project's actual aliases. Use `npx shadcn@latest info` to get the correct `ui` alias (e.g. `@workspace/ui/components`) and rewrite the imports accordingly. The CLI rewrites imports for its own UI files, but third-party registry components may use default paths that don't match the project.1767. **Review added components** — After adding a component or block from any registry, **always read the added files and verify they are correct**. Check for missing sub-components (e.g. `SelectItem` without `SelectGroup`), missing imports, incorrect composition, or violations of the [Critical Rules](#critical-rules). Also replace any icon imports with the project's `iconLibrary` from the project context (e.g. if the registry item uses `lucide-react` but the project uses `hugeicons`, swap the imports and icon names accordingly). Fix all issues before moving on.1778. **Registry must be explicit** — When the user asks to add a block or component, **do not guess the registry**. If no registry is specified (e.g. user says "add a login block" without specifying `@shadcn`, `@tailark`, etc.), ask which registry to use. Never default to a registry on behalf of the user.1789. **Switching presets** — Ask the user first: **overwrite**, **partial**, **merge**, or **skip**?179- **Inspect current preset**: `npx shadcn@latest preset resolve`. Use `--json` when you need structured values.180- **Inspect incoming preset**: `npx shadcn@latest preset decode <code>`. Use `preset url <code>` or `preset open <code>` to share or open the preset builder.181- **Overwrite**: `npx shadcn@latest apply <code>`. Overwrites detected components, fonts, and CSS variables.182- **Partial**: `npx shadcn@latest apply <code> --only theme,font`. Updates only the selected preset parts without reinstalling UI components. Supported values are `theme` and `font`; comma-separated combinations are allowed. `icon` is intentionally not supported, because icon changes may require full component reinstall and transforms.183- **Merge**: `npx shadcn@latest init --preset <code> --force --no-reinstall`, then run `npx shadcn@latest info` to list installed components, then for each installed component use `--dry-run` and `--diff` to [smart merge](#updating-components) it individually.184- **Skip**: `npx shadcn@latest init --preset <code> --force --no-reinstall`. Only updates config and CSS, leaves components as-is.185- **Important**: Always run preset commands inside the user's project directory. `apply` only works in an existing project with a `components.json` file. The CLI automatically preserves the current base (`base` vs `radix`) from `components.json`. If you must use a scratch/temp directory (e.g. for `--dry-run` comparisons), pass `--base <current-base>` explicitly — preset codes do not encode the base.186187## Updating Components188189When the user asks to update a component from upstream while keeping their local changes, use `--dry-run` and `--diff` to intelligently merge. **NEVER fetch raw files from GitHub manually — always use the CLI.**1901911. Run `npx shadcn@latest add <component> --dry-run` to see all files that would be affected.1922. For each file, run `npx shadcn@latest add <component> --diff <file>` to see what changed upstream vs local.1933. Decide per file based on the diff:194- No local changes → safe to overwrite.195- Has local changes → read the local file, analyze the diff, and apply upstream updates while preserving local modifications.196- User says "just update everything" → use `--overwrite`, but confirm first.1974. **Never use `--overwrite` without the user's explicit approval.**198199## Quick Reference200201```bash202# Create a new project.203npx shadcn@latest init --name my-app --preset base-nova204npx shadcn@latest init --name my-app --preset a2r6bw --template vite205206# Create a monorepo project.207npx shadcn@latest init --name my-app --preset base-nova --monorepo208npx shadcn@latest init --name my-app --preset base-nova --template next --monorepo209210# Initialize existing project.211npx shadcn@latest init --preset base-nova212npx shadcn@latest init --defaults # shortcut: --template=next --preset=nova (base style implied)213214# Apply a preset to an existing project.215npx shadcn@latest apply a2r6bw216npx shadcn@latest apply a2r6bw --only theme217npx shadcn@latest apply a2r6bw --only font218npx shadcn@latest apply a2r6bw --only theme,font219220# Inspect preset codes and project preset state.221npx shadcn@latest preset decode a2r6bw222npx shadcn@latest preset url a2r6bw223npx shadcn@latest preset open a2r6bw224npx shadcn@latest preset resolve225npx shadcn@latest preset resolve --json226227# Add components.228npx shadcn@latest add button card dialog229npx shadcn@latest add @magicui/shimmer-button230npx shadcn@latest add --all231232# Preview changes before adding/updating.233npx shadcn@latest add button --dry-run234npx shadcn@latest add button --diff button.tsx235npx shadcn@latest add @acme/form --view button.tsx236237# Search registries.238npx shadcn@latest search @shadcn -q "sidebar"239npx shadcn@latest search @tailark -q "stats"240241# Get component docs and example URLs.242npx shadcn@latest docs button dialog select243244# View registry item details (for items not yet installed).245npx shadcn@latest view @shadcn/button246```247248**Named presets:** `nova`, `vega`, `maia`, `lyra`, `mira`, `luma`249**Templates:** `next`, `vite`, `start`, `react-router`, `astro` (all support `--monorepo`) and `laravel` (not supported for monorepo)250**Preset codes:** Version-prefixed base62 strings (e.g. `a2r6bw` or `b0`), from [ui.shadcn.com](https://ui.shadcn.com).251252## Detailed References253254- [rules/forms.md](./rules/forms.md) — FieldGroup, Field, InputGroup, ToggleGroup, FieldSet, validation states255- [rules/composition.md](./rules/composition.md) — Groups, overlays, Card, Tabs, Avatar, Alert, Empty, Toast, Separator, Skeleton, Badge, Button loading256- [rules/icons.md](./rules/icons.md) — data-icon, icon sizing, passing icons as objects257- [rules/styling.md](./rules/styling.md) — Semantic colors, variants, className, spacing, size, truncate, dark mode, cn(), z-index258- [rules/base-vs-radix.md](./rules/base-vs-radix.md) — asChild vs render, Select, ToggleGroup, Slider, Accordion259- [cli.md](./cli.md) — Commands, flags, presets, templates260- [customization.md](./customization.md) — Theming, CSS variables, extending components261