Skip to main content

Design system components

IconButton

Icon-only action button. Wraps @dt/Button in its rounded icon-only form with an enforced accessible label, sharing Button's variant (weight) x tone (semantic) matrix and surface awareness.

Status: stable. Group: actions. Markdown version: /design-system/components/icon-button.md

When to use

IconButton is an icon-only action for compact surfaces: toolbars, card corners, table rows, dialog close affordances. It wraps Button in its rounded icon-only form, so weight, tone, and surface behave exactly like Button; label is required and becomes the accessible name. A className is applied to an inline-flex wrapper span around the button, not to the button itself.

When not to use

  • Do not omit label; there is no fallback announcement.
  • Do not use for primary marketing CTAs; text + icon is more discoverable; use Button with an icon prop.
  • Do not rely on tooltip as the only accessible name.
  • Do not use IconButton for primary marketing CTAs; text plus icon is more discoverable, use Button with an icon prop.

Look-alikes

  • Button: Do not use IconButton for primary marketing CTAs; text plus icon is more discoverable, use Button with an icon prop.

Props

IconButton props
PropTypeDefaultDescriptionRequired
iconReactNode | stringnoneIcon glyph: a rendered element (e.g. <CaretRight />) or a Phosphor icon name (e.g. "x").Yes
labelstringnoneAccessible name when aria-labelledby is not set.Yes
variant"primary" | "secondary" | "tertiary"tertiaryVisual weight.No
toneButtonProps["tone"]neutralSemantic colour, orthogonal to variant.No
surfaceButtonProps["surface"]defaultSurface the control sits on; prefer over color overrides on tinted bands.No
size"sm" | "md" | "lg"mdNo description in the contract.No
tooltipstringnoneNative tooltip text shown on hover; the label stays the accessible name.No

Variants

  • Available variants: primary, secondary, tertiary (default tertiary).
  • Available tones: neutral, error, warning, success, info (default neutral).
  • Available surfaces: default, onDark, onBrand (default default).
  • Available sizes: sm, md, lg (default md).

Invalid combinations

The contract records no invalid combinations.

Keyboard

IconButton keyboard behaviour
KeyBehaviour
TabFocusable.
Enter / SpaceActivates.

Rules

Every item under When not to use is a MUST NOT. MUST and SHOULD follow RFC 2119.

IconButton rules
LevelRuleHow it is checked
MUSTARIA: label prop is required and renders as the accessible name; the icon glyph itself is aria-hidden.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTARIA: tooltip is hover-only garnish; it never replaces label as the accessible name.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTARIA: disabled (and Button's loading state) sets the native disabled attribute on the button, which removes it from the tab order and from pointer interaction; screen readers still expose it as a disabled button when browsing. It does not use aria-disabled.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTRequired stories produce no axe violations at the configured severity.Automated by npm run test:stories:matrix:ci. WCAG 2.5.8.
MUSTThe accessibility tree (role, name, state) matches the committed snapshot for every required story.Automated by npm run test:stories:matrix:ci. WCAG 1.3.1, 4.1.2.
MUSTThe component remains legible and operable under a real browser forced-colors: active pass.Automated by npm run test:stories:hc.
MUSTEvery documented keyboard interaction works as specified.Not yet verified: no evidence record. WCAG 2.1.1, 2.1.2.
MUSTA human completed an end-to-end accessibility review of this component.Manual review, last on 2026-11-04.
SHOULDWrite label as the action, like Close dialog or Copy link, never the icon name like X or Clipboard.Not stated in the contract.
SHOULDStay on the default variant=tertiary in toolbars and chrome; reserve primary for the one dominant action of a compact surface.Not stated in the contract.
SHOULDPick an icon whose meaning survives without text (x, magnifying-glass, caret-*); if you have to explain the icon, use Button with a visible label instead.Not stated in the contract.
SHOULDAdd tooltip for sighted-user reassurance on ambiguous glyphs; the label still carries the accessible name.Not stated in the contract.
SHOULDUse surface=onDark or onBrand when the control sits on a dark or brand band instead of overriding colors.Not stated in the contract.
SHOULD NOTDo not omit or auto-generate label; there is no fallback announcement and axe fails the render.Not stated in the contract.
SHOULD NOTDo not stack more than about five icon-only actions in a row without grouping or labels; recognition drops sharply.Not stated in the contract.

Install and import

  • Install: npm install @digitaltableteur/react (version 0.9.1, restricted access on npm).
  • Import: import { IconButton } from "@digitaltableteur/react";
  • Entry point: @digitaltableteur/react/actions exports it too.
  • Styles: import @digitaltableteur/react/style.css once at the app boundary.
  • Also available as the custom element <dt-icon-button>; see the custom elements manifest.