Button
Forms
Core
Versatile button component with multiple variants, sizes, loading states, and icon support. Fully accessible with WCAG 2.2 AA compliance.
Preview
Interactive button examples
Variants
Semantic variants for different actions
Sizes
Standard and icon-only sizes
Standard Sizes
Icon-Only
With Icons
Icons before or after button text
Loading States
Built-in loading spinner with accessible labels
Full Width
Buttons that stretch to fill their container
Disabled State
Consistent disabled styling across variants
Props
Button component API reference
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'primary' | 'secondary' | 'inverse' | 'ghost' | 'destructive' | 'destructive-secondary' | 'link' | 'primary' | Visual style variant |
size | 'sm' | 'md' | 'lg' | 'icon-sm' | 'icon' | 'icon-lg' | 'md' | Size variant |
fullWidth | boolean | false | Fill container width |
asChild | boolean | false | Render as child component (polymorphic) |
loading | boolean | false | Show loading spinner |
loadingText | string | — | Accessible label for loading state |
leftIcon | ReactNode | — | Icon before the label |
rightIcon | ReactNode | — | Icon after the label |
disabled | boolean | false | Disable interaction |
Usage
Import and implementation example
import { Button } from '@/components/ui/button'
import { Download, Trash2 } from 'lucide-react'
import Link from 'next/link'
export default function Example() {
return (
<>
{/* Basic usage */}
<Button>Click me</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="inverse">Inverse</Button>
{/* With icons */}
<Button leftIcon={<Download />}>Download</Button>
<Button variant="destructive" leftIcon={<Trash2 />}>Delete</Button>
{/* Loading state */}
<Button loading loadingText="Saving...">Save</Button>
{/* Icon only */}
<Button size="icon"><Settings /></Button>
{/* As link */}
<Button asChild>
<Link href="/about">About</Link>
</Button>
</>
)
}Features
Built-in functionality
- 7 variants: Primary, secondary, inverse, ghost, destructive, destructive-secondary, link
- 6 sizes: sm, md, lg, icon-sm, icon, icon-lg
- Loading states: Built-in spinner with custom loading text
- Icon support: Left and right icon positioning
- Polymorphic: Use asChild prop with Next.js Link
- Full width: Option to fill container width
- Accessible: WCAG 2.2 AA compliant with proper focus states
- Dark mode: Full dark mode support
Accessibility
Accessibility considerations
ARIA Attributes
aria-disabled when disabled or loadingaria-busy during loading stateIcons have aria-hidden="true"Keyboard Navigation
| Key | Action |
|---|---|
| Tab | Focus the button |
| Enter / Space | Activate the button |
Notes
- Uses native button element for accessibility
- Loading state prevents double-submission
- Focus ring visible on keyboard navigation
- Color contrast meets WCAG AA requirements