> ## Documentation Index
> Fetch the complete documentation index at: https://docs.twenty.com/llms.txt
> Use this file to discover all available pages before exploring further.

# IconButton

> Trigger actions with accessible icon buttons.

export const StoryEmbed = ({storyId, title, height = 120}) => <>
    <Tabs>
      <Tab title="Light">
        <iframe title={`${title} (light)`} src={`https://storybook.twenty.com/iframe.html?id=${storyId}&viewMode=story&globals=colorScheme:light`} width="100%" height={height} loading="lazy" allow="clipboard-write" style={{
  border: 0
}} />
      </Tab>
      <Tab title="Dark">
        <iframe title={`${title} (dark)`} src={`https://storybook.twenty.com/iframe.html?id=${storyId}&viewMode=story&globals=colorScheme:dark`} width="100%" height={height} loading="lazy" allow="clipboard-write" style={{
  border: 0
}} />
      </Tab>
    </Tabs>
    <a href={`https://storybook.twenty.com/?path=/story/${storyId}`}>
      Open in Storybook
    </a>
  </>;

`IconButton` composes [Button](/ui/primitives/input/button) with a square or round surface. Pass the icon as children and provide an accessible name with `aria-label` or `aria-labelledby`. Icon content is decorative and hidden from assistive technology.

<StoryEmbed storyId="ui-components-iconbutton--display" title="Icon button with an accessible name" height={110} />

## Usage

```tsx theme={null}
import { IconButton } from 'twenty-ui/components/input';
import { IconSearch } from 'twenty-ui/icon';

export const SearchButton = () => (
  <IconButton aria-label="Search">
    <IconSearch />
  </IconButton>
);
```

Sizes are `xs` (20px), `sm` (24px), and `md` (32px). The defaults are `md`, `outline`, and `neutral`. Variants and colors match Button. Use `shape="round"` for a circular button; the default shape is `square`.

## Visual options

Compare one visual choice at a time. Use the named tooltip, elevated, and grouped examples for composition.

<StoryEmbed storyId="ui-components-iconbutton--catalog" title="Icon button variants, colors, sizes, shapes, elevation, and states" height={810} />

## Accessible names

Use `aria-label` for a name supplied directly on the control. When visible text already names the action, use `aria-labelledby` to reference it instead. At least one naming prop is required.

```tsx theme={null}
import { IconButton } from 'twenty-ui/components/input';
import { IconSearch } from 'twenty-ui/icon';
import { Text } from 'twenty-ui/primitives/typography';

export const LabelledSearchButton = () => (
  <Text style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
    <Text render={<span />} id="records-search-label">
      Search records
    </Text>
    <IconButton aria-labelledby="records-search-label" tooltip="Find a record">
      <IconSearch />
    </IconButton>
  </Text>
);
```

<StoryEmbed title="Icon button named by visible text" storyId="ui-components-iconbutton--labelled-by" height={140} />

## Tooltip

Add `tooltip` to show text on hover and keyboard focus. Keep `aria-label` or `aria-labelledby` as the accessible name of the action. Disabled and loading buttons retain hover tooltips.

```tsx theme={null}
import { IconButton } from 'twenty-ui/components/input';
import { IconSearch } from 'twenty-ui/icon';

export const SearchRecordsButton = () => (
  <IconButton aria-label="Search" tooltip="Search records">
    <IconSearch />
  </IconButton>
);
```

<StoryEmbed title="Icon button with tooltip" storyId="ui-components-iconbutton--tooltip-documentation" height={140} />

The tooltip defaults to the bottom, with a 1000ms delay and a 5px offset. Use `tooltipPlace`, `tooltipDelay`, and `tooltipOffset` to adjust it. Omitting `tooltip` renders the button directly.

## State ownership

Your application supplies `loading` and `disabled`. Both prevent activation. Loading preserves the square dimensions and accessible label. The button does not track a selected value or set loading automatically after a click. Native keyboard focus follows the browser; use `aria-pressed` when your application owns a toggle state.

## Elevated actions

Use `elevated` to add a shadow and backdrop blur. The default neutral outline button also gains a bordered surface with matching icon and interaction colors. Other variants and semantic colors keep their existing palette.

`elevated` defaults to `false`. It does not change positioning, visibility, or size. The size remains `md` (32px) by default; set `size="sm"` for a 24px control.

```tsx theme={null}
import { IconButton } from 'twenty-ui/components/input';
import { IconPlus } from 'twenty-ui/icon';

export const AddWidgetButton = () => (
  <IconButton elevated size="sm" aria-label="Add widget">
    <IconPlus />
  </IconButton>
);
```

<StoryEmbed title="Elevated icon action" storyId="ui-components-iconbutton--elevated" height={100} />

Omit `elevated` or set it to `false` to restore the standard appearance. Elevated buttons support the same tooltips, loading states, links, and keyboard interactions.

<StoryEmbed title="Elevated icon action with tooltip" storyId="ui-components-iconbutton--elevated-tooltip" height={140} />

Replace existing `FloatingIconButton` controls with `IconButton elevated`. Pass the icon as children, use native `aria-label`, and map `small` to `sm` and `medium` to `md`. Supply `size="sm"` when the previous control used its default size. Native focus and `aria-pressed` replace synthetic focus and active flags.

`FloatingIconButtonGroup` is removed. Compose ButtonGroup with IconButton for grouped actions, and keep any shared floating surface in your layout.

## Grouped actions

