Button
A versatile button component with multiple variants, sizes, and states. Supports icons, loading state, and composition via asChild.
Installation
pnpm dlx @hex-core/cli add buttonVariants
Different visual styles
<>
<Button variant="default">Primary</Button>
<Button variant="outline">Outline</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="destructive">Delete</Button>
<Button variant="link">Link</Button>
</>With loading state
Button showing a spinner while loading
<Button loading>Submitting...</Button>As link
Button rendered as an anchor tag
<Button asChild>
<a href="/login">Login</a>
</Button>Variant values
variantVisual style variants| Value | Description |
|---|---|
defaultdefault | Primary filled button with subtle shadow for main actions |
destructive | Red button with shadow for dangerous/irreversible actions |
outline | Bordered button with hover fill for secondary actions |
secondary | Muted filled button for less prominent actions |
ghost | Transparent button, background appears on hover |
link | Styled as a hyperlink with underline on hover, no padding |
sizeSize variants| Value | Description |
|---|---|
defaultdefault | Standard size (h-10, px-4) |
sm | Compact size (h-9, px-3) |
lg | Large size (h-11, px-8, text-base) |
icon | Square icon-only size (h-10, w-10) |
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | default | The visual style of the button |
size | "default" | "sm" | "lg" | "icon" | default | The size of the button |
asChild | boolean | false | Render as a Slot component, merging props with the child element. Use to render as a link or other element. |
loading | boolean | false | Show loading spinner and disable interaction |
disabled | boolean | false | Disable the button |
className | string | — | Additional CSS classes to merge with the component styles |
AI Guidance
When to use
Use for clickable actions: form submissions, confirmations, triggering operations. Use 'default' variant for primary CTAs, 'outline' or 'secondary' for less important actions, 'ghost' for toolbar-style actions.
When not to use
Don't use for navigation between pages (use Link or anchor with asChild). Don't use 'destructive' for non-dangerous actions. Don't use for toggling state (use Toggle or Switch).
Common mistakes
- Using 'destructive' variant for non-destructive actions
- Nesting interactive elements inside asChild button
- Missing aria-label when using icon-only size='icon' variant
- Using onClick for navigation instead of asChild with a link
Accessibility
Automatically handles focus ring, disabled state, and aria attributes. Icon-only buttons MUST have aria-label. Loading state automatically sets disabled.
Related components
Token budget: 500
Verified against @hex-core/components@1.12.0