Button

Triggers an action or event. Supports 6 variants, 4 sizes, and can render as any HTML element via the asChild prop.

  • 6 variants: default, secondary, outline, ghost, destructive, link
  • 4 sizes: sm, default, lg, icon (square, for icon-only buttons)
  • First-class Lucide React icon support — icons are auto-sized and pointer-events disabled
  • asChild prop renders as any element via Radix Slot (avoids nested button/anchor issues)
  • Full keyboard accessibility — focus ring, disabled state
  • Forwards ref to the underlying element

import { Button }from "@aetherstack/ui"

button.tsx
import { Button } from "@/components/ui/button"

export function ButtonDemo() {
  return (
    <div className="flex flex-wrap gap-3">
      <Button>Default</Button>
      <Button variant="secondary">Secondary</Button>
      <Button variant="outline">Outline</Button>
      <Button variant="ghost">Ghost</Button>
      <Button variant="destructive">Destructive</Button>
    </div>
  )
}

Usage

Variants

Six visual variants covering the full range of action contexts.

Sizes

Four sizes. Use 'icon' for square icon-only buttons — always add aria-label.

Disabled state

Disabled buttons are non-interactive and visually dimmed.

As link (asChild)

Use asChild to render the Button as a different element. This avoids the invalid nested <button><a> pattern and keeps full button styling.

With icon

Place a Lucide icon before or after the label. Icons are auto-sized to 16px — no extra classes needed.

Icon-only buttons

Use size="icon" for square icon buttons. Always provide aria-label for screen readers.

Loading state

Combine disabled with an animated Loader2 spinner for async actions.

Props

PropTypeDefaultDescription
variant"default" | "destructive" | "outline" | "secondary" | "ghost" | "link""default"Controls the visual style of the button.
size"default" | "sm" | "lg" | "icon""default"Controls the padding and height. Use 'icon' for square icon-only buttons.
asChildbooleanfalseWhen true, renders the button's children as the root element using Radix Slot. Useful for rendering as <a>, <Link>, or other elements.
disabledbooleanfalseDisables the button — prevents pointer events and applies reduced opacity.
classNamestringAdditional class names merged onto the button element.
...propsReact.ButtonHTMLAttributes<HTMLButtonElement>All standard HTML button attributes (onClick, type, aria-*, data-*, etc.) are forwarded to the element.

* Required props

Accessibility

  • Always provide a descriptive label for icon-only buttons via aria-label.
  • Keyboard accessible — activates with Enter and Space keys.
  • Focus ring uses the --ring token and is always visible on keyboard navigation (focus-visible).
  • Disabled state removes pointer events entirely — does not trap focus.
  • When using asChild with <a>, the element becomes a link — screen readers announce it as a link, not a button. This is correct semantic behavior.