> class-variance-authority
Define component variants with CVA. Use when creating variant-based components with Tailwind, building design system tokens, or managing complex conditional class names in React.
curl "https://skillshub.wtf/TerminalSkills/skills/class-variance-authority?format=md"Class Variance Authority (CVA)
Overview
CVA creates type-safe component variants with Tailwind. Define base styles, variants (size, color, state), compound variants, and defaults. Works with any framework. Powers the variant system in shadcn/ui.
Instructions
Step 1: Define Variants
// components/button.tsx — Button with CVA variants
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/utils'
const buttonVariants = cva(
// Base styles — always applied
'inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50',
{
variants: {
variant: {
default: 'bg-blue-600 text-white hover:bg-blue-700',
secondary: 'bg-gray-100 text-gray-900 hover:bg-gray-200',
destructive: 'bg-red-600 text-white hover:bg-red-700',
outline: 'border border-gray-300 bg-transparent hover:bg-gray-50',
ghost: 'hover:bg-gray-100',
link: 'text-blue-600 underline-offset-4 hover:underline',
},
size: {
sm: 'h-8 px-3 text-xs',
md: 'h-10 px-4 text-sm',
lg: 'h-12 px-6 text-base',
icon: 'h-10 w-10',
},
},
compoundVariants: [
// Destructive + outline = red border
{ variant: 'outline', className: 'border-2' },
{ variant: 'destructive', size: 'lg', className: 'text-lg font-bold' },
],
defaultVariants: {
variant: 'default',
size: 'md',
},
}
)
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {}
function Button({ className, variant, size, ...props }: ButtonProps) {
return <button className={cn(buttonVariants({ variant, size }), className)} {...props} />
}
Step 2: Complex Components
const badgeVariants = cva(
'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold',
{
variants: {
status: {
active: 'bg-green-100 text-green-800',
inactive: 'bg-gray-100 text-gray-600',
warning: 'bg-yellow-100 text-yellow-800',
error: 'bg-red-100 text-red-800',
},
size: {
sm: 'text-[10px] px-1.5 py-0',
md: 'text-xs px-2.5 py-0.5',
lg: 'text-sm px-3 py-1',
},
},
defaultVariants: { status: 'active', size: 'md' },
}
)
// Usage
<Badge status="active">Online</Badge>
<Badge status="error" size="sm">Failed</Badge>
Guidelines
- CVA is for defining variants. Use
cn()(clsx + tailwind-merge) for conditional classes. compoundVariantsfor combinations that need special treatment (e.g., destructive + outline).VariantProps<typeof variants>gives you TypeScript types for free.- Keep CVA definitions close to their component — one file per component.
- Works with any CSS framework, but shines with Tailwind's utility classes.
> related_skills --same-repo
> zustand
You are an expert in Zustand, the small, fast, and scalable state management library for React. You help developers manage global state without boilerplate using Zustand's hook-based stores, selectors for performance, middleware (persist, devtools, immer), computed values, and async actions — replacing Redux complexity with a simple, un-opinionated API in under 1KB.
> zod
You are an expert in Zod, the TypeScript-first schema declaration and validation library. You help developers define schemas that validate data at runtime AND infer TypeScript types at compile time — eliminating the need to write types and validators separately. Used for API input validation, form validation, environment variables, config files, and any data boundary.
> xero-accounting
Integrate with the Xero accounting API to sync invoices, expenses, bank transactions, and contacts — and generate financial reports like P&L and balance sheet. Use when: connecting apps to Xero, automating bookkeeping workflows, syncing accounting data, or pulling financial reports programmatically.
> windsurf-rules
Configure Windsurf AI coding assistant with .windsurfrules and workspace rules. Use when: customizing Windsurf for a project, setting AI coding standards, creating team-shared Windsurf configurations, or tuning Cascade AI behavior.