```tsx theme={null}
import { ButtonGroup } from 'twenty-ui/primitives/input';
import { IconButton } from 'twenty-ui/components/input';
import { IconPlus, IconSearch } from 'twenty-ui/icon';

export const RecordActions = () => (
  <ButtonGroup
    aria-label="Record actions"
    size="sm"
    variant="solid"
    color="accent"
  >
    <IconButton
      aria-label="Search records"
      tooltip="Search records"
      variant="outline"
      color="neutral"
    >
      <IconSearch />
    </IconButton>
    <IconButton aria-label="Create record" tooltip="Create record">
      <IconPlus />
    </IconButton>
  </ButtonGroup>
);
```

[ButtonGroup](/ui/primitives/input/button-group) supplies defaults for size, variant, and color, plus adjoining corners. Explicit child props take precedence independently, including `size="xs"`. Individual buttons do not need a position prop.

Keep attached buttons the same size so their edges align. Set the size on the group and let each button inherit it.

<StoryEmbed storyId="ui-components-iconbutton--grouped-overrides" title="Individual icon button appearance in a group" height={140} />

## Links and forms

Without a custom `render`, `href` renders an anchor unless `nativeButton` is explicitly true. For a custom navigation anchor or router link, set `nativeButton={false}` and `role="link"`. The renderer can own its destination without an IconButton `href`. Keep `nativeButton` true for a custom native button, and use false for a non-native action element. Explicit nativeButton and role props are preserved. Disabled and loading links cannot activate. Routing stays in the application.

Native button and anchor attributes, event handlers, event details, refs, and render composition pass through to Button. The ref receives the actual root element. Tooltip composition preserves that root and its accessible name. The default is `type="button"`; set `type="submit"` explicitly for form submission.

## Compact and round controls

Use `size="xs"` for a 20px control and `shape="round"` for circular corners. Existing `RoundedIconButton` controls become `IconButton` with `shape="round"`, `variant="solid"`, and `color="accent"`. Map their old `small` size to `xs` and `medium` size to `sm`. Supply icon children and an accessible name.

<StoryEmbed storyId="ui-components-iconbutton--round-documentation" title="Round icon buttons in compact and regular sizes" height={140} />

## Props

<ParamField body="aria-label" type="string">
  Accessible name describing the action. Required unless `aria-labelledby` supplies the name.
</ParamField>

<ParamField body="aria-labelledby" type="string">
  ID of the element supplying the accessible name. Can be used instead of `aria-label`.
</ParamField>

<ParamField body="children" type="ReactNode" required>
  Icon content. Decorative and hidden from assistive technology.
</ParamField>

<ParamField body="className" type="string | ((state: ButtonState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="color" type="&#x22;accent&#x22; | &#x22;danger&#x22; | &#x22;neutral&#x22; | &#x22;success&#x22;" default="neutral">
  Semantic color of the button.
</ParamField>

<ParamField body="elevated" type="boolean">
  Adds a shadow and backdrop blur. Neutral outline buttons also use elevated surface colors.
</ParamField>

<ParamField body="focusableWhenDisabled" type="boolean" default="false">
  Whether the button should be focusable when disabled.
</ParamField>

<ParamField body="href" type="string">
  Destination URL. Renders a native anchor when `render` is omitted unless `nativeButton` is explicitly true. Custom renderers retain their own element contract.
</ParamField>

<ParamField body="loading" type="boolean">
  Shows a loading indicator and disables activation.
</ParamField>

<ParamField body="nativeButton" type="boolean" default="true (false for the built-in href anchor)">
  Whether the rendered root is a native button. Defaults to true for custom renderers. The built-in `href` anchor defaults to false; an explicit value takes precedence.
</ParamField>

<ParamField body="render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, ButtonState>">
  Caller-supplied root element or renderer. Native attributes, handlers, event details, and refs reach the rendered root. Use `nativeButton={false}` and `role="link"` for a custom navigation anchor. Router integration belongs to the caller.
</ParamField>

<ParamField body="role" type="AriaRole">
  Role of the root element. Use `link` for custom navigation renderers.
</ParamField>

<ParamField body="shape" type="&#x22;round&#x22; | &#x22;square&#x22;" default="square">
  Square or round icon control.
</ParamField>

<ParamField body="size" type="&#x22;md&#x22; | &#x22;sm&#x22; | &#x22;xs&#x22;" default="md">
  Button size: `xs` (20px), `sm` (24px), or `md` (32px).
</ParamField>

<ParamField body="style" type="CSSProperties | ((state: ButtonState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>

<ParamField body="tooltip" type="string">
  Text displayed when hovering or focusing the button.
</ParamField>

<ParamField body="tooltipDelay" type="number" default="1000">
  Delay before showing the tooltip.
</ParamField>

<ParamField body="tooltipOffset" type="number" default="5">
  Distance in pixels between the button and the tooltip.
</ParamField>

<ParamField body="tooltipPlace" type="&#x22;bottom&#x22; | &#x22;inline-end&#x22; | &#x22;inline-start&#x22; | &#x22;left&#x22; | &#x22;right&#x22; | &#x22;top&#x22;" default="bottom">
  Preferred placement of the tooltip relative to the button.
</ParamField>

<ParamField body="variant" type="&#x22;ghost&#x22; | &#x22;link&#x22; | &#x22;outline&#x22; | &#x22;soft&#x22; | &#x22;solid&#x22;" default="outline">
  Visual treatment of the button surface. `link` uses compact text styling without a filled surface or border; render composition determines native semantics.
</ParamField>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.