Skip to content

Design system

Documentation

DesignComponents / IconButton

Components / IconButton

Beta

IconButton

Use IconButton for a compact action whose visible content is an icon. It reuses Button behavior and requires an accessible name.

On this page

Examples

Accessible name

An icon-only action always exposes a concise aria-label.

IconButton with an accessible name

Variant and size

Match toolbar emphasis and touch target size to the surrounding context.

IconButton variant and size comparison

Disabled and loading

Inherited Button states keep the target stable and prevent repeat activation.

Disabled and loading IconButton states

With Tooltip

Tooltip adds context but does not replace the accessible name.

IconButton ready to pair with Tooltip

When to use

Use IconButton when the action is familiar from its icon and the surrounding context makes it easy to understand. Use a text Button when the action is new, high impact, or needs a longer explanation.

Good fit

Notifications, search, close, or compact toolbar actions with a stable label.

Use text instead

Do not hide “Delete account” or another consequential action behind an unfamiliar icon.

Usage

icon-button-basic.tsx
import { Bell } from "@phuctech/ui/icons";
import { IconButton } from "@phuctech/ui/components/icon-button";

export function Example() {
  return (
    <IconButton aria-label="View notifications" variant="outline">
      <Bell aria-hidden="true" />
    </IconButton>
  );
}

The required aria-label is the accessible name. Keep it short and describe the action, not the icon.

Variants and states

IconButton sizes and states
OptionUse for
xs, smDense toolbars and compact rows.
mdThe normal action target in a toolbar.
lgA more prominent action or touch-first surface.
disabled, loadingInherited Button states; loading keeps the target size stable.

Icons

Use a PhucTech icon from @phuctech/ui/icons and mark it aria-hidden="true". Do not use the icon as the only accessible name; the explicit aria-label is the contract.

API

Component API
PropTypeDefaultDescriptionConstraints
aria-labelstringrequiredAccessible name for the icon-only action.Required; describe the action in plain language.
size"xs" | "sm" | "md" | "lg""md"Maps to Button icon sizing and the shared touch-target scale.Choose a size that matches the surrounding density.
variantButton variant"default"Inherited visual intent from Button.Use a lower-emphasis variant for toolbars when appropriate.
loadingbooleanfalseInherited in-flight state from Button.Use while the action is being processed.
disabledbooleanfalsePrevents activation.Explain an unexpected unavailable state nearby.

Tokens

Component tokens
TokenRoleEffective valueUsage
--size-control-*Touch targetxs / sm / md / lgIconButton maps each public size to the Button control scale.
--size-icon-*Icon geometryxs / sm / md / lgPhucTech icons inherit the matching Button icon size.
--focus-ring-*Keyboard focus3px / 2px / semantic focusUses the shared visible focus contract.

Accessibility

  • Provide the required aria-label; a tooltip is not a replacement for the accessible name.
  • Test focus, Enter, Space, disabled, and loading states with a keyboard.
  • Keep the target at least the shared control size; do not shrink an icon only to fit more actions.

Do and don’t

Do

Use one clear action label, a familiar icon, and a visible focus ring.

Don’t

Render an unlabeled icon, rely on color alone, or put many ambiguous icons side by side.

  • Button provides the base variants, loading behavior, and focus contract.
  • Icons documents PhucTech sizing and decorative semantics.