Icon button

A compact button with an icon and no text.

Props

icon
GoabIconType
Sets the icon.
action
string
Action identifier passed in click events for event delegation patterns.
actionArg
string
Single argument value passed with the action in click events.
actionArgs
Record<string, unknown>
Multiple argument values passed with the action in click events.
ariaLabel
string
Sets the aria-label of the button.
disabled
boolean
Disables the button.
size
GoabIconSize
Sets the size of button.
Defaults to medium.
testId
string
Sets a data-testid attribute for automated testing.
theme
GoabIconTheme
Sets the theme of the icon inside the button. "outline" for stroked icons, "filled" for solid icons.
Defaults to outline.
title
string
Sets the title of the button.
variant
GoabIconButtonVariant
Styles the button to show color, light, dark or destructive action.
Defaults to color.
mt, mr, mb, ml
Spacing
Apply margin to the top, right, bottom, and/or left of the component.
icon
GoabIconType
Sets the icon.
action
string
Action identifier passed in click events for event delegation patterns.
actionArg
string
Single argument value passed with the action in click events.
actionArgs
Record<string, unknown>
Multiple argument values passed with the action in click events.
ariaLabel
string
Sets the aria-label of the button.
disabled
boolean
Disables the button.
size
GoabIconSize
Sets the size of button.
Defaults to medium.
testId
string
Sets the data-testid attribute for automated testing.
theme
GoabIconTheme
Sets the icon theme. "outline" for stroked icons, "filled" for solid icons.
Defaults to outline.
title
string
Sets the title of the button.
variant
GoabIconButtonVariant
Styles the button to show color, light, dark or destructive action.
mt, mr, mb, ml
Spacing
Apply margin to the top, right, bottom, and/or left of the component.
icon
GoabIconType
Sets the icon.
action
string
Action identifier passed in click events for event delegation patterns.
action-arg
string
Single argument value passed with the action in click events.
action-args
Record<string, unknown>
Multiple argument values passed with the action in click events.
Defaults to {}.
arialabel
string
Sets the aria-label of the button.
disabled
boolean true | false
Disables the button.
Defaults to false.
inverted
boolean true | false
When true, inverts the icon colors for use on dark backgrounds.
Defaults to false.
size
IconSize
Sets the size of button.
Defaults to medium.
testid
string
Sets a data-testid attribute for automated testing.
theme
IconTheme
Sets the icon theme. 'outline' for stroked icons, 'filled' for solid icons.
Defaults to outline.
title
string
Sets the title of the button.
variant
GoabIconButtonVariant color | nocolor | light | dark | destructive
Styles the button to show color, light, dark or destructive action.
Defaults to color.
mt, mr, mb, ml
Spacing
Apply margin to the top, right, bottom, and/or left of the component.

Events

onClick
() => void
Callback fired when the icon button is clicked.
onClick
() => void
Emits when the icon button is clicked.
_click
CustomEvent<{ event: Event }>
Examples

Copy to clipboard

.token-block {
  background-color: var(--goa-color-interactive-default);
  height: 22px;
  width: 24px;
  border-radius: var(--goa-border-radius-s);
}
const [isCopied, setIsCopied] = useState(false);

function copyCode() {
  const codeToCopy = "$goa-color-interactive-default";
  navigator.clipboard.writeText(codeToCopy).then(() => {
    setIsCopied(true);
    setTimeout(() => setIsCopied(false), 1000);
  });
}
<GoabBlock alignment="center">
  <div className="token-block" />
  <span>$goa-color-interactive-default</span>
  <GoabTooltip content={isCopied ? "Copied" : "Copy?"} position="top">
    <GoabIconButton icon="copy" onClick={copyCode} mt="2xs" />
  </GoabTooltip>
</GoabBlock>
isCopied = false;

copyCode(): void {
  const codeToCopy = "$goa-color-interactive-default";
  navigator.clipboard.writeText(codeToCopy).then(() => {
    this.isCopied = true;
    setTimeout(() => (this.isCopied = false), 1000);
  });
}
<goab-block alignment="center" gap="s">
  <div class="token-block"></div>
  <span>$goa-color-interactive-default</span>
  <goab-tooltip [content]="isCopied ? 'Copied' : 'Copy?'" position="top">
    <goab-icon-button icon="copy" (onClick)="copyCode()" mt="2xs"></goab-icon-button>
  </goab-tooltip>
