Skip to main content

Button

stable

Buttons enable a user to initiate a specific action.

Overview

Button is the primary control for initiating an action. It signals what will happen on click and carries the weight of the decision the user is making — primary buttons commit, secondary buttons offer escape, danger buttons commit destructively. The component's emphasis hierarchy is load-bearing: how prominent a button looks should match how consequential its action is.

Usage

When to use

  • Committing a change a user has explicitly chosen — "Save", "Continue", "Delete"
  • Triggering a flow or transaction whose effect happens outside the current view
  • Acting as the single, unambiguous call to action in a card, dialog, or form

One primary per view. Neutral for everything else. Secondary only beside a primary. Tertiary where a border would be noise.

When not to use

  • Navigating between pages or sections — use a Link instead, even if the link is styled as a button
  • Toggling a binary state — use a Switch or Checkbox for on/off, not a button
  • Selecting from a set of mutually exclusive options — use Radio or Segmented control

Keep the label concise and action-driven. A left icon reinforces the action, and a right icon shows what happens next. Use an icon alone only in a compact layout, and give it a tooltip and an accessible name.

Alternatives

Link

Use when the action is navigation (<a href>), not a page-local action.

IconButton

Use for icon-only actions in compact layouts. IconButton enforces the accessible-name requirement automatically.

Switch

Use when the control toggles a setting on or off.

Anatomy

The button is made up of five elements.

  1. Container

    The interactive surface that holds the button content.

  2. Leading icon

    Optional glyph before the label.

  3. Label

    The text that describes the action.

  4. Trailing icon

    Optional glyph after the label.

  5. Progress

    Replaces the label and icon while the button is in a pending state.

Variants

Button has five appearances mapped to a single dimension — emphasis. Choose by how prominent the action should be in its context, not by color preference. The code default is secondary for compatibility; set appearance deliberately.

Neutral

The everyday button. Use it for most actions in a view: toolbar actions, secondary tasks, anything that isn't the one thing we want the user to do. Gray outline, dark label, so it sits quietly next to content.

Primary

The one action we want the user to take. One per view. If two actions feel primary, one of them isn't.

Secondary

The paired action beside a primary, usually Cancel or Back. Brand outline so it reads as part of the same decision as the primary. Don't use it on its own; a lone secondary wants to be neutral.

Tertiary

Lowest emphasis, no outline. Use it for inline or repeated actions where even a neutral border would add noise: table rows, list items, dense toolbars.

Danger

Destructive actions only. Delete, Remove, Discard. Never for emphasis.

Sizes

Buttons come in four sizes: x-small, small, medium, and large. Match a size to an input of the same size in a form.

  • X-small — nested inside a smaller component. There is no matching input, so don't use x-small in a form
  • Small — limited vertical space or pairing with similarly-sized content
  • Medium (default) — most button instances
  • Large — limited cases where the button needs extra prominence; typically one per view
View in Storybook

Block

A block button expands to its container's width. Use when stacking calls to action in a card or dialog.

States

Every appearance implements all six states.

Enabled

Default resting state.

Hover

Hover to see it

Focus

Tab to it

Active

Press and hold.

Disabled

Interaction prevented.

Pending

Label and icon are replaced by a progress indicator. Use while a process such as saving is in progress.

Configuration

Theming

Tune via style hook

HookDescriptionDefault
1 Container background (24)
HookDescriptionDefault
--jh-button-color-background-primary-enabledThe button container background-color when enabled and appearance="primary".--jh-color-content-brand-enabled
--jh-button-color-background-primary-focusThe button container background-color when in focus and appearance="primary".--jh-color-content-brand-hover
--jh-button-color-background-primary-hoverThe button container background-color when hovered and appearance="primary".--jh-color-content-brand-hover
--jh-button-color-background-primary-activeThe button container background-color when active and appearance="primary".--jh-color-content-brand-active
--jh-button-color-background-primary-disabledThe button container background-color when disabled and appearance="primary".--jh-color-content-brand-enabled
--jh-button-color-background-primary-pendingThe button container background-color when pending and appearance="primary".--jh-color-content-brand-enabled
--jh-button-color-background-secondary-enabledThe button container background-color when enabled and appearance="secondary".transparent
--jh-button-color-background-secondary-focusThe button container background-color when in focus and appearance="secondary".--jh-color-content-brand-hover
--jh-button-color-background-secondary-hoverThe button container background-color when hovered and appearance="secondary".--jh-color-content-brand-hover
--jh-button-color-background-secondary-activeThe button container background-color when active and appearance="secondary".--jh-color-content-brand-active
--jh-button-color-background-secondary-disabledThe button container background-color when disabled and appearance="secondary".transparent
--jh-button-color-background-secondary-pendingThe button container background-color when pending and appearance="secondary".transparent
--jh-button-color-background-tertiary-enabledThe button container background-color when enabled and appearance="tertiary".transparent
--jh-button-color-background-tertiary-focusThe button container background-color when in focus and appearance="tertiary".--jh-color-content-brand-hover
--jh-button-color-background-tertiary-hoverThe button container background-color when hovered and appearance="tertiary".--jh-color-content-brand-hover
--jh-button-color-background-tertiary-activeThe button container background-color when active and appearance="tertiary".--jh-color-content-brand-active
--jh-button-color-background-tertiary-disabledThe button container background-color when disabled and appearance="tertiary".transparent
--jh-button-color-background-tertiary-pendingThe button container background-color when pending and appearance="tertiary".transparent
--jh-button-color-background-danger-enabledThe button container background-color when enabled and appearance="danger".--jh-color-content-negative-enabled
--jh-button-color-background-danger-focusThe button container background-color when in focus and appearance="danger".--jh-color-content-negative-hover
--jh-button-color-background-danger-hoverThe button container background-color when hovered and appearance="danger".--jh-color-content-negative-hover
--jh-button-color-background-danger-activeThe button container background-color when active and appearance="danger".--jh-color-content-negative-active
--jh-button-color-background-danger-disabledThe button container background-color when disabled and appearance="danger".--jh-color-content-negative-enabled
--jh-button-color-background-danger-pendingThe button container background-color when pending and appearance="danger".--jh-color-content-negative-enabled
1 Container border (24)
HookDescriptionDefault
--jh-button-color-border-primary-enabledThe button container border-color when enabled and appearance="primary".transparent
--jh-button-color-border-primary-focusThe button container border-color when in focus and appearance="primary".transparent
--jh-button-color-border-primary-hoverThe button container border-color when hovered and appearance="primary".transparent
--jh-button-color-border-primary-activeThe button container border-color when active and appearance="primary".transparent
--jh-button-color-border-primary-disabledThe button container border-color when disabled and appearance="primary".transparent
--jh-button-color-border-primary-pendingThe button container border-color when pending and appearance="primary".transparent
--jh-button-color-border-secondary-enabledThe button container border-color when enabled and appearance="secondary".--jh-border-action-color
--jh-button-color-border-secondary-focusThe button container border-color when in focus and appearance="secondary".--jh-color-content-brand-hover
--jh-button-color-border-secondary-hoverThe button container border-color when hovered and appearance="secondary".--jh-color-content-brand-hover
--jh-button-color-border-secondary-activeThe button container border-color when active and appearance="secondary".--jh-color-content-brand-active
--jh-button-color-border-secondary-disabledThe button container border-color when disabled and appearance="secondary".--jh-border-action-color
--jh-button-color-border-secondary-pendingThe button container border-color when pending and appearance="secondary".--jh-border-action-color
--jh-button-color-border-tertiary-enabledThe button container border-color when enabled and appearance="tertiary".transparent
--jh-button-color-border-tertiary-focusThe button container border-color when in focus and appearance="tertiary".transparent
--jh-button-color-border-tertiary-hoverThe button container border-color when hovered and appearance="tertiary".transparent
--jh-button-color-border-tertiary-activeThe button container border-color when active and appearance="tertiary".transparent
--jh-button-color-border-tertiary-disabledThe button container border-color when disabled and appearance="tertiary".transparent
--jh-button-color-border-tertiary-pendingThe button container border-color when pending and appearance="tertiary".transparent
--jh-button-color-border-danger-enabledThe button container border-color when enabled and appearance="danger".transparent
--jh-button-color-border-danger-focusThe button container border-color when in focus and appearance="danger".transparent
--jh-button-color-border-danger-hoverThe button container border-color when hovered and appearance="danger".transparent
--jh-button-color-border-danger-activeThe button container border-color when active and appearance="danger".transparent
--jh-button-color-border-danger-disabledThe button container border-color when disabled and appearance="danger".transparent
--jh-button-color-border-danger-pendingThe button container border-color when pending and appearance="danger".transparent
1 Container radius (1)
HookDescriptionDefault
--jh-button-border-radiusThe button container border-radius.--jh-border-radius-100
1 Focus ring (1)
HookDescriptionDefault
--jh-button-color-focusThe button container outline when it receives keyboard focus.--jh-border-focus-color
1 Disabled opacity (1)
HookDescriptionDefault
--jh-button-opacity-disabledThe button container opacity when disabled.--jh-opacity-disabled
3 Label text color (20)
HookDescriptionDefault
--jh-button-label-color-text-primary-enabledThe label text color when enabled and appearance="primary".--jh-color-content-on-brand-enabled
--jh-button-label-color-text-primary-focusThe label text color when in focus and appearance="primary".--jh-color-content-on-brand-hover
--jh-button-label-color-text-primary-hoverThe label text color when hovered and appearance="primary".--jh-color-content-on-brand-hover
--jh-button-label-color-text-primary-activeThe label text color when active and appearance="primary".--jh-color-content-on-brand-active
--jh-button-label-color-text-primary-disabledThe label text color when disabled and appearance="primary".--jh-color-content-on-brand-enabled
--jh-button-label-color-text-secondary-enabledThe label text color when enabled and appearance="secondary".--jh-color-content-brand-enabled
--jh-button-label-color-text-secondary-focusThe label text color when in focus and appearance="secondary".--jh-color-content-on-brand-hover
--jh-button-label-color-text-secondary-hoverThe label text color when hovered and appearance="secondary".--jh-color-content-on-brand-hover
--jh-button-label-color-text-secondary-activeThe label text color when active and appearance="secondary".--jh-color-content-on-brand-active
--jh-button-label-color-text-secondary-disabledThe label text color when disabled and appearance="secondary".--jh-color-content-brand-enabled
--jh-button-label-color-text-tertiary-enabledThe label text color when enabled and appearance="tertiary".--jh-color-content-brand-enabled
--jh-button-label-color-text-tertiary-focusThe label text color when in focus and appearance="tertiary".--jh-color-content-on-brand-hover
--jh-button-label-color-text-tertiary-hoverThe label text color when hovered and appearance="tertiary".--jh-color-content-on-brand-hover
--jh-button-label-color-text-tertiary-activeThe label text color when active and appearance="tertiary".--jh-color-content-on-brand-active
--jh-button-label-color-text-tertiary-disabledThe label text color when disabled and appearance="tertiary".--jh-color-content-brand-enabled
--jh-button-label-color-text-danger-enabledThe label text color when enabled and appearance="danger".--jh-color-content-on-negative-enabled
--jh-button-label-color-text-danger-focusThe label text color when in focus and appearance="danger".--jh-color-content-on-negative-hover
--jh-button-label-color-text-danger-hoverThe label text color when hovered and appearance="danger".--jh-color-content-on-negative-hover
--jh-button-label-color-text-danger-activeThe label text color when active and appearance="danger".--jh-color-content-on-negative-active
--jh-button-label-color-text-danger-disabledThe label text color when disabled and appearance="danger".--jh-color-content-on-negative-enabled
2, 4 Icon fill (20)
HookDescriptionDefault
--jh-button-icon-color-fill-primary-enabledThe icon color when enabled and appearance="primary".--jh-color-content-on-brand-enabled
--jh-button-icon-color-fill-primary-focusThe icon color when in focus and appearance="primary".--jh-color-content-on-brand-hover
--jh-button-icon-color-fill-primary-hoverThe icon color when hovered and appearance="primary".--jh-color-content-on-brand-hover
--jh-button-icon-color-fill-primary-activeThe icon color when active and appearance="primary".--jh-color-content-on-brand-active
--jh-button-icon-color-fill-primary-disabledThe icon color when disabled and appearance="primary".--jh-color-content-on-brand-enabled
--jh-button-icon-color-fill-secondary-enabledThe icon color when enabled and appearance="secondary".--jh-color-content-brand-enabled
--jh-button-icon-color-fill-secondary-focusThe icon color when in focus and appearance="secondary".--jh-color-content-on-brand-hover
--jh-button-icon-color-fill-secondary-hoverThe icon color when hovered and appearance="secondary".--jh-color-content-on-brand-hover
--jh-button-icon-color-fill-secondary-activeThe icon color when active and appearance="secondary".--jh-color-content-on-brand-active
--jh-button-icon-color-fill-secondary-disabledThe icon color when disabled and appearance="secondary".--jh-color-content-brand-enabled
--jh-button-icon-color-fill-tertiary-enabledThe icon color when enabled and appearance="tertiary".--jh-color-content-brand-enabled
--jh-button-icon-color-fill-tertiary-focusThe icon color when in focus and appearance="tertiary".--jh-color-content-on-brand-hover
--jh-button-icon-color-fill-tertiary-hoverThe icon color when hovered and appearance="tertiary".--jh-color-content-on-brand-hover
--jh-button-icon-color-fill-tertiary-activeThe icon color when active and appearance="tertiary".--jh-color-content-on-brand-active
--jh-button-icon-color-fill-tertiary-disabledThe icon color when disabled and appearance="tertiary".--jh-color-content-brand-enabled
--jh-button-icon-color-fill-danger-enabledThe icon color when enabled and appearance="danger".--jh-color-content-on-negative-enabled
--jh-button-icon-color-fill-danger-focusThe icon color when in focus and appearance="danger".--jh-color-content-on-negative-hover
--jh-button-icon-color-fill-danger-hoverThe icon color when hovered and appearance="danger".--jh-color-content-on-negative-hover
--jh-button-icon-color-fill-danger-activeThe icon color when active and appearance="danger".--jh-color-content-on-negative-active
--jh-button-icon-color-fill-danger-disabledThe icon color when disabled and appearance="danger".--jh-color-content-on-negative-enabled
5 Progress track (4)
HookDescriptionDefault
--jh-button-progress-track-color-border-primary-pendingThe progress indicator track-color when appearance="primary".--jh-color-control-enabled
--jh-button-progress-track-color-border-secondary-pendingThe progress indicator track-color when appearance="secondary".--jh-color-control-enabled
--jh-button-progress-track-color-border-tertiary-pendingThe progress indicator track-color when appearance="tertiary".--jh-color-control-enabled
--jh-button-progress-track-color-border-danger-pendingThe progress indicator track-color when appearance="danger".--jh-color-control-enabled
5 Progress indicator (4)
HookDescriptionDefault
--jh-button-progress-color-border-primary-pendingThe progress indicator border-color when appearance="primary".--jh-color-content-on-brand-enabled
--jh-button-progress-color-border-secondary-pendingThe progress indicator border-color when appearance="secondary".--jh-color-content-brand-enabled
--jh-button-progress-color-border-tertiary-pendingThe progress indicator border-color when appearance="tertiary".--jh-color-content-brand-enabled
--jh-button-progress-color-border-danger-pendingThe progress indicator border-color when appearance="danger".--jh-color-content-on-negative-enabled
1 Size token (1)
HookDescriptionDefault
--jh-button-sizeThe button width of single icon buttons, and the button height. Button width and height defaults to --jh-dimension-600 when size="x-small",--jh-dimension-800 when size="small", --jh-dimension-1000 when size="medium", and --jh-dimension-1200 when size="large".--jh-dimension-600, --jh-dimension-800, --jh-dimension-1000, --jh-dimension-1200

Change via mechanism

Examples

Toolbar actions

Standalone actions use neutral.

Primary action with cancel pairing

The cancel is a secondary because it's paired with a primary.

Destructive action

Make the destructive nature explicit in the label — don't rely on color alone.

Button with leading icon

Use an icon to reinforce the action. Place icons before the label by default.

Block button in a dialog

Stack block buttons when they're the only call to action in a constrained container.

Accessibility

WCAG conformance

Button targets WCAG 2.2 AA. The default tokens satisfy 1.4.3 (Contrast Minimum) and 1.4.11 (Non-text Contrast) on Forge's default surface; custom token overrides are the consumer's responsibility to validate. Minimum touch target is 44×44 CSS pixels (2.5.5).

Keyboard

Buttons are reachable via Tab, activated via Enter or Space. They should not be removed from the tab order unless disabled.

Screen reader

The label is the accessible name. For icon-only buttons, provide an aria-label (Web) — the icon alone is not a sufficient accessible name.