Icon button

A compact button with an icon and no text.

Props

icon
GoAIconType
Sets the icon.
size
IconSize
Sets the size of button.
Defaults to medium.
theme
IconTheme
Sets the icon theme. 'outline' for stroked icons, 'filled' for solid icons.
Defaults to outline.
variant
color | nocolor | light | dark | destructive
Styles the button to show color, light, dark or destructive action.
Defaults to color.
title
string
Sets the title of the button.
testId
string
Sets a data-testid attribute for automated testing.
disabled
boolean
Disables the button.
Defaults to false.
inverted
boolean
When true, inverts the icon colors for use on dark backgrounds.
Defaults to false.
ariaLabel
string
Sets the aria-label of the button.
mt, mr, mb, ml
none | 3xs | 2xs | xs | s | m | l | xl | 2xl | 3xl | 4xl
Apply margin to the top, right, bottom, and/or left of the component.

Events

onClick
(event: Event) => void
_click
CustomEvent
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>
.token-block {
  background-color: var(--goa-color-interactive-default);
  height: 22px;
  width: 24px;
  border-radius: var(--goa-border-radius-s);
}
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: "dark", 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 },
  ];
<GoabxTable 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>
              <GoabxBadge
                type={row.status as "information" | "dark" | "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>
    </GoabxTable>
rows: TableRow[] = [
    { status: "information", statusText: "In progress", name: "Darlene Robertson", id: 45904 },
    { status: "dark", 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 },
  ];
<goabx-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>
        <goabx-badge [type]="row.status" [content]="row.statusText" [icon]="false"></goabx-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>
</goabx-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="dark" 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.
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.