Skills
shadcn-ui
shadcn-ui
npx @loomcraft/cli add skill shadcn-uiFrontmatter
Name
shadcn-ui
Description
ShadCN UI component patterns, forms, data tables, and page layouts. Use when building interfaces with ShadCN components, creating forms with react-hook-form, tables with TanStack Table, or designing page layouts.
Content
# ShadCN UI Patterns
## Critical Rules
- **Always use ShadCN primitives first** — before building custom components.
- **Never rebuild keyboard or focus behavior** — use the component primitives.
- **Never mix primitive systems** — don't combine Radix, Headless UI, React Aria in the same surface.
- **Never use `h-screen`** — use `h-dvh` for correct mobile viewport.
- **Empty states must have one clear next action** — never blank screens.
- **No gradients or glow effects** unless explicitly requested.
## Installation & Setup
- Install components individually with `npx shadcn@latest add <component>` — never install all at once.
- Components are copied to `src/components/ui/` — they are yours to customize.
- Configure `components.json` for path aliases and styling preferences.
- Use `cn()` from `src/lib/utils` for class merging (clsx + tailwind-merge).
## Component Usage
- **Always use ShadCN primitives** before building custom components:
- `Button` for all clickable actions (with appropriate `variant` and `size`)
- `Card` for content containers
- `Dialog` for modal overlays
- `Sheet` for slide-out panels
- `DropdownMenu` for action menus
- `Select` for option picking
- `Table` for data display
- `Form` + `Input` + `Label` for forms
- `Badge` for tags and status indicators
- `Tabs` for content switching
- `Toast` / `Sonner` for notifications
## Forms
- Use `react-hook-form` + `zod` with ShadCN's `Form` component:
```tsx
const form = useForm<z.infer<typeof schema>>({
resolver: zodResolver(schema),
defaultValues: { name: '' },
})
```
- Stack form fields with `space-y-4`.
- Use `grid gap-4 md:grid-cols-2` for side-by-side fields on desktop.
- Show validation errors inline with `FormMessage`.
- Use `FormDescription` for helper text below fields.
## Data Tables
- Use ShadCN `DataTable` pattern with `@tanstack/react-table`:
- Define columns with type-safe `ColumnDef`.
- Support sorting, filtering, and pagination.
- Add row actions via `DropdownMenu`.
- Use `tabular-nums` on numeric columns for alignment.
- Add loading skeletons with ShadCN `Skeleton` for async data.
- **Toolbar pattern**: search input + result counter + limit selector in every table.
- Hide columns progressively by breakpoint: `hidden sm:table-cell`, `hidden md:table-cell`.
## Dialogs & Alerts
- Use `Dialog` for informational or form-based modals.
- Use `AlertDialog` for destructive or irreversible actions — never a plain `Dialog`.
- Keep dialog content focused — one primary action per dialog.
- Always provide a way to dismiss (close button, escape key, outside click).
## Page Layout Pattern
Structure pages with Cards for consistent visual hierarchy:
```tsx
// Header → Cards → Footer pattern
<div className="space-y-6">
<div className="flex items-center justify-between">
<h1 className="text-3xl font-bold tracking-tight">Page Title</h1>
<Button>Primary Action</Button>
</div>
<Card>
<CardHeader><CardTitle>Section</CardTitle></CardHeader>
<CardContent>{/* content */}</CardContent>
</Card>
</div>
```
- Multi-Card forms: split complex forms into logical Card sections.
- Use `CardHeader` + `CardTitle` + `CardDescription` for section context.
## Charts
- Use `ChartContainer` from ShadCN with Recharts for data visualization.
- Wrap charts in a `Card` with descriptive `CardHeader`.
- Always include a `ChartTooltip` for data point details.
## File Upload
- Use a `FileUpload` dropzone component with drag-and-drop support.
- Show preview for images, file name + size for documents.
- Validate file type and size client-side before upload.
## Theming
- Use CSS variables from the ShadCN theme system: `bg-background`, `text-foreground`, `bg-card`, `text-muted-foreground`, `bg-primary`, etc.
- Never hardcode hex colors — always use semantic tokens.
- Support dark mode via the `dark` class on `<html>` — CSS variables handle the switch.
- Limit accent color usage to one per view.
## Accessibility
- All icon-only buttons must have `aria-label`.
- Use `sr-only` class for screen-reader-only text.
- Ensure all interactive elements have visible focus states (ShadCN handles this by default).
- Use `role` and `aria-*` attributes when composing custom components.
- Never block paste in `input` or `textarea` elements.
## Do
- Use ShadCN primitives before building anything custom — check the component library first.
- Use `cn()` from `@/lib/utils` for all conditional class merging.
- Use `AlertDialog` for destructive actions — never a plain `Dialog`.
- Use `FormMessage` for inline validation errors in every form field.
- Use `Skeleton` components for loading states in async data areas.
- Provide `aria-label` on every icon-only `Button`.
- Use `Sheet` for mobile navigation and side panels instead of custom drawers.
- Wrap charts in `Card` with descriptive `CardHeader` for context.
- Install components individually with `npx shadcn@latest add` — only what you need.
## Don't
- Don't rebuild keyboard navigation, focus traps, or dismiss behavior — use the primitives.
- Don't mix Radix, Headless UI, and React Aria in the same surface.
- Don't use `h-screen` — use `h-dvh` for correct mobile viewport height.
- Don't add gradients or glow effects unless explicitly requested.
- Don't leave empty states blank — always provide a message and a clear next action.
- Don't hardcode hex colors — use semantic tokens from the ShadCN theme system.
- Don't use `Dialog` for destructive confirmations — use `AlertDialog`.
- Don't install all ShadCN components at once — install individually as needed.
- Don't block paste on `input` or `textarea` elements.
## Anti-Patterns
| Anti-Pattern | Problem | Fix |
|-------------|---------|-----|
| **Custom modal from scratch** | Missing focus trap, escape handling, scroll lock | Use `Dialog` or `AlertDialog` from ShadCN |
| **Plain `Dialog` for delete** | No forced confirmation, easy accidental deletion | Use `AlertDialog` with explicit confirm/cancel |
| **Mixing component libraries** | Conflicting styles, broken focus management | Stick to ShadCN/Radix for all primitives |
| **`select` HTML element** | Inconsistent styling, no search/filter support | Use ShadCN `Select` or `Combobox` |
| **Manual form validation** | Inconsistent error handling, no schema reuse | Use `react-hook-form` + `zod` + ShadCN `Form` |
| **Blank empty state** | User confusion, no clear path forward | Add message + primary action `Button` |
| **Inline hex colors** | Breaks dark mode, inconsistent theming | Use `bg-background`, `text-foreground`, etc. |
| **`onClick` on `div`** | Not keyboard accessible, no focus state | Use `Button` with appropriate `variant` |
## Animation
- Never add animation unless explicitly requested.
- Use `transition-colors` for hover/focus state changes.
- Keep interaction feedback under 200ms.
- Avoid animating layout properties (`width`, `height`, `margin`, `padding`) — use `transform` and `opacity` only.
- Respect `prefers-reduced-motion` media query.Files
No additional files