IconButton allows users to take actions and make choices with a single click or tap. IconButtons use icons instead of text to convey available actions on a screen. IconButton is typically found in forms, dialogs and toolbars.
Some buttons are specialized for particular tasks, such as navigation or presenting menus.

also known as Glyph button, Condensed Button

Figma:

Responsive:

Adaptive:

Props

Component props
Name
Type
Default
accessibilityLabel
Required
string
-

Label for screen readers to announce IconButton. See the Accessibility guidelines for details on proper usage.

accessibilityControls
string
-

Specifies the id of an associated element (or elements) whose contents or visibility are controlled by IconButton so that screen reader users can identify the relationship between elements. See the Accessibility guidelines for details on proper usage.

accessibilityExpanded
boolean
-

Indicates that IconButton hides or exposes collapsible components and expose whether they are currently expanded or collapsed. See the Accessibility guidelines for details on proper usage.

accessibilityHaspopup
boolean
-

Indicates that a component controls the appearance of interactive popup elements, such as menu or dialog. See the Accessibility guidelines for details on proper usage.

accessibilityPopupRole
"menu" | "dialog"
-

Indicates whether this component displays a menu, such as Dropdown, or a dialog, like Popover, Modal or ModalAlert. See the Accessibility guidelines for details on proper usage.

bgColor
"transparent"
| "transparentDarkGray"
| "transparentDarkGray"
| "gray"
| "lightGray"
| "washLight"
| "white"
| "red"
-

Primary colors to apply to the IconButton background.

dangerouslySetSvgPath
{
  __path: string;
}
-

Defines a new icon different from the built-in Gestalt icons.

dataTestId
string
-

Available for testing purposes, if needed. Consider better queries before using this prop.

disabled
boolean
-

When disabled, IconButton looks inactive and cannot be interacted with.

focusColor
"lightBackground" | "darkBackground"
"lightBackground"

Indicates whether this component is hosted in a light or dark container.
Used for improving focus ring color contrast.

icon
unknown
-

Icon displayed in IconButton to convey the behavior of the component. Refer to the iconography guidelines regarding the available icon options.

iconColor
"gray" | "darkGray" | "red" | "white" | "brandPrimary" | "light" | "dark"
-

Primary color to apply to the Icon. See icon color variant to learn more.

label
string
-

Visible label for the IconButton. Only visible in XL size IconButtons. See the label variant to learn more.

name
string
-

The name attribute specifies the name of the button element. The name attribute is used to reference form-data after the form has been submitted and for testing.

onClick
(arg1: {
  event: React.MouseEvent<HTMLButtonElement> | React.KeyboardEvent<HTMLButtonElement>;
}) => void
-

Callback fired when the component is clicked, pressed or tapped.

padding
1 | 2 | 3 | 4 | 5
-

Sets a padding for the IconButton. See the size variant to learn more.

ref
HTMLButtonElement
-

Ref that is forwarded to the underlying button element.

selected
boolean
-

Toggles between binary states: on/off, selected/unselected, open/closed. See the selected variant to learn more.

size
"xs" | "sm" | "md" | "lg" | "xl"
"lg"

The maximum height and width of IconButton. See the size variant to learn more.

tabIndex
-1 | 0
0

Removes IconButton from sequential keyboard navigation to improve accessibility. See the Accessibility guidelines for details on proper usage.

tooltip
{
  accessibilityLabel?: string;
  inline?: boolean;
  idealDirection?: "up" | "right" | "down" | "left";
  text: string;
  zIndex?: Indexable;
}
-

Adds a Tooltip on hover/focus of the IconButton.

type
"submit" | "button"
-

Use "submit" if IconButton is used within or associated with a form.

Usage guidelines

When to use
  • Interface space is limited. Prioritize using a Button if space is available.
  • Triggering a Modal to complete a related task.
  • Creating visual separation of actions in text-heavy content.
  • Lower-emphasis actions that don't impede users from completing a task.
