Component Variants Guide
Component Variants Guide
This guide demonstrates how to use and extend shadcn/ui components with our theme system.
Base Components
Button Variants
// Default button with semantic tokens
<Button>Default</Button>
// Secondary variant with custom spacing
<Button variant="secondary" className="px-button-md">
Secondary
</Button>
// Ghost variant with icon
<Button variant="ghost" size="icon">
<Icon className="h-4 w-4" />
</Button>
Alert Variants
// Default alert
<Alert>
<AlertTitle>Default Alert</AlertTitle>
<AlertDescription>Description text</AlertDescription>
</Alert>
// Destructive alert with custom opacity
<Alert variant="destructive" className="bg-destructive/alert-light">
<AlertTitle>Error</AlertTitle>
<AlertDescription>Error message</AlertDescription>
</Alert>
Card Variants
// Default card with semantic spacing
<Card className="p-card-md">
<CardHeader className="space-y-card-section">
<CardTitle>Title</CardTitle>
<CardDescription>Description</CardDescription>
</CardHeader>
<CardContent>Content</CardContent>
</Card>
// Interactive card with hover states
<Card className="p-card-md hover:bg-muted/subtle">
<CardHeader>
<CardTitle>Interactive Card</CardTitle>
</CardHeader>
</Card>
Custom Component Patterns
Creating New Variants
// Example: Custom card variant
const cardVariants = cva(
"rounded-lg border bg-card text-card-foreground shadow-sm",
{
variants: {
variant: {
default: "",
interactive: "hover:bg-muted/subtle transition-colors",
featured: "border-primary/20 bg-primary/subtle",
},
size: {
sm: "p-card-sm",
default: "p-card-md",
lg: "p-card-lg",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
);
Extending shadcn/ui Components
// Example: Extended button with new variant
const CustomButton = React.forwardRef<
HTMLButtonElement,
ButtonProps & { isLoading?: boolean }
>(({ isLoading, children, ...props }, ref) => {
return (
<Button
ref={ref}
{...props}
disabled={isLoading || props.disabled}
>
{isLoading ? <Spinner className="mr-2" /> : null}
{children}
</Button>
);
});
Best Practices
-
Consistent Spacing
// ✅ Use semantic tokens for spacing <Card className="p-card-md space-y-card-section"> // ❌ Avoid arbitrary values <Card className="p-4 space-y-6">
-
Theme-Aware Colors
// ✅ Use semantic colors <Alert className="bg-muted/subtle border-border/alert-border"> // ❌ Avoid hard-coded colors <Alert className="bg-gray-100 border-gray-200">
-
Interactive States
// ✅ Use opacity tokens <Button className="hover:bg-primary/hover active:bg-primary/active"> // ❌ Avoid arbitrary opacity <Button className="hover:opacity-90">
Common Patterns
Form Components
// Input with label
<div className="space-y-form-label">
<Label>Email</Label>
<Input type="email" className="h-form-input px-form-padding-x" />
</div>
// Form section
<div className="space-y-form-stack">
<FormField>
<FormLabel>Name</FormLabel>
<FormControl>
<Input />
</FormControl>
<FormMessage />
</FormField>
</div>
Navigation Components
// Navigation menu
<NavigationMenu className="space-x-nav-item">
<NavigationMenuItem>
<NavigationMenuLink>
<span className="space-x-nav-icon">
<Icon />
<span>Link Text</span>
</span>
</NavigationMenuLink>
</NavigationMenuItem>
</NavigationMenu>
Content Components
// Article card
<Card className="p-card-md">
<CardHeader className="space-y-card-section-sm">
<CardTitle className="text-xl">Article Title</CardTitle>
<CardDescription className="text-muted-foreground/form-text">
Description
</CardDescription>
</CardHeader>
<CardContent className="space-y-card-section">
{/* Content */}
</CardContent>
</Card>
Migration Guide
When updating existing components:
- Replace direct spacing values with semantic tokens
- Update color usage to use theme-aware tokens
- Implement proper interactive states
- Add proper aria attributes
- Test in both light and dark themes
Component Checklist
When creating or modifying components:
- Uses semantic tokens for spacing
- Implements proper interactive states
- Works in both light and dark themes
- Follows accessibility guidelines
- Has proper TypeScript types
- Includes usage examples
- Documents variants and props
components
documentation
shadcn-ui