Button
Buttons are the most fundamental interactive elements for users to perform actions. Trigger operations with clicks or taps — used for form submission, navigation, and more.
Playground
<Button>Button</Button>Variants
Style
Solid Colors
Sizes
xssmmddefaultlg| Size | Height | H-Padding | Gap | Icon | Font | Preview |
|---|---|---|---|---|---|---|
xs | 28px | 10px | 4px | 14px | 12px | |
sm | 32px | 12px | 8px | 14px | 13px | |
md | 36px | 14px | 8px | 16px | 14px | |
default | 40px | 16px | 8px | 16px | 14px | |
lg | 48px | 24px | 8px | 16px | 16px |
Touch target: WCAG 2.5.8 requires a minimum 24px touch area. Even the smallest xs (28px) meets the WCAG standard.
Features
With Icons
<Button variant="outline" leftIcon={<Search />}>Search</Button>
<Button variant="outline" rightIcon={<ChevronRight />}>Continue</Button>
<Button variant="outline" leftIcon={<Search />} rightIcon={<ChevronRight />}>
Search
</Button>States
// Solid Primary States
<Button color="primary">Default</Button>
<Button color="primary" loading>Loading</Button>
<Button color="primary" disabled>Disabled</Button>
// Outline States
<Button variant="outline">Default</Button>
<Button variant="outline" loading>Loading</Button>
<Button variant="outline" disabled>Disabled</Button>API
Props
variant"solid""solid" | "outline" | "ghost" | "link"Button style. Font weight: solid=600, outline/ghost/link=400
color"default""default" | "primary" | "secondary" | "destructive"Color for solid variant (default=dark, primary=brand, secondary=secondary, destructive=error). Ignored for non-solid
size"default""xs" | "sm" | "md" | "default" | "lg" | "icon"Button height and padding
radius"default""none" | "sm" | "base" | "default" | "lg" | "xl" | "2xl" | "3xl" | "full"Border radius size (6px)
fullWidthfalsebooleanDisplay at 100% width
loadingfalsebooleanLoading state
disabledfalsebooleanDisabled state
leftIconundefinedReactNodeLeft icon
rightIconundefinedReactNodeRight icon
fontWeightundefined"normal" | "semibold"Override font weight. Defaults to variant default (solid=600, outline/ghost/link=400). Priority: direct prop > ButtonGroup context > variant default
selectedfalsebooleanSelected state (outline/ghost only). outline=bg-background-muted, ghost=font-semibold. No effect on other variants
pressEffectundefinedbooleanPress effect (active:scale-pressed). Defaults to true. Set false to disable
asChildfalsebooleanRender as Slot
| Name | Type | Default | Description |
|---|---|---|---|
variant | "solid" | "outline" | "ghost" | "link" | "solid" | Button style. Font weight: solid=600, outline/ghost/link=400 |
color | "default" | "primary" | "secondary" | "destructive" | "default" | Color for solid variant (default=dark, primary=brand, secondary=secondary, destructive=error). Ignored for non-solid |
size | "xs" | "sm" | "md" | "default" | "lg" | "icon" | "default" | Button height and padding |
radius | "none" | "sm" | "base" | "default" | "lg" | "xl" | "2xl" | "3xl" | "full" | "default" | Border radius size (6px) |
fullWidth | boolean | false | Display at 100% width |
loading | boolean | false | Loading state |
disabled | boolean | false | Disabled state |
leftIcon | ReactNode | undefined | Left icon |
rightIcon | ReactNode | undefined | Right icon |
fontWeight | "normal" | "semibold" | undefined | Override font weight. Defaults to variant default (solid=600, outline/ghost/link=400). Priority: direct prop > ButtonGroup context > variant default |
selected | boolean | false | Selected state (outline/ghost only). outline=bg-background-muted, ghost=font-semibold. No effect on other variants |
pressEffect | boolean | undefined | Press effect (active:scale-pressed). Defaults to true. Set false to disable |
asChild | boolean | false | Render as Slot |
Anatomy
Best Practices
Recommended
- ✓One primary button per page
- ✓Action-oriented labels ("Submit", "Save")
- ✓Show loading state for async operations
- ✓Ensure sufficient touch area (WCAG 2.5.8: 24px+)
Avoid
- ✗Don't place multiple primary buttons side by side
- ✗Avoid vague labels like "Click here"
- ✗Don't disable buttons without reason
- ✗Don't use destructive for safe operations
Accessibility
Keyboard
WCAG 2.2 Compliance
- Contrast ratio 4.5:1 or higher
- Focus indicator
- Native disabled attribute
- aria-busy (auto-applied during loading)
- aria-hidden (auto-applied to icons)
- aria-pressed (auto-applied when selected)