When not to use
  • Displaying icons that don't have actions associated with them. Use an Icon instead.
  • Displaying multiple IconButtons on a surface that uses the same icon for different actions.
  • Text is better suited to convey the action and/or the icon isn't quickly recognizable by users.
  • Destructive, high-emphasis actions, e.g "delete", "remove".

Best practices

Do

Use IconButton to perform low-emphasis actions, such as opening a Modal to edit a board.

Don't

Pair IconButton with a regular button to perform a high-emphasis action. IconButton should be a secondary action among regular buttons.

Do

Consider grouping multiple actions in an "ellipsis" IconButton to avoid distraction with an overload of icons.

Don't

Display more than 4 icon buttons in a single row as it can cause cognitive load and usability issues.

Do

Display a Tooltip in conjunction with IconButton to provide context when the icon alone would be insufficient to convey the purpose of the button.

Don't

Add an IconButton on top of images unless it has a background that ensures easy readability and accessible contrast. Check the background color variant to learn more.

Accessibility

ARIA attributes

IconButton conveys the component behavior using iconography. IconButton requires accessibilityLabel, a text description for screen readers to announce and communicate the represented Icon. In the example below, the screen reader reads: "Create Pin menu". The label should describe the intent of the action, not the Icon itself. For example, use "Edit board" instead of "Pencil".

If IconButton is used as a control button to show/hide a Popover-based component, we recommend passing the following ARIA attributes to assist screen readers:

  • accessibilityControls: informs the screen reader that IconButton controls the display of an anchored Popover-based component. It populates aria-controls.
  • accessibilityHaspopup: informs the screen reader that there’s a Popover-based component attached to IconButton. It populates aria-haspopup.
  • accessibilityExpanded: informs the screen reader whether an anchored Popover-based component is currently open or closed. It populates aria-expanded.
import { useRef, useState } from 'react';
import { Box, Dropdown, Flex, IconButton } from 'gestalt';

export default function Example() {
  const [open, setOpen] = useState(false);
  const [selected, setSelected] = useState([]);
  const anchorRef = useRef(null);

  const onSelect = ({ item }) => {
    if (selected.some(({ value }) => value === item.value)) {
      setSelected((selectedValue) =>
        selectedValue.filter(({ value }) => value !== item.value)
      );
    } else {
      setSelected((selectedValue) => [...selectedValue, item]);
    }
  };

  return (
    <Box padding={4}>
      <Flex justifyContent="center" width="100%">
        <IconButton
          ref={anchorRef}
          accessibilityControls="accessibility-example"
          accessibilityExpanded={open}
          accessibilityHaspopup
          accessibilityLabel="Create Pin Menu"
          bgColor="lightGray"
          icon="add"
          iconColor="darkGray"
          onClick={() => setOpen((prevVal) => !prevVal)}
          selected={open}
          size="lg"
          tooltip={{ text: 'Create Pin', idealDirection: 'up' }}
        />
        {open && (
          <Dropdown
            anchor={anchorRef.current}
            id="accessibility-example"
            onDismiss={() => setOpen(false)}
          >
            <Dropdown.Section label="Create">
              <Dropdown.Item
                onSelect={onSelect}
                option={{ value: 'Pin', label: 'Pin' }}
                selected={selected}
              />
              <Dropdown.Item
                onSelect={onSelect}
                option={{ value: 'Story Pin', label: 'Story Pin' }}
                selected={selected}
              />
            </Dropdown.Section>
          </Dropdown>
        )}
      </Flex>
    </Box>
  );
}

Keyboard interaction

The default behaviour for IconButton is to be focusable in sequential keyboard navigation in the order defined by the document's source order.

Use tabIndex to remove IconButton from the sequential keyboard navigation to improve accessibility. The example below shows a common use case when two consecutive and visually different elements perform the same action. One of them, in this case IconButton, can be removed from keyboard navigation to prevent screen readers from announcing the same interaction twice.
If IconButton is disabled, it's also unreachable from keyboard navigation.

import { Avatar, Flex, IconButton, Link, Text } from 'gestalt';

