shadcn/ui component patterns including CVA variants, OKLCH theming, cn() utility, and composition. Use when adding shadcn components, building variant systems, or customizing themes.
View on GitHubyonatangross/skillforge-claude-plugin
orchestkit-complete
January 23, 2026
Select agents to install to:
npx add-skill https://github.com/yonatangross/skillforge-claude-plugin/blob/main/./skills/shadcn-patterns/SKILL.md -a claude-code --skill shadcn-patternsInstallation paths:
.claude/skills/shadcn-patterns/# shadcn/ui Patterns
Beautifully designed, accessible components you own and customize.
## Core Pattern: CVA (Class Variance Authority)
Declarative, type-safe variant definitions:
```tsx
import { cva, type VariantProps } from 'class-variance-authority'
const buttonVariants = cva(
// Base classes (always applied)
'inline-flex items-center justify-center rounded-md font-medium transition-colors',
{
variants: {
variant: {
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
destructive: 'bg-destructive text-destructive-foreground',
outline: 'border border-input bg-background hover:bg-accent',
ghost: 'hover:bg-accent hover:text-accent-foreground',
},
size: {
default: 'h-10 px-4 py-2',
sm: 'h-9 px-3',
lg: 'h-11 px-8',
icon: 'h-10 w-10',
},
},
compoundVariants: [
{ variant: 'outline', size: 'lg', className: 'border-2' },
],
defaultVariants: {
variant: 'default',
size: 'default',
},
}
)
// Type-safe props
interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {}
```
## Core Pattern: cn() Utility
Combines `clsx` + `tailwind-merge` for conflict resolution:
```tsx
import { clsx, type ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
// Usage - later classes win
cn('px-4 py-2', 'px-6') // => 'py-2 px-6'
cn('text-red-500', condition && 'text-blue-500')
```
## OKLCH Theming (2026 Standard)
Modern perceptually uniform color space:
```css
:root {
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.922 0 0);
--ring: oklch(0.708 0 0);
--radius: 0.625rem;
}
.dark {
--background: oklch(0.145 0 0);
--foreground: