Icon Button

stable

IconButton is a compact native button whose visible content is an icon rather than a text label. It is intended for familiar, frequently used actions where space is limited and the icon’s meaning is clear from established conventions or surrounding context.

Because the action is not visibly named, every IconButton requires an accessible label that describes what the control does.

Variants
Sizes
Disabled
Loading

Basic usage

Provide a familiar icon and a non-empty aria-label that describes the action.

---
import { IconButton } from "@ulubit/ui";
---
<IconButton aria-label="Close dialog">
  <CloseIcon />
</IconButton>

Use an ordinary Button when visible text would make the action clearer.

Accessible label

Every icon button requires a non-empty aria-label because its icon is hidden from assistive technologies.

The label must describe the action, not the icon’s appearance.

Prefer:

  • Copy link
  • Close dialog
  • Delete project
  • Open settings

Avoid:

  • Copy icon
  • X
  • Trash can
  • Button
<IconButton aria-label="Copy link">
  <CopyIcon />
</IconButton>

Variants

Choose a variant based on the action’s purpose and priority.

Variant Use for
primary A high-emphasis icon action
secondary A visible alternative or supporting action
tertiary Most compact supporting actions
danger A destructive icon action

tertiary is the default because icon-only controls are usually supporting actions that should not compete with the page’s primary action.

Use a specific accessible label for danger actions, such as Delete project rather than Delete when the affected item is not otherwise clear.

IconButton uses the same variant and disabled color tokens as Button. See Button color tokens for the complete reference.

Sizes

Icon buttons support sm, md, and lg. Size controls both the square target and the icon dimensions.

Size Use for
sm Compact interfaces with sufficient spacing between controls
md Most icon-button uses
lg Spacious interfaces or intentionally larger targets

md is the default.

<IconButton aria-label="Edit item" size="sm">
  <EditIcon />
</IconButton>

<IconButton aria-label="Edit item">
  <EditIcon />
</IconButton>

<IconButton aria-label="Edit item" size="lg">
  <EditIcon />
</IconButton>

Disabled state

Use the native disabled attribute when the action is unavailable.

<IconButton aria-label="Delete project" variant="danger" disabled>
  <TrashIcon />
</IconButton>

A disabled icon button cannot be focused or activated. Provide nearby context when the reason it is unavailable would otherwise be unclear.

Loading state

Use loading while an action is being processed.

<IconButton
  aria-label="Delete project"
  variant="danger"
  loading
  loadingLabel="Deleting project"
>
  <TrashIcon />
</IconButton>

While loading, the component shows a progress indicator, disables activation, sets aria-busy="true", and uses loadingLabel as its accessible name.

loadingLabel must be non-empty and should describe the operation in progress. The consuming application remains responsible for managing the asynchronous operation and announcing important success or failure results.

The loading prop controls the state rendered by Astro. If loading changes after the page loads, the consuming application must update the button from client-side code.

Tooltips

aria-label provides an accessible name, but it does not create visible help text.

Use a text Button when the icon is not clear enough on its own. Do not add a title attribute as a substitute for a well-designed visible label or a proper Tooltip component.

Boundaries

IconButton performs an action. It does not provide:

  • navigation behavior
  • toggle or pressed-state behavior
  • automatic tooltips

Use a native <a> for icon-only navigation. Use ButtonLink when the navigation control has a visible text label.

Introduce a dedicated toggle-button pattern only when an action requires a persistent pressed state.

Accessibility

IconButton renders a native <button> and retains its built-in keyboard and focus behavior. The required aria-label supplies its accessible name, while the decorative icon is hidden from assistive technologies.

API

The component accepts valid native <button> attributes except aria-labelledby, and aria-busy. aria-label is required through the component API.

Property Type Default Description
aria-label string Required Provides the button’s accessible name.
variant "primary" | "secondary" | "tertiary" | "danger" "tertiary" Defines visual hierarchy and intent.
size "sm" | "md" | "lg" "md" Defines the square target and icon dimensions.
loading boolean false Displays the loading state and prevents repeated activation.
loadingLabel string Provides the accessible name while loading. Required when loading is true.
type "button" | "submit" | "reset" "button" Defines native button behavior.
disabled boolean false Prevents interaction with the button.
class string Adds a class alongside the component’s internal classes.
Default slot AstroComponentFactory Required Provides the decorative icon.

Native attributes such as name, value, form, aria-describedby, aria-controls, and data-* are forwarded to the underlying <button>.