A reusable button system with variants, sizes, keyboard navigation, and full dark mode support.
Both components are exported from @/components:
import {Button, ButtonGroup} from '@/components';
import type { ButtonProps } from '@/components';##Overview
This project uses URL-based API versioning to protect clients from breaking changes.
- Stable API paths continue to be served at
/api/v1/* - Legacy paths under
/api/*remain supported through a compatibility layer - Older
/api/*requests are rewritten to/api/v1/*and receive deprecation headers
| Variant | Usage |
|---|---|
primary |
Main call to action (default) |
secondary |
Alternative action |
outline |
Bordered, low emphasis |
ghost |
Minimal, no border |
danger |
Destructive action |
<Button variant="primary">Enroll Now</Button>
<Button variant="secondary">Save Draft</Button>
<Button variant="outline">Preview</Button>
<Button variant="ghost">Cancel</Button>
<Button variant="danger">Delete Course</Button>| Size | Height |
|---|---|
sm |
32px |
md |
40px (default) |
lg |
48px |
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>// Disabled
<Button disabled>Not Available</Button>
// Custom className
<Button className="ml-auto">Right-aligned</Button>
// With icon
<Button>
<svg className="w-4 h-4" ... />
Download
</Button>| Key | Action |
|---|---|
Tab |
Focus next button |
Enter / Space |
Click the focused button |
focus-visible |
Blue outline ring on keyboard focus only |
Groups buttons with arrow-key navigation (roving tabindex).
<ButtonGroup aria-label="View options">
<Button variant="ghost">Week</Button>
<Button variant="ghost">Month</Button>
<Button variant="ghost">Year</Button>
</ButtonGroup>// Horizontal (default)
<ButtonGroup orientation="horizontal" aria-label="Toolbar">
<Button variant="outline">Bold</Button>
<Button variant="outline">Italic</Button>
<Button variant="outline">Underline</Button>
</ButtonGroup>
// Vertical
<ButtonGroup orientation="vertical" aria-label="Navigation">
<Button variant="ghost">Dashboard</Button>
<Button variant="ghost">Courses</Button>
<Button variant="ghost">Settings</Button>
</ButtonGroup>| Key (Horizontal) | Key (Vertical) | Action |
|---|---|---|
ArrowRight |
ArrowDown |
Focus next button (wraps) |
ArrowLeft |
ArrowUp |
Focus previous button (wraps) |
Home |
Home |
Focus first button |
End |
End |
Focus last button |
All variants automatically adapt to dark mode using Tailwind dark: variants. No extra work needed.
<Button variant="primary">Always visible</Button>
<Button variant="ghost">Adapts to theme</Button>- Native
<button>element — works with screen readers by default role="toolbar"+aria-orientationon ButtonGrouparia-labelrequired on ButtonGroupdisabledprop prevents interaction and reduces opacityfocus-visibleoutlines only show during keyboard navigation (not mouse clicks)