A versatile button component with multiple variants, sizes, and states. Supports icons, loading states, and full accessibility features.
npm install @uicomponents/button@radix-ui/react-slot^1.0.2class-variance-authority^0.7.0clsx^2.0.0tailwind-merge^2.0.0The simplest button with default styling.
<Button>Click me</Button>Button supports six different visual variants for different contexts.
<div className=class="text-green-600 dark:text-green-400">"flex gap-2">
<Button variant=class="text-green-600 dark:text-green-400">"default">Default</Button>
<Button variant=class="text-green-600 dark:text-green-400">"secondary">Secondary</Button>
<Button variant=class="text-green-600 dark:text-green-400">"destructive">Destructive</Button>
<Button variant=class="text-green-600 dark:text-green-400">"outline">Outline</Button>
<Button variant=class="text-green-600 dark:text-green-400">"ghost">Ghost</Button>
<Button variant=class="text-green-600 dark:text-green-400">"link">Link</Button>
</div>Choose from four sizes: small, default, large, and icon.
<div className=class="text-green-600 dark:text-green-400">"flex items-center gap-2">
<Button size=class="text-green-600 dark:text-green-400">"sm">Small</Button>
<Button size=class="text-green-600 dark:text-green-400">"default">Default</Button>
<Button size=class="text-green-600 dark:text-green-400">"lg">Large</Button>
<Button size=class="text-green-600 dark:text-green-400">"icon">
<Plus className=class="text-green-600 dark:text-green-400">"h-4 w-4" />
</Button>
</div>Combine with a loading spinner for async actions.
<Button disabled>
<Loader2 className=class="text-green-600 dark:text-green-400">"mr-2 h-4 w-4 animate-spin" />
Please wait
</Button>Add icons before or after the button text.
<Button>
<Mail className=class="text-green-600 dark:text-green-400">"mr-2 h-4 w-4" />
Email
</Button>
<Button>
Next
<ArrowRight className=class="text-green-600 dark:text-green-400">"ml-2 h-4 w-4" />
</Button>Use the button styling with a different element, like a link.
<Button asChild>
<Link href=class="text-green-600 dark:text-green-400">"/login">Login</Link>
</Button>| Prop | Type | Default | Description |
|---|---|---|---|
variant | "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | "default" | The visual style variant of the button. |
size | "default" | "sm" | "lg" | "icon" | "default" | The size of the button. |
asChild | boolean | false | Change the default rendered element for the one passed as a child, merging their props and behavior. |
disabled | boolean | false | When true, prevents the user from interacting with the button. |
onClick | (event: React.MouseEvent<HTMLButtonElement>) => void | — | Event handler called when the button is clicked. |
type | "button" | "submit" | "reset" | "button" | The type of button. Use 'submit' for form submission. |
WCAG Level
AA
Keyboard Support
Yes
Screen Reader
Yes
Buttons are announced as 'button' with their accessible name. Disabled buttons are announced as 'dimmed'.
Buttons have visible focus indicators with a 2px ring offset. Focus is automatically managed when buttons are dynamically added or removed.
| Attribute | Description |
|---|---|
aria-disabled | Set to 'true' when the button is disabled |
aria-busy | Set to 'true' when the button is in a loading state |
aria-pressed | Set to 'true' when the button is in a pressed/toggle state |
| Variable | Default | Description |
|---|---|---|
--primary | hsl(222 47% 11%) | Primary button background color |
--primary-foreground | hsl(210 40% 98%) | Primary button text color |
--secondary | hsl(210 40% 96%) | Secondary button background |
--destructive | hsl(0 84% 60%) | Destructive button background |
Copy the code above or explore more components in our library.