Button

A versatile button component with multiple variants, sizes, and states. Supports icons, loading state, and composition via asChild.

Variants

Sizes

States

Patterns

Read the docs

Installation

pnpm
pnpm dlx @hex-core/cli add button

Variants

Different visual styles

tsx
<>
  <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

tsx
<Button loading>Submitting...</Button>

Icon button

Square button with just an icon

tsx
<Button variant="outline" size="icon" aria-label="Settings">
  <SettingsIcon />
</Button>

Variant values

variantVisual style variants
ValueDescription
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
ValueDescription
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

PropTypeDefaultDescription
variant
"default" | "destructive" | "outline" | "secondary" | "ghost" | "link"defaultThe visual style of the button
size
"default" | "sm" | "lg" | "icon"defaultThe size of the button
asChild
booleanfalseRender as a Slot component, merging props with the child element. Use to render as a link or other element.
loading
booleanfalseShow loading spinner and disable interaction
disabled
booleanfalseDisable the button
className
stringAdditional 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.

Token budget: 500