Skip to content

Icon button

Icon button — a button that is only its icon.

Beta · Actions · packages/css/src/components/icon-button.css · React on Base UI: @pepperui/icon-button

.pui-icon-button · shape --round · size --small --large · variant --secondary --ghost --danger. Always aria-label + a Tooltip.

Icon button — every size and every stateOpen in the workshop

Sizes across, states down.

  • Shape: square (radius 8 — actions are squares) or round (radius full — for the one floating action, never the default)
  • Size: small, medium, large; five states: default, hover, focus, pressed, disabled — Button’s rules exactly
  • Icon is an INSTANCE_SWAP on the Icon placeholder; the real Lucide glyph goes in when the Lucide subset lands
  • No label: the accessible name is a Tooltip on hover and an aria-label in code — both, always
  • Secondary and ghost are separate sets below, the way Button is split

Use when a toolbar, a table row’s actions, a dialog’s close, a topbar’s notifications — an action whose icon is universally read (close, edit, delete, search, more).

Do not use when the icon is not universally read — then it is a Button with a label and a leading icon; the action is the page’s main one (a labelled primary Button).

Relates to Button (same tokens), Tooltip (its name), Icon, Button group, Topbar, Table.

Anti-patterns an icon button with no tooltip and no aria-label · a primary icon button as the page’s main action · round by default · a 44 icon button in a table row.

Keywords: icon button, toolbar, action, close, edit, more

shadcn: Button size=“icon”

Figma — page Icon button: Icon button (30 variants) · Icon button - secondary (30 variants) · Icon button - ghost (30 variants)

shadcn: button

The class, the parts, and nothing that is not in the package. The same block opens icon-button.css.

<button class="pui-icon-button pui-icon-button--ghost" aria-label="Close">
<span class="pui-icon">…lucide x…</span></button>
What it is Note
Shape (none) square, radius 8 · --round, radius full — for the one floating action, never the default —
Size --small 28 · (none) medium 36 · --large 44 (icon 24) —
Variant (none) primary · --secondary · --ghost · --danger —

Rule — no label: aria-label in the markup and a Tooltip on hover — both, always.

Every number here is measured on the rendered component: contrast (npm run contrast:render), the focus ring (npm run focus) and the keyboard (npm run keyboard). The floors are principle 12’s.

ink on ground reads floor the matrix calls it
#544d4d on #ffffff 8.24 4.5 text.muted on surface.page (promised) ok

1 distinct pair(s) rendered, 0 that axe calls a violation.

12 of 12 focus stop(s) in this block meet WCAG 2.4.13 on screen — the same crop screenshotted focused and unfocused, and the difference measured.

Nothing in this component claims an ARIA role with a keyboard contract; its controls are ordinary ones and the browser already gives them their keys.

Tab order across the whole library is document order over 344 stops, and Shift+Tab is its exact reverse — no keyboard trap anywhere (WCAG 2.1.2).

Pepper UI v1.5.0

The Mobupps design system. 386 tokens, 88 components, 65 pages in the workshop — every page of this site generated from the repository, so nothing here is typed twice.