export default function Example() {
  return (
    <Flex
      alignItems="center"
      gap={2}
      height="100%"
      justifyContent="center"
      width="100%"
    >
      <Avatar
        name="James Jones"
        size="md"
        src="https://i.ibb.co/2Fc00R3/james.jpg"
      />
      <Flex alignItems="center" gap={{ row: 2, column: 0 }}>
        <Text inline weight="bold">
          <Link
            accessibilityLabel="Open the settings page"
            display="inlineBlock"
            href="https://www.pinterest.com/settings/"
            target="blank"
            underline="none"
          >
            James Jones
          </Link>
        </Text>
        <IconButton
          accessibilityLabel="Open the settings page"
          icon="edit"
          onClick={() => {}}
          size="xs"
          tabIndex={-1}
          tooltip={{ text: 'Edit name' }}
        />
      </Flex>
    </Flex>
  );
}

Selected state

IconButton has a selected state to visually indicate that the element is selected, open, and/or active. If the selected state controls the display of a Popover-based component (open/closed), use accessibilityExpanded to inform screen reader users. See the Accessibility guidelines to learn more.

import { useRef, useState } from 'react';
import { Box, Dropdown, Flex, IconButton } from 'gestalt';

export default function Example() {
  const [open, setOpen] = useState(false);
  const [selected, setSelected] = useState([]);
  const anchorRef = useRef(null);

  const onSelect = ({ item }) => {
    if (selected.some(({ value }) => value === item.value)) {
      setSelected((selectedValue) =>
        selectedValue.filter(({ value }) => value !== item.value)
      );
    } else {
      setSelected((selectedValue) => [...selectedValue, item]);
    }
  };

  return (
    <Box padding={4}>
      <Flex justifyContent="center" width="100%">
        <IconButton
          ref={anchorRef}
          accessibilityControls="sections-dropdown-example"
          accessibilityExpanded={open}
          accessibilityHaspopup
          accessibilityLabel="Create Pin Menu"
          bgColor="lightGray"
          icon="add"
          iconColor="darkGray"
          onClick={() => setOpen((prevVal) => !prevVal)}
          selected={open}
          size="lg"
          tooltip={{
            text: 'Create',
            accessibilityLabel: '',
            idealDirection: 'up',
          }}
        />
        {open && (
          <Dropdown
            anchor={anchorRef.current}
            id="sections-dropdown-example"
            onDismiss={() => setOpen(false)}
          >
            <Dropdown.Section label="Create">
              <Dropdown.Item
                onSelect={onSelect}
                option={{ value: 'Pin', label: 'Pin' }}
                selected={selected}
              />
              <Dropdown.Item
                onSelect={onSelect}
                option={{ value: 'Story Pin', label: 'Story Pin' }}
                selected={selected}
              />
            </Dropdown.Section>
            <Dropdown.Section label="Add">
              <Dropdown.Item
                badge={{ text: 'New' }}
                onSelect={onSelect}
                option={{ value: 'Note', label: 'Note' }}
                selected={selected}
              />
            </Dropdown.Section>
          </Dropdown>
        )}
      </Flex>
    </Box>
  );
}

Localization

Be sure to localize all text strings. Note that localization can lengthen text by 20 to 30 percent.

Variants

Size

IconButton is available in 5 fixed sizes:

  1. xl (56px)
    Extra large IconButtons should be used sparingly and only in places where the UI has a case for an extra-large IconButton. A common use case is IconButtonFloating.
  2. lg (48px)
    Large is the only size that should be used on Pinner surfaces.
  3. md (40px)
    Medium is the size used on more dense UI such as business surfaces or internal tools.
  4. sm (32px)
    Small IconButton should be used sparingly and only in places where the UI is very dense.
  5. xs (24px)
    Use sparingly and only in places where the UI is very dense or has a case for an extra-small IconButton as they can be hard to see for people with visual impairments.

Use padding sparingly. The padding options are 1-5, which represents the padding in increments of 4 pixels (2 = 8px padding). Combine the padding with size options for custom icon/button size ratios. If omitted, padding is derived from the default padding for each size prop.

