IconButton
Compact icon-only action and its link twin — same chrome as Button, with a required accessible name.
Base UI
IconButton is the compact, icon-only sibling of Button. Pass the glyph through icon; size, variant, pill, and loading follow the same chrome. The icon alone is not a name — every instance needs aria-label or aria-labelledby.
When the affordance should navigate (in-app route or external URL), use IconButtonLink instead. It shares the same visual chrome but renders a native <a>, or a framework Link via render. Do not force render={<a />} on IconButton; Base UI keeps button semantics there.
Variants follow the same intent rules as Button. Prefer flat in dense toolbars so icon actions stay quiet next to labeled commits. When loading is on, the control keeps its width, sets aria-busy, and shows a decorative Spinner over the icon. On IconButton, loading also blocks activation; on IconButtonLink, loading sets aria-disabled / aria-busy while the link stays activatable.
When to use
- Toolbar or header chrome where space is tight and a glyph is enough
- Icon-only navigation (
IconButtonLink) with a clear destination name - Quiet secondary actions next to a labeled primary Button
When not to use
- The action needs a visible text label → Button
- The control stays pressed or swaps icons after activation → ToggleButton
- A labeled control that stays pressed → ToggleTextButton
- Critical guidance that must stay visible without hover → put it in copy, not an icon alone (Tooltip can reinforce, not replace)
Related
- Button — labeled actions and
ButtonLink - ToggleButton — pressed-state icon toggles and groups
- ToggleTextButton — labeled pressed toggles and groups
- Tooltip — short hover/focus hints that match the accessible name
Common examples
Variants
Pick the variant from what the action means on that surface. A bare IconButton is already primary; reach for another variant when the action is not the commit. Every control still needs an accessible name.
Sizes
size steps the hit target and glyph together. Match toolbar density: s in tight chrome, l when the icon sits alone as a primary control.
Loading
Turn on loading while the request runs. Width stays stable so the layout does not jump when the Spinner appears; the Spinner itself stays decorative because aria-busy already marks the control.
Keep the same accessible name during the wait so the announced name stays continuous.
Toolbars
Toolbar strips live in a Surface: Stack row of IconButtons inside, with gap and alignment on the Stack (not per-button CSS). Flat variants keep the strip quiet; reserve destructive for irreversible actions.
If the action needs a visible text label, switch to Button. Do not force a caption beside icon.
As a link
Use IconButtonLink when activation should navigate. Same chrome as IconButton; different element — a native <a>, or a framework Link via render. The accessible name should say where the link goes, not only what the icon looks like.
Pass href for native or external URLs (target / rel when needed). Pass render for in-app framework routing. Labeled navigation belongs on Button (ButtonLink).
Ask your agent
Add a compact icon toolbar to this panel: settings, share, and delete. Label each icon button for screen readers. Show loading on one button during a short async action.Last updated on