</goab-block>
.token-block {
  background-color: var(--goa-color-interactive-default);
  height: 22px;
  width: 24px;
  border-radius: var(--goa-border-radius-s);
}
const copyBtn = document.getElementById("copy-btn");
const tooltip = document.getElementById("copy-tooltip");

function copyCode() {
  const codeToCopy = "$goa-color-interactive-default";
  navigator.clipboard.writeText(codeToCopy).then(() => {
    tooltip.setAttribute("content", "Copied");
    setTimeout(() => {
      tooltip.setAttribute("content", "Copy?");
    }, 1000);
  });
}

copyBtn.addEventListener("_click", copyCode);
<goa-block alignment="center">
  <div class="token-block"></div>
  <span>$goa-color-interactive-default</span>
  <goa-tooltip id="copy-tooltip" content="Copy?" position="top">
    <goa-icon-button id="copy-btn" icon="copy" mt="2xs"></goa-icon-button>
  </goa-tooltip>
</goa-block>

Show a label on an icon only button

<GoabButtonGroup alignment="start">
  <GoabTooltip content="Edit">
    <GoabIconButton icon="pencil" ariaLabel="Edit" />
  </GoabTooltip>
  <GoabTooltip content="Alerts">
    <GoabIconButton icon="notifications" ariaLabel="Alerts" />
  </GoabTooltip>
  <GoabTooltip content="Settings">
    <GoabIconButton icon="settings" ariaLabel="Settings" />
  </GoabTooltip>
</GoabButtonGroup>
<goab-button-group alignment="start">
  <goab-tooltip content="Edit">
    <goab-icon-button icon="pencil" ariaLabel="Edit"></goab-icon-button>
  </goab-tooltip>
  <goab-tooltip content="Alerts">
    <goab-icon-button icon="notifications" ariaLabel="Alerts"></goab-icon-button>
  </goab-tooltip>
  <goab-tooltip content="Settings">
    <goab-icon-button icon="settings" ariaLabel="Settings"></goab-icon-button>
  </goab-tooltip>
</goab-button-group>
<goa-button-group alignment="start">
  <goa-tooltip content="Edit">
    <goa-icon-button icon="pencil" aria-label="Edit"></goa-icon-button>
  </goa-tooltip>
  <goa-tooltip content="Alerts">
    <goa-icon-button icon="notifications" aria-label="Alerts"></goa-icon-button>
  </goa-tooltip>
  <goa-tooltip content="Settings">
    <goa-icon-button icon="settings" aria-label="Settings"></goa-icon-button>
  </goa-tooltip>
</goa-button-group>

Show multiple actions in a compact table

const rows = [
  {
    status: "information",
    statusText: "In progress",
    name: "Darlene Robertson",
    id: 45904,
  },
  { status: "default", statusText: "Inactive", name: "Floyd Miles", id: 47838 },
  { status: "success", statusText: "Active", name: "Kathryn Murphy", id: 34343 },
  { status: "important", statusText: "Recent", name: "Annette Black", id: 89897 },
  { status: "success", statusText: "Active", name: "Esther Howard", id: 12323 },
  { status: "success", statusText: "Active", name: "Jane Cooper", id: 56565 },
];
<GoabTable width="100%">
  <thead>
    <tr>
      <th>Status</th>
      <th>Name</th>
      <th style={{ textAlign: "right" }}>Id Number</th>
      <th style={{ width: "1%", whiteSpace: "nowrap" }}>Edit | Flag | Send</th>
    </tr>
  </thead>
  <tbody>
    {rows.map((row) => (
      <tr key={row.id}>
        <td>
          <GoabBadge
            type={row.status as "information" | "default" | "success" | "important"}
            content={row.statusText}
            icon={false}
          />
        </td>
        <td>{row.name}</td>
        <td className="goa-table-number-column">{row.id}</td>
        <td>
          <GoabBlock>
            <GoabIconButton size="small" icon="pencil" ariaLabel="Edit" />
            <GoabIconButton size="small" icon="flag" ariaLabel="Flag" />
            <GoabIconButton size="small" icon="mail" ariaLabel="Send" />
          </GoabBlock>
        </td>
      </tr>
    ))}
  </tbody>
