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>

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