shadcn-best-practices
shadcn/ui Best Practices
This skill covers best practices for working with shadcn/ui — component imports, className utilities, form building, theming, and data tables.
Use-When
This skill activates when:
- Agent works with shadcn/ui components
- Agent adds or imports shadcn components
- Agent builds forms with validation
- Agent configures theming or dark mode
- Agent creates data tables
Core Rules
- ALWAYS import shadcn components from
@/components/ui/{component-name} - ALWAYS use the
cn()utility for className merging - ALWAYS use Zod + React Hook Form for form validation
- ALWAYS use CSS variables for theming (not hardcoded colors)
- ALWAYS use TanStack Table for data tables
- ALWAYS check components.json to identify the primitive library (Radix vs Base UI)
- ALWAYS use migration commands when upgrading between styles (
migrate radix,migrate rtl)
Common Agent Mistakes
- Using relative paths instead of alias paths
- Forgetting to import
cn()utility - Hardcoding colors instead of using CSS variables
- Building table logic manually instead of using TanStack Table
- Assuming all shadcn projects use Radix UI (Base UI is now available)
- Using Radix-specific imports in Base UI projects (or vice versa)
Examples
✅ Correct
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { cn } from "@/lib/utils"
function MyComponent({ className }) {
return (
<Button className={cn("base-class", className)}>
<Input placeholder="Enter email" />
</Button>
)
}
❌ Wrong
// Using relative paths
import { Button } from "../../components/ui/button"
// Hardcoding colors
<Button className="bg-blue-500 text-white" />
// Building table manually
data.map(item => <tr><td>{item.name}</td></tr>)
// Assuming Radix - wrong for Base UI projects
import * as DialogPrimitive from "@radix-ui/react-dialog"
Identifying Primitive Library
// Check components.json to determine which library the project uses
// Look for "style" field:
// - "base-*" styles use @base-ui/react
// - Other styles use @radix-ui/react-* or radix-ui
// Example: reading the config
// import fs from "fs"
// const config = JSON.parse(fs.readFileSync("components.json", "utf-8"))
// config.style === "base-vega" // true = Base UI, false = Radix
// The API is identical regardless of library
import { Dialog, DialogContent } from "@/components/ui/dialog"
// Works the same for both Radix and Base UI projects
References
More from moderndegree/agent-skills
design-systems
Design tokens, spacing scales, color systems, and typography for building consistent UIs. Use when creating design systems, theming, or establishing UI foundations.
8motion-animation
Motion design principles, when to animate, transitions, and accessibility. Use when adding animations, micro-interactions, or ensuring accessibility for motion.
6dialogs-modals
Modal and dialog patterns, confirmations, destructive actions, and focus management. Use when building modals, dialogs, or confirmation dialogs.
6form-design
Form UX patterns, field types, multi-step wizards, and layout. Use when building forms, registration flows, or any data collection interfaces.
5a11y-best-practices
Comprehensive accessibility patterns for building, testing, and fixing accessible interfaces. Use when building UI components, forms, pages, or auditing code for accessibility issues.
5notifications-feedback
Toast notifications, alerts, feedback messages, and their timing. Use when adding user feedback, success messages, or alerts.
5