Components

Icon button

View in Figma

Square, icon-only button that reuses the button variants and requires an accessible label.

Install

npx shadcn@latest add @alix/iconButton

Preview

Usage

<IconButton aria-label="Add">
  <Plus />
</IconButton>
<IconButton variant="outline" aria-label="Next">
  <ArrowRight />
</IconButton>
<IconButton size="iconSm" aria-label="Search">
  <Search />
</IconButton>
<IconButton loading aria-label="Saving">
  <Plus />
</IconButton>

Examples

01

Compact toolbar sizes

Use the smaller square sizes when a dense toolbar needs several familiar actions in one row.

<IconButton size="iconXs" variant="ghost" aria-label="Search insights"><Search /></IconButton>
<IconButton size="iconSm" variant="outline" aria-label="Download report"><Download /></IconButton>
<IconButton aria-label="Add workstream"><Plus /></IconButton>
<IconButton size="iconLg" variant="secondary" aria-label="Next service"><ArrowRight /></IconButton>
02

Destructive and busy states

Destructive, disabled, and loading states keep icon-only actions honest when the label is hidden.

<IconButton variant="destructive" aria-label="Remove person"><Trash2 /></IconButton>
<IconButton variant="outline" disabled aria-label="Download locked report"><Download /></IconButton>
<IconButton loading aria-label="Saving action"><Plus /></IconButton>
03

Toolbar with visible escape

Pair a visible Button with tooltip-backed icon actions when only the secondary commands can be icon-only.

<Inline gap="sm">
  <Button variant="outline" leftIcon={<Download />}>Export report</Button>
  <Tooltip content="Search insights">
    <IconButton variant="ghost" aria-label="Search insights"><Search /></IconButton>
  </Tooltip>
  <Tooltip content="More actions">
    <IconButton variant="ghost" aria-label="More actions"><MoreHorizontal /></IconButton>
  </Tooltip>
</Inline>

When to use it

Use it for

  • Dense toolbars where the action icon is conventional: search, download, close, or more actions.
  • Secondary commands beside a labelled Button when the row would otherwise become noisy.
  • Transient loading on icon-only actions where aria-busy needs to follow the disabled state.

Reach for something else

  • Primary page actions that need a visible verb — use Button instead.
  • Overflow lists or more than three hidden commands — use Menu instead.
  • Hints that explain an unfamiliar icon — wrap the IconButton in Tooltip.

Props

PropTypeDefaultDescription
aria-labelstringRequired accessible label — the button has no visible text, so this names it for assistive tech.
childrenReactNodeThe icon to render. Replaced by a spinner while loading.
variant"default" | "secondary" | "destructive" | "outline" | "ghost""default"Visual style. The "link" variant is excluded — an underline makes no sense on an icon-only control.
size"icon" | "iconXs" | "iconSm" | "iconLg""icon"Square control size — padding plus the icon dimension.
loadingbooleanfalseShows a spinner, disables interaction, and sets aria-busy.

See also