size="xl"
size="lg"
size="md"
size="sm"
size="xs"

States

IconButton's appearance can be modified by the following states:

  1. default
    The default, enabled and unselected state.
  2. selected
    Selected state, used to indicate that the button and associated elements are selected, open, and/or active.
  3. disabled
    Disabled state, used to indicate that the button is not currently available for interaction.
import { Flex, IconButton } from 'gestalt';

export default function Example() {
  return (
    <Flex
      alignItems="center"
      gap={8}
      height="100%"
      justifyContent="center"
      width="100%"
      wrap
    >
      <IconButton
        accessibilityLabel="Share"
        bgColor="gray"
        icon="share"
        label="gray"
        size="xl"
      />
      <IconButton
        accessibilityLabel="lightGray"
        bgColor="lightGray"
        icon="share"
        label="lightGray"
        size="xl"
      />
      <IconButton
        accessibilityLabel="Share"
        bgColor="red"
        icon="share"
        label="red"
        size="xl"
      />
      <IconButton
        accessibilityLabel="transparent"
        bgColor="transparent"
        icon="share"
        label="transparent"
        size="xl"
      />
      <IconButton
        accessibilityLabel="transparentDarkGray"
        bgColor="transparentDarkGray"
        icon="share"
        label="transparentDarkGray"
        size="xl"
      />
      <IconButton
        accessibilityLabel="washLight"
        bgColor="washLight"
        icon="share"
        label="washLight"
        size="xl"
      />
      <IconButton
        accessibilityLabel="white"
        bgColor="white"
        icon="share"
        label="white"
        size="xl"
      />
    </Flex>
  );
}

import { Flex, IconButton } from 'gestalt';

export default function Example() {
  return (
    <Flex
      alignItems="center"
      gap={8}
      height="100%"
      justifyContent="center"
      width="100%"
      wrap
    >
      <IconButton
        accessibilityLabel="Share"
        bgColor="gray"
        disabled
        icon="share"
        label="gray"
        size="xl"
      />
      <IconButton
        accessibilityLabel="Share"
        bgColor="lightGray"
        disabled
        icon="share"
        label="lightGray"
        size="xl"
      />
      <IconButton
        accessibilityLabel="Share"
        bgColor="red"
        disabled
        icon="share"
        label="red"
        size="xl"
      />
      <IconButton
        accessibilityLabel="Share"
        bgColor="transparent"
        disabled
        icon="share"
        label="transparent"
        size="xl"
      />
      <IconButton
        accessibilityLabel="Share"
        bgColor="transparentDarkGray"
        disabled
        icon="share"
        label="transparentDarkGray"
        size="xl"
      />
      <IconButton
        accessibilityLabel="Share"
        bgColor="washLight"
        disabled
        icon="share"
        label="washLight"
        size="xl"
      />
      <IconButton
        accessibilityLabel="Share"
        bgColor="white"
        disabled
        icon="share"
        label="white"
        size="xl"
      />
    </Flex>
  );
}

import { Flex, IconButton } from 'gestalt';

export default function Example() {
  return (
    <Flex
      alignItems="center"
      gap={8}
      height="100%"
      justifyContent="center"
      width="100%"
      wrap
    >
      <IconButton
        accessibilityLabel="Share"
        bgColor="gray"
        icon="share"
        label="selected"
        selected
        size="xl"
      />
      <IconButton
        accessibilityLabel="Share"
        bgColor="lightGray"
        disabled
        icon="share"
        label="disabled + selected"
        selected
        size="xl"
      />
    </Flex>
  );
}

Label

You can add a label for the IconButton. It is only visible in XL size IconButtons.

It is recommended to use short labels for IconButtons, but the label will wrap up to two lines if needed.

import { Flex, IconButton } from 'gestalt';

export default function Example() {
  return (
    <Flex
      alignItems="center"
      height="100%"
      justifyContent="center"
      width="100%"
    >
      <IconButton
        accessibilityLabel="Share"
        bgColor="lightGray"
        icon="share"
        iconColor="darkGray"
        label="Share"
        size="xl"
        tooltip={{ text: 'Send pin to others', idealDirection: 'up' }}
      />
    </Flex>
  );
}

