02 — COMPONENTS
Button
Trigger actions or navigate. Built on @base-ui/react/button with class-variance-authority variants.
Variants
Six semantic variants — choose based on action hierarchy
<Button>Default</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="destructive">Destructive</Button>
<Button variant="link">Link</Button>
Sizes
Eight size tokens — from xs icon buttons to large CTAs
<Button size="xs">Extra Small</Button>
<Button size="sm">Small</Button>
<Button>Default</Button>
<Button size="lg">Large</Button>
Icon Buttons
Square icon-only buttons — use aria-label for accessibility
<Button size="icon-xs" variant="outline" aria-label="Add"> <Plus /> </Button>
<Button size="icon-sm" variant="outline" aria-label="Add"> <Plus /> </Button>
<Button size="icon" aria-label="Add"> <Plus /> </Button>
<Button size="icon-lg" aria-label="Add"> <Plus /> </Button>
With Icons
Combine text with leading or trailing icons
<Button> <Mail /> Send Email </Button>
<Button> Continue <ArrowRight /> </Button>
<Button variant="outline"> <Download /> Download </Button>
<Button variant="destructive"> <Trash2 /> Delete </Button>
States
Disabled and loading states for interactive feedback
<Button disabled>Disabled</Button>
<Button variant="outline" disabled>Disabled</Button>
<Button disabled> <Loader2 className="animate-spin" /> Loading… </Button>
<Button variant="outline" disabled> <Loader2 className="animate-spin" /> Loading… </Button>
All Variants — Side by Side
Visual comparison across all variants and the default size
Usage
Import and use in any component
Import
import { Button } from "@/components/ui/button"Props
variant
"default" | "secondary" | "outline" | "ghost" | "destructive" | "link"
Default: "default"
size
"xs" | "sm" | "default" | "lg" | "icon-xs" | "icon-sm" | "icon" | "icon-lg"
Default: "default"
disabled
boolean
Default: false
asChild
boolean
Default: false — render as a different element
Accessibility
- Icon-only buttons must have an
aria-label - Use
disabledprop — never CSS-only opacity - Keyboard: Space / Enter to activate
Chuv Studio Design System · Component: button.tsx · @base-ui/react/button + CVA