Icon Button

A button component designed specifically for icons with various sizes and states.

Anatomy

Import and assemble the component:

1import { IconButton } from "@raystack/apsara";
2
3<IconButton />

Usage

An icon-only button built on the Base UI Button.

Size

Four steps, 1 through 4. Match the step to the control the button sits beside so their heights agree.

1<Flex gap={9} align="center">
2 <IconButton size={1}>
3 <Info size={16} />
4 </IconButton>
5 <IconButton size={2}>
6 <Info size={16} />
7 </IconButton>
8 <IconButton size={3}>
9 <Info size={16} />
10 </IconButton>
11 <IconButton size={4}>
12 <Info size={16} />
13 </IconButton>
14</Flex>

State

Hover and focus are handled for you. disabled stops the button responding and removes it from the tab order.

loading shows a spinner in place of the icon and sets aria-busy. The button blocks clicks while it loads but stays focusable, so focus is not lost.

1<Flex gap={9}>
2 <IconButton size={4}>
3 <Info size={16} />
4 </IconButton>
5 <IconButton size={4} disabled>
6 <Info size={16} />
7 </IconButton>
8 <IconButton size={4} loading>
9 <Info size={16} />
10 </IconButton>
11</Flex>

Focusable when disabled

focusableWhenDisabled keeps a disabled button in the tab order. The button uses aria-disabled instead of the native disabled attribute.

1<IconButton size={4} disabled focusableWhenDisabled aria-label="Info">
2 <Info size={16} />
3</IconButton>

Render as another element

render swaps the underlying element and keeps the styles. When render is set, nativeButton defaults to false, so the button role and keyboard handling are added. If render returns a real <button>, set nativeButton to true.

1<IconButton
2 size={4}
3 render={<a href="/docs/components/button" />}
4 aria-label="Go to Button docs"
5>
6 <Info size={16} />
7</IconButton>

API Reference

Renders a button designed for icon-only content.

Prop

Type

Slots

Every rendered part carries a stable data-slot attribute for styling and testing:

SlotElement
icon-buttonThe root <button> element
icon-button-iconWrapper around the icon content
icon-button-loaderThe loading spinner (when loading)

Styling

The IconButton uses CSS variables for consistent styling across themes:

  • Background color uses --rs-color-background-base-primary
  • Border color uses --rs-color-border-base-primary
  • Text color uses --rs-color-foreground-base-primary
  • Hover state uses --rs-color-background-base-primary-hover
  • Disabled state uses reduced opacity and different background/border colors

Accessibility

IconButton uses the Base UI Button, which renders a native <button> by default:

  • Enter and Space activate the button.
  • disabled sets the native disabled attribute. With focusableWhenDisabled or loading, it sets aria-disabled instead.
  • loading sets aria-busy="true". The spinner has aria-hidden="true".

For better accessibility, make sure to:

  • Provide meaningful aria-label when the button's purpose isn't clear from the icon alone
  • Consider adding tooltips for icon-only buttons