Focus ring on dark backgrounds

IconButtonLink can be used on dark backgrounds. The focus ring is visible on dark backgrounds to ensure accessibility.

import { Box, Flex, IconButton } from 'gestalt';

export default function Example() {
  return (
    <Flex gap={6}>
      <Flex direction="column" gap={6}>
        <Flex direction="column">
          <Box
            alignItems="center"
            dangerouslySetInlineStyle={{
              __style: {
                backgroundImage: 'url("https://i.ibb.co/rcdDzVh/image.png")',
              },
            }}
            display="flex"
            height="100%"
            justifyContent="center"
            padding={8}
          >
            <IconButton
              accessibilityLabel="heart"
              focusColor="lightBackground"
              icon="heart"
              iconColor="red"
            />
          </Box>
          focusColor=&quot;lightBackground&quot;
        </Flex>
        <Flex direction="column">
          <Box
            alignItems="center"
            dangerouslySetInlineStyle={{
              __style: {
                backgroundImage: 'url("https://i.ibb.co/DC0sQrx/image.png")',
              },
            }}
            display="flex"
            height="100%"
            justifyContent="center"
            padding={8}
          >
            <IconButton
              accessibilityLabel="heart"
              focusColor="darkBackground"
              icon="heart"
              iconColor="red"
            />
          </Box>
          focusColor=&quot;darkBackground&quot;
        </Flex>
      </Flex>
      <Flex direction="column" gap={6}>
        <Flex direction="column">
          <Box
            alignItems="center"
            dangerouslySetInlineStyle={{
              __style: {
                backgroundImage: 'url("https://i.ibb.co/rcdDzVh/image.png")',
              },
            }}
            display="flex"
            height="100%"
            justifyContent="center"
            padding={8}
          >
            <IconButton
              accessibilityLabel="heart"
              focusColor="lightBackground"
              icon="heart"
              iconColor="red"
            />
          </Box>
          focusColor=&quot;lightBackground&quot;
        </Flex>
        <Flex direction="column">
          <Box
            alignItems="center"
            dangerouslySetInlineStyle={{
              __style: {
                backgroundImage: 'url("https://i.ibb.co/DC0sQrx/image.png")',
              },
            }}
            display="flex"
            height="100%"
            justifyContent="center"
            padding={8}
          >
            <IconButton
              accessibilityLabel="heart"
              focusColor="darkBackground"
              icon="heart"
              iconColor="red"
            />
          </Box>
          focusColor=&quot;darkBackground&quot;
        </Flex>
      </Flex>
    </Flex>
  );
}

Icon color

IconButton can be presented in combinations of icon and background colors. In the absence of combinations, for each iconColor or bgColor value, a default paired value is assigned.

Follow these guidelines for iconColor

  1. Red ("red"). High emphasis, used for primary actions.
  2. Dark Gray ("darkGray"). Medium emphasis, used for secondary actions.
  3. Gray ("gray"). Low emphasis when placed on white backgrounds, used for tertiary actions. Medium emphasis when placed on dark backgrounds, used for secondary actions.
  4. White ("white"). Used in a dark mode scheme or over a dark-colored background creating better visibility.
  5. Brand primary ("brandPrimary"). Used to represent the Pinterest brand.
  6. Light ("light"). Used over a dark-colored background that does not change in dark mode, like transparentDarkGray, creating better visibility.
  7. Dark ("dark"). Used over a light-colored background that does not change in light mode, like washLight, creating better visibility.
iconColor="red"
iconColor="darkGray"
iconColor="gray"
iconColor="white"
iconColor="brandPrimary"
iconColor="light"
iconColor="dark"

Background color

IconButton can be presented in combinations of icon and background colors. In the absence of combinations, for each iconColor or bgColor value, a default paired value is assigned.

Follow these guidelines for bgColor

  1. Red ("red"). High emphasis, used for primary actions.
  2. Light Gray ("lightGray"). Medium emphasis, used for secondary actions.
  3. Transparent Dark Gray ("transparentDarkGray"). Medium emphasis, used for secondary actions, usually above a colored background.
  4. Gray ("gray"). Used for tertiary actions or in cases where the primary "red" is not an option. Medium emphasis when placed on dark backgrounds, used for secondary actions.
  5. Light Wash ("washLight"). Used when there is a need of a semi-transparent IconButton with a light wash over an item, like an image.
  6. White ("white"). Used when there is a need of an IconButton over an image or colored background to provide better contrast and visibility.
  7. Transparent ("transparent"). Used when there is a need to have an IconButton over an image without a background.
bgColor="red"
bgColor="lightGray"
bgColor="transparentDarkBackground"
bgColor="transparentDarkGray"
bgColor="gray"
bgColor="washLight"
bgColor="white"
bgColor="transparent"

With Tooltip

By specifying the tooltip property, a Tooltip will automatically be triggered when IconButton is hovered or focused. If the Tooltip text does not provide more information than the IconButton accessibilityLabel, set the tooltip prop's accessibilityLabel to an empty string, as seen below in the Edit example.

import { Flex, IconButton } from 'gestalt';

export default function Example() {
  return (
    <Flex
      alignItems="center"
      gap={4}
      height="100%"
      justifyContent="center"
      width="100%"
    >
      <IconButton
        accessibilityLabel="Sharing"
        icon="share"
        tooltip={{
          text: 'This Pin is private unless you share it with others.',
          idealDirection: 'up',
        }}
      />
      <IconButton
        accessibilityLabel="Edit"
        icon="edit"
        tooltip={{
          text: 'Edit',
          accessibilityLabel: '',
          idealDirection: 'up',
        }}
      />
    </Flex>
  );
}

Custom icon

IconButton accepts both Gestalt Icons and custom icons, as shown in the second example. For custom icons, follow our custom SVG icons guidelines.

Built-in icon
import { Flex, IconButton } from 'gestalt';

export default function Example() {
  return (
    <Flex
      alignItems="center"
      gap={2}
      height="100%"
      justifyContent="center"
      width="100%"
    >
      <IconButton
        accessibilityLabel="Go to next steps"
        icon="directional-arrow-right"
      />
    </Flex>
  );
}

Custom SVG icon
import { Flex, IconButton } from 'gestalt';

export default function Example() {
  return (
    <Flex
      alignItems="center"
      gap={2}
      height="100%"
      justifyContent="center"
      width="100%"
    >
      <IconButton
        accessibilityLabel="Go to next steps"
        dangerouslySetSvgPath={{
          __path:
            'M23 5v14a4 4 0 0 1-4 4H5a4 4 0 0 1-4-4v-5.5h10.258l-1.94 1.939a1.5 1.5 0 0 0 2.121 2.122L17 12l-5.561-5.561a1.501 1.501 0 0 0-2.121 2.122l1.94 1.939H1V5a4 4 0 0 1 4-4h14a4 4 0 0 1 4 4',
        }}
      />
    </Flex>
  );
}

Writing

When pairing IconButton with Tooltip, refer to the Tooltip component for writing guidelines.

Do
  • Use a descriptive label to describe the IconButton action by beginning with a verb.
Don't

Use the words "image" or "icon" in the description label; instead, prefer to use verbs that describe the action, e.g. "Save" or "Edit".

Component quality checklist

Component quality checklist
Quality item
Status
Status description
Figma Library
Ready
Component is available in Figma for web and mobile web.
Responsive Web
Ready
Component responds to changing viewport sizes in web and mobile web.

Internal documentation

IconButtonLink
Use IconButtonLink when a link is needed instead of an action.

Button
Button allows users to take actions, and make choices using text labels to express what action will occur when the user interacts with it.

Icon
IconButtons use icons instead of text to convey available actions on a screen. Use an existing one from the Gestalt Icon library.

Dropdown
It's most common to anchor Dropdown to Button or IconButton.