</GoabTable>
rows: TableRow[] = [
  {
    status: "information",
    statusText: "In progress",
    name: "Darlene Robertson",
    id: 45904,
  },
  { status: "default", statusText: "Inactive", name: "Floyd Miles", id: 47838 },
  { status: "success", statusText: "Active", name: "Kathryn Murphy", id: 34343 },
  { status: "important", statusText: "Recent", name: "Annette Black", id: 89897 },
  { status: "success", statusText: "Active", name: "Esther Howard", id: 12323 },
  { status: "success", statusText: "Active", name: "Jane Cooper", id: 56565 },
];
<goab-table width="100%">
  <thead>
    <tr>
      <th>Status</th>
      <th>Name</th>
      <th style="text-align: right">Id Number</th>
      <th style="width: 1%; white-space: nowrap">Edit | Flag | Send</th>
    </tr>
  </thead>
  <tbody>
    @for (row of rows; track row.id) {
    <tr>
      <td>
        <goab-badge
          [type]="row.status"
          [content]="row.statusText"
          [icon]="false"
        ></goab-badge>
      </td>
      <td>{{ row.name }}</td>
      <td class="goa-table-number-column">{{ row.id }}</td>
      <td>
        <goab-block>
          <goab-icon-button
            size="small"
            icon="pencil"
            ariaLabel="Edit"
          ></goab-icon-button>
          <goab-icon-button size="small" icon="flag" ariaLabel="Flag"></goab-icon-button>
          <goab-icon-button size="small" icon="mail" ariaLabel="Send"></goab-icon-button>
        </goab-block>
      </td>
    </tr>
    }
  </tbody>
</goab-table>
<goa-table version="2" width="100%">
  <table width="100%">
    <thead>
      <tr>
        <th>Status</th>
        <th>Name</th>
        <th style="text-align: right">Id Number</th>
        <th style="width: 1%; white-space: nowrap">Edit | Flag | Send</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>
          <goa-badge
            version="2"
            type="information"
            content="In progress"
            icon="false"
          ></goa-badge>
        </td>
        <td>Darlene Robertson</td>
        <td class="goa-table-number-column">45904</td>
        <td>
          <goa-block>
            <goa-icon-button
              size="small"
              icon="pencil"
              arialabel="Edit"
            ></goa-icon-button>
            <goa-icon-button size="small" icon="flag" arialabel="Flag"></goa-icon-button>
            <goa-icon-button size="small" icon="mail" arialabel="Send"></goa-icon-button>
          </goa-block>
        </td>
      </tr>
      <tr>
        <td>
          <goa-badge
            version="2"
            type="default"
            content="Inactive"
            icon="false"
          ></goa-badge>
        </td>
        <td>Floyd Miles</td>
        <td class="goa-table-number-column">47838</td>
        <td>
          <goa-block>
            <goa-icon-button
              size="small"
              icon="pencil"
              arialabel="Edit"
            ></goa-icon-button>
            <goa-icon-button size="small" icon="flag" arialabel="Flag"></goa-icon-button>
            <goa-icon-button size="small" icon="mail" arialabel="Send"></goa-icon-button>
          </goa-block>
        </td>
      </tr>
      <tr>
        <td>
          <goa-badge version="2" type="success" content="Active" icon="false"></goa-badge>
        </td>
        <td>Kathryn Murphy</td>
        <td class="goa-table-number-column">34343</td>
        <td>
          <goa-block>
            <goa-icon-button
              size="small"
              icon="pencil"
              arialabel="Edit"
            ></goa-icon-button>
            <goa-icon-button size="small" icon="flag" arialabel="Flag"></goa-icon-button>
            <goa-icon-button size="small" icon="mail" arialabel="Send"></goa-icon-button>
          </goa-block>
        </td>
      </tr>
      <tr>
        <td>
          <goa-badge
            version="2"
            type="important"
            content="Recent"
            icon="false"
          ></goa-badge>
        </td>
        <td>Annette Black</td>
        <td class="goa-table-number-column">89897</td>
        <td>
          <goa-block>
            <goa-icon-button
              size="small"
              icon="pencil"
              arialabel="Edit"
            ></goa-icon-button>
            <goa-icon-button size="small" icon="flag" arialabel="Flag"></goa-icon-button>
            <goa-icon-button size="small" icon="mail" arialabel="Send"></goa-icon-button>
          </goa-block>
        </td>
      </tr>
      <tr>
        <td>
          <goa-badge version="2" type="success" content="Active" icon="false"></goa-badge>
        </td>
        <td>Esther Howard</td>
        <td class="goa-table-number-column">12323</td>
        <td>
          <goa-block>
            <goa-icon-button
              size="small"
              icon="pencil"
              arialabel="Edit"
            ></goa-icon-button>
            <goa-icon-button size="small" icon="flag" arialabel="Flag"></goa-icon-button>
            <goa-icon-button size="small" icon="mail" arialabel="Send"></goa-icon-button>
          </goa-block>
        </td>
      </tr>
      <tr>
        <td>
          <goa-badge version="2" type="success" content="Active" icon="false"></goa-badge>
        </td>
        <td>Jane Cooper</td>
        <td class="goa-table-number-column">56565</td>
        <td>
          <goa-block>
            <goa-icon-button
              size="small"
              icon="pencil"
              arialabel="Edit"
            ></goa-icon-button>
            <goa-icon-button size="small" icon="flag" arialabel="Flag"></goa-icon-button>
            <goa-icon-button size="small" icon="mail" arialabel="Send"></goa-icon-button>
          </goa-block>
        </td>
      </tr>
    </tbody>
  </table>
</goa-table>

States

Submit

Only use disabled buttons if research shows it makes the user interface easier to understand.

Consider removing options that are unavailable or not applicable. Show actions that are only relevant and useful to the user at a given time.

Avoid using disabled buttons. They have poor contrast and can confuse users.
Submit

When you must disable a button or input:

  • Provide nearby text explaining what needs to happen first
  • Consider showing the element enabled with validation on submit instead
  • Use aria-describedby to link the disabled element to explanatory text
Don't disable buttons or inputs without explaining why. Disabled controls can be confusing and users may not understand why they can't interact with an element.

Types

Go to homepage
Don't use Button for simple navigation (use Link), toggling state (use Toggle or Checkbox), or minor utility functions (use Icon Button).

Positioning

SubmitCancel
Use a button group when putting multiple buttons together.

Usage

Don't use icon buttons for actions that are not easily understood.
Use icon buttons for universal actions such as closing a modal window.

Feedback

Use tooltips to describe an icon button and provide clarity on what the icon button will do.
Don't use tooltips inconsistently; if one icon button has a tooltip, the rest of the icon buttons must also have tooltips.
All GoA Design System components are built to meet WCAG 2.2 AA standards. The following guidelines provide additional context for accessible implementation.

Screen Readers

Icon-only interactive elements must have an accessible label so screen reader users understand their purpose.

For IconButton: The ariaLabel prop is required.

// Good - describes the action
<GoabIconButton icon="trash" ariaLabel="Delete item" />

// Bad - no label for screen readers
<GoabIconButton icon="trash" />

For Badge with icon only: Provide ariaLabel when there’s no visible text.

<GoabBadge icon="warning" ariaLabel="Warning" type="important" />

For Icon: Use ariaLabel when the icon conveys meaning, not just decoration.

The label should describe:

  • What action happens (for buttons): “Delete”, “Edit”, “Close”
  • What the icon represents (for informational icons): “Warning”, “Success”
Don't use icon-only elements without an accessible label
Icon-only buttons must include a descriptive label for screen readers.

Focus

Don't focus on just the icon within a button. Focus the button as a whole.

Accessibility

Use a tooltip to clearly indicate an icon button's function when there's no visible label.
View old component docs