BridgeHandbookDraft
For agents
Menu
ExperimentalatomActions

IconButton

An action shown only as an icon (close, more, copy). Always round; always named.

import { … } from "@brdgapp/ui/components/icon-button"

Usage

IconButton is the button that shows only an icon: close, more actions, back, copy, sync. It is always round and always has a name for screen readers (aria-label is required). The usual mistakes are hand-making a small round <button>, and naming it after the picture ("X") instead of the action ("Close").

When to use

  • Close a dialog, drawer or banner.
  • Open a row's actions menu (the kebab).
  • Copy, back, sync and other actions people recognize from the icon alone.
  • "Sync now" is always a refresh IconButton, never a text link.

When not to use

  • When the action isn't obvious from the icon. Add a label. Use Button instead.
  • For a menu of row actions: use the complete menu, which includes its own trigger. Use ActionMenu instead.
  • For a person's avatar used as a trigger. A photo is not an icon.

The look comes from props

A component's appearance comes only from its own options (variant, size, color). className on a package component is for layout (mt-4, shrink-0, w-full), never for font size, color, padding, radius or hover. If the look needs a className, the component or the chosen option is wrong: fix that instead.

One icon set, one icon per meaning

Every icon is Lucide at its own 2px line. Each meaning has one icon, listed on Iconography; a meaning that isn't listed gets a Lucide icon nobody else uses, added to the list in the same change. No other icon set, no emoji in the interface, and no hand-drawn company logos: BrandMark draws them.

Every control has a name

Every control says what it does to a screen reader. An icon-only button carries an aria-label naming the action ("Close", not "X"); a group of filters or a table has a name; a tooltip is never the only name.

Anatomy

  1. Container. A circle: 28, 32 or 36px.

  2. Icon. 16px, hidden from screen readers. The aria-label is the name.

  3. Spinner. Replaces the icon while loading.

Examples

Common actions

Each has an aria-label naming the action.

Sizes

28, 32 and 36px.

Sync now

Bridge's sync control is always a refresh IconButton.

States

RestHoverFocusDisabledLoading
Default
Danger
StateWhat happens
RestMuted icon, no fill.
HoverA light fill and darker icon. danger turns red.
Focus visible2px ring with a 2px offset.
Disabled30% opacity.
LoadingSpinner, disabled, aria-busy. Put the progress in the label: "Syncing accounts…".

Behavior

  • A native button through Base UI: Enter and Space press it, and it defaults to type="button".
  • For sync: idle shows refresh, loading shows the spinner, then a check when done or an alert icon with variant="danger" on failure. The state is in the aria-label, not visible text.

Do and don't

Do

Name the action: aria-label="Close".

Don't

Name the picture: aria-label="X icon".

Do

Pass a bare icon; the button sizes it.

Don't

Set className="h-5 w-5" on the icon.

Content

  • The aria-label is a verb phrase in sentence case: "Copy profile link", "More actions".

Accessibility

  • aria-label is required by the type, so a nameless icon button can't compile.
  • All sizes clear the 24px minimum target; sm (28px) is the smallest.
KeysAction
TabMoves focus to the button.
EnterSpacePresses it.

API reference

IconButton

The icon-only button, built on Base UI Button. Extends Base UI Button (native <button> attributes).

PropTypeDefaultDescription
aria-labelstring—Required. What the button does.
variant"default" | "danger""default"danger for removing or deleting.
size"sm" | "md" | "lg""md"28, 32 or 36px.
loadingbooleanfalseSpinner, disabled, aria-busy.
childrenReactNode—One bare Lucide icon.
classNamestring—Layout only. Merged last.

iconButtonVariants

The class recipe behind IconButton.

PropTypeDefaultDescription

Lineage

What it's built from and where it's used, read from the code. When you change it, check these too.

Built from
Nothing else in the package
Used in templates
None

Sources

  • Bridge OS components.md → the button-system family (IconButton, "Sync now" convention).
  • Bridge OS src/components/ui/icon-button.tsx.