Overview
An <sp-action-button>
represents an action a user can take.
Usage

yarn add @spectrum-web-components/action-button
Import the side effectful registration of <sp-action-button>
via:
import '@spectrum-web-components/action-button/sp-action-button.js';
When looking to leverage the ActionButton
base class as a type and/or for extension purposes, do so via:
import { ActionButton } from '@spectrum-web-components/action-button';
Anatomy
<sp-action-button>Try me</sp-action-button>
Content
<sp-action-button>
elements can be provided a visible label,
a label and an icon, or just an icon.
An icon is provided by placing an icon element in the icon
slot.
If the button is icon-only
, a non-visible label
can be provided via the label
attribute on an <sp-action-button>
or on an <sp-icon*>
element child to appropriately
fulfill the accessibility contract of the button.
Label only
<sp-action-button variant="primary">Label only</sp-action-button>
Icon + label
<sp-action-button variant="primary">
<sp-icon-help slot="icon"></sp-icon-help>
Icon + Label
</sp-action-button>
SVG Icon + label
<sp-action-button variant="primary">
<svg
slot="icon"
viewBox="0 0 36 36"
focusable="false"
aria-hidden="true"
role="img"
>
<path
d="M16 36a4.407 4.407 0 0 0 4-4h-8a4.407 4.407 0 0 0 4 4zm9.143-24.615c0-3.437-3.206-4.891-7.143-5.268V3a1.079 1.079 0 0 0-1.143-1h-1.714A1.079 1.079 0 0 0 14 3v3.117c-3.937.377-7.143 1.831-7.143 5.268C6.857 26.8 2 26.111 2 28.154V30h28v-1.846C30 26 25.143 26.8 25.143 11.385z"
></path>
</svg>
SVG Icon + Label
</sp-action-button>
Icon only
<sp-action-button variant="primary" label="Icon only">
<sp-icon-help slot="icon"></sp-icon-help>
</sp-action-button>
Options
Sizes
Extra Small
<sp-action-group size="xs">
<sp-action-button>Edit</sp-action-button>
<sp-action-button>
<sp-icon-edit slot="icon"></sp-icon-edit>
Edit
</sp-action-button>
<sp-action-button label="Edit">
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
<sp-action-button label="Edit" hold-affordance>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
</sp-action-group>
Small
<sp-action-group size="s">
<sp-action-button>Edit</sp-action-button>
<sp-action-button>
<sp-icon-edit slot="icon"></sp-icon-edit>
Edit
</sp-action-button>
<sp-action-button label="Edit">
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
<sp-action-button label="Edit" hold-affordance>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
</sp-action-group>
Medium
<sp-action-group size="m">
<sp-action-button>Edit</sp-action-button>
<sp-action-button>
<sp-icon-edit slot="icon"></sp-icon-edit>
Edit
</sp-action-button>
<sp-action-button label="Edit">
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
<sp-action-button label="Edit" hold-affordance>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
</sp-action-group>
Large
<sp-action-group size="l">
<sp-action-button>Edit</sp-action-button>
<sp-action-button>
<sp-icon-edit slot="icon"></sp-icon-edit>
Edit
</sp-action-button>
<sp-action-button label="Edit">
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
<sp-action-button label="Edit" hold-affordance>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
</sp-action-group>
Extra Large
<sp-action-group size="xl">
<sp-action-button>Edit</sp-action-button>
<sp-action-button>
<sp-icon-edit slot="icon"></sp-icon-edit>
Edit
</sp-action-button>
<sp-action-button label="Edit">
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
<sp-action-button label="Edit" hold-affordance>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
</sp-action-group>
Variants
The <sp-action-button>
can be customized with either or both of the emphasized
and quiet
attributes. These will pair with either or both of the state attributes (selected
and disabled
) to decide the final visual delivery of the <sp-action-button>
. Content addressed to the icon
slot can also be provided and will be positioned just before the rest of the the supplied button content.
Default
<div
style="display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 2em;"
>
<div>
<sp-field-label for="standard">Default</sp-field-label>
<sp-action-group id="standard">
<sp-action-button>Edit</sp-action-button>
<sp-action-button>
<sp-icon-edit slot="icon"></sp-icon-edit>
Edit
</sp-action-button>
<sp-action-button label="Edit">
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
<sp-action-button label="Edit" hold-affordance>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
</sp-action-group>
</div>
<div>
<sp-field-label for="standard-selected">Selected</sp-field-label>
<sp-action-group id="standard-selected">
<sp-action-button selected>Edit</sp-action-button>
<sp-action-button selected>
<sp-icon-edit slot="icon"></sp-icon-edit>
Edit
</sp-action-button>
<sp-action-button label="Edit" selected>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
<sp-action-button label="Edit" selected hold-affordance>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
</sp-action-group>
</div>
<div>
<sp-field-label for="standard-disabled">Disabled</sp-field-label>
<sp-action-group id="standard-disabled">
<sp-action-button disabled>Edit</sp-action-button>
<sp-action-button disabled>
<sp-icon-edit slot="icon"></sp-icon-edit>
Edit
</sp-action-button>
<sp-action-button label="Edit" disabled>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
<sp-action-button label="Edit" disabled hold-affordance>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
</sp-action-group>
</div>
<div>
<sp-field-label for="standard-disabled-selected">
Disabled + Selected
</sp-field-label>
<sp-action-group id="standard-disabled-selected">
<sp-action-button disabled selected>Edit</sp-action-button>
<sp-action-button disabled selected>
<sp-icon-edit slot="icon"></sp-icon-edit>
Edit
</sp-action-button>
<sp-action-button label="Edit" disabled selected>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
<sp-action-button label="Edit" disabled selected hold-affordance>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
</sp-action-group>
</div>
</div>
Quiet
<div
style="display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 2em;"
>
<div>
<sp-field-label for="standard">Default</sp-field-label>
<sp-action-group quiet id="standard">
<sp-action-button quiet>Edit</sp-action-button>
<sp-action-button quiet>
<sp-icon-edit slot="icon"></sp-icon-edit>
Edit
</sp-action-button>
<sp-action-button label="Edit" quiet>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
<sp-action-button label="Edit" quiet hold-affordance>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
</sp-action-group>
</div>
<div>
<sp-field-label for="standard-selected">Selected</sp-field-label>
<sp-action-group quiet id="standard-selected">
<sp-action-button quiet selected>Edit</sp-action-button>
<sp-action-button quiet selected>
<sp-icon-edit slot="icon"></sp-icon-edit>
Edit
</sp-action-button>
<sp-action-button label="Edit" quiet selected>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
<sp-action-button label="Edit" quiet selected hold-affordance>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
</sp-action-group>
</div>
<div>
<sp-field-label for="standard-disabled">Disabled</sp-field-label>
<sp-action-group quiet id="standard-disabled">
<sp-action-button quiet disabled>Edit</sp-action-button>
<sp-action-button quiet disabled>
<sp-icon-edit slot="icon"></sp-icon-edit>
Edit
</sp-action-button>
<sp-action-button label="Edit" quiet disabled>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
<sp-action-button label="Edit" quiet disabled hold-affordance>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
</sp-action-group>
</div>
<div>
<sp-field-label for="standard-disabled-selected">
Disabled + Selected
</sp-field-label>
<sp-action-group quiet id="standard-disabled-selected">
<sp-action-button quiet disabled selected>Edit</sp-action-button>
<sp-action-button quiet disabled selected>
<sp-icon-edit slot="icon"></sp-icon-edit>
Edit
</sp-action-button>
<sp-action-button label="Edit" quiet disabled selected>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
<sp-action-button
label="Edit"
quiet
disabled
selected
hold-affordance
>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
</sp-action-group>
</div>
</div>
Emphasized
<div
style="display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 2em;"
>
<div>
<sp-field-label for="standard">Default</sp-field-label>
<sp-action-group emphasized id="standard">
<sp-action-button emphasized>Edit</sp-action-button>
<sp-action-button emphasized>
<sp-icon-edit slot="icon"></sp-icon-edit>
Edit
</sp-action-button>
<sp-action-button label="Edit" emphasized>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
<sp-action-button label="Edit" emphasized hold-affordance>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
</sp-action-group>
</div>
<div>
<sp-field-label for="standard-selected">Selected</sp-field-label>
<sp-action-group emphasized id="standard-selected">
<sp-action-button emphasized selected>Edit</sp-action-button>
<sp-action-button emphasized selected>
<sp-icon-edit slot="icon"></sp-icon-edit>
Edit
</sp-action-button>
<sp-action-button label="Edit" emphasized selected>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
<sp-action-button label="Edit" emphasized selected hold-affordance>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
</sp-action-group>
</div>
<div>
<sp-field-label for="standard-disabled">Disabled</sp-field-label>
<sp-action-group emphasized id="standard-disabled">
<sp-action-button emphasized disabled>Edit</sp-action-button>
<sp-action-button emphasized disabled>
<sp-icon-edit slot="icon"></sp-icon-edit>
Edit
</sp-action-button>
<sp-action-button label="Edit" emphasized disabled>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
<sp-action-button label="Edit" emphasized disabled hold-affordance>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
</sp-action-group>
</div>
<div>
<sp-field-label for="standard-disabled-selected">
Disabled + Selected
</sp-field-label>
<sp-action-group emphasized id="standard-disabled-selected">
<sp-action-button emphasized disabled selected>
Edit
</sp-action-button>
<sp-action-button emphasized disabled selected>
<sp-icon-edit slot="icon"></sp-icon-edit>
Edit
</sp-action-button>
<sp-action-button label="Edit" emphasized disabled selected>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
<sp-action-button
label="Edit"
emphasized
disabled
selected
hold-affordance
>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
</sp-action-group>
</div>
</div>
Emphasized + quiet
<div
style="display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 2em;"
>
<div>
<sp-field-label for="standard">Default</sp-field-label>
<sp-action-group emphasized quiet id="standard">
<sp-action-button emphasized quiet>Edit</sp-action-button>
<sp-action-button emphasized quiet>
<sp-icon-edit slot="icon"></sp-icon-edit>
Edit
</sp-action-button>
<sp-action-button label="Edit" emphasized quiet>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
<sp-action-button label="Edit" emphasized quiet hold-affordance>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
</sp-action-group>
</div>
<div>
<sp-field-label for="standard-selected">Selected</sp-field-label>
<sp-action-group emphasized quiet id="standard-selected">
<sp-action-button emphasized quiet selected>Edit</sp-action-button>
<sp-action-button emphasized quiet selected>
<sp-icon-edit slot="icon"></sp-icon-edit>
Edit
</sp-action-button>
<sp-action-button label="Edit" emphasized quiet selected>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
<sp-action-button
label="Edit"
emphasized
quiet
selected
hold-affordance
>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
</sp-action-group>
</div>
<div>
<sp-field-label for="standard-disabled">Disabled</sp-field-label>
<sp-action-group emphasized quiet id="standard-disabled">
<sp-action-button emphasized quiet disabled>Edit</sp-action-button>
<sp-action-button emphasized quiet disabled>
<sp-icon-edit slot="icon"></sp-icon-edit>
Edit
</sp-action-button>
<sp-action-button label="Edit" emphasized quiet disabled>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
<sp-action-button
label="Edit"
emphasized
quiet
disabled
hold-affordance
>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
</sp-action-group>
</div>
<div>
<sp-field-label for="standard-disabled-selected">
Disabled + Selected
</sp-field-label>
<sp-action-group emphasized quiet id="standard-disabled-selected">
<sp-action-button emphasized quiet disabled selected>
Edit
</sp-action-button>
<sp-action-button emphasized quiet disabled selected>
<sp-icon-edit slot="icon"></sp-icon-edit>
Edit
</sp-action-button>
<sp-action-button label="Edit" emphasized quiet disabled selected>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
<sp-action-button
label="Edit"
emphasized
quiet
disabled
selected
hold-affordance
>
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
</sp-action-group>
</div>
</div>
Behaviors
Action button with hold affordance
The use of the hold-affordance
attribute signifies that the <sp-action-button>
in question will be delivered with a visual affordance outlining that special interaction with the button will dispatch a longpress
event. Via a pointer input, this even will be dispatched when 300ms has passed after a pointerdown
event without the presence of a pointerup
or pointercancel
event. Via the keyboard, an event with a code of Space
or or ArrowDown
while altKey === true
will dispatch the event.
<div
style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 2em;"
>
<overlay-trigger placement="bottom-start">
<sp-action-button label="Edit" hold-affordance slot="trigger">
<sp-icon-edit slot="icon"></sp-icon-edit>
</sp-action-button>
<sp-popover slot="longpress-content" dialog tip>
<p style="color: var(--spectrum-neutral-content-color-default);">
This content is triggered by the "longpress" interaction.
</p>
</sp-popover>
</overlay-trigger>
<overlay-trigger placement="top">
<sp-action-button hold-affordance quiet slot="trigger">
Show Longpress Content
</sp-action-button>
<sp-popover slot="longpress-content" dialog tip>
<p style="color: var(--spectrum-neutral-content-color-default);">
This content is triggered by the "longpress" interaction.
</p>
</sp-popover>
</overlay-trigger>
<overlay-trigger placement="top-end">
<sp-action-button hold-affordance selected slot="trigger">
<sp-icon-edit slot="icon"></sp-icon-edit>
Extended Content with Longpress
</sp-action-button>
<sp-popover slot="longpress-content" dialog tip>
<p style="color: var(--spectrum-neutral-content-color-default);">
This content is triggered by the "longpress" interaction.
</p>
</sp-popover>
</overlay-trigger>
</div>
Toggles
With the application of the toggles
attribute, the button will self manage its selected
property on click
. When this value is updated, a cancellable change
event will be dispatched to inform the parent application.
Default
<sp-action-button toggles id="toggles-default">Toggle button</sp-action-button>
<sp-action-button toggles selected id="toggles-default">
Toggle button
</sp-action-button>
Quiet
<sp-action-button toggles quiet id="toggles-quiet">
Toggle button
</sp-action-button>
<sp-action-button toggles quiet selected id="toggles-quiet">
Toggle button
</sp-action-button>
Emphasized
<sp-action-button toggles emphasized id="toggles-emphasized">
Toggle button
</sp-action-button>
<sp-action-button toggles emphasized selected id="toggles-emphasized">
Toggle button
</sp-action-button>
Emphasized + Quiet
<sp-action-button toggles emphasized quiet id="toggles-emphasized-quiet">
Toggle button
</sp-action-button>
<sp-action-button
toggles
emphasized
quiet
selected
id="toggles-emphasized-quiet"
>
Toggle button
</sp-action-button>
Handling events
Events handlers for clicks and other user actions can be registered on a
<sp-action-button>
as on a standard HTML <button>
element.
<sp-button onclick="spAlert(this, '<sp-action-button> clicked!')">
Click me
</sp-button>
In addition to handling events like a native <button>
HTML element, one can also use a <sp-action-button>
in place of the <a>
HTML element by using the href
and optional target
attribute.
<sp-action-button
href="https://github.com/adobe/spectrum-web-components"
target="_blank"
>
Click me
</sp-action-button>
Accessibility
Include a label
A button is required to have either a visible text label or a label
attribute on either the <sp-button>
itself,
or on an <sp-icon*>
element child.
Don't override color
Do not use custom colors for buttons. The colors of different button variations have been designed to be consistent and accessible.
Use static black or static white to contrast with backgrounds and images
To ensure maximum contrast with the background, use static black for light backgrounds and images, and static white for dark backgrounds and images. Avoid placing static components on top of busy images with a lot of variance in contrast.
Static black on light background
<div style="background-color: #ccffee; padding: 20px">
<sp-action-button static="black">Click me</sp-action-button>
<sp-action-button static="black" selected>Click me</sp-action-button>
</div>
Static white on dark background
<div style="background-color: #220033; padding: 20px">
<sp-action-button static="white">Click me</sp-action-button>
<sp-action-button static="white" selected>Click me</sp-action-button>
</div>
Clearly state the action
Make sure that an action button’s label clearly states the outcome of the action. Use the same word or phrase as found elsewhere in the experience.
1.7.0 (2025-06-11)
Minor Changes
sp-overlay: Fixed : Overlays (like pickers and action menus) were incorrectly closing when scrolling occurred within components. The fix ensures the handleScroll
method in OverlayStack
only responds to document/body scrolling events and ignores component-level scrolling events, which was the original intention.
sp-card: Fixed: On mobile Chrome (both Android and iOS), scrolling on sp-card
components would inadvertently trigger click events. This was caused by the timing-based click detection (200ms threshold) in the pointer event handling, which could misinterpret quick scrolls as clicks. This issue did not affect Safari on mobile devices.
sp-action-button: - Fixed : Action buttons with href attributes now properly detects modifier keys and skips the proxy click, allowing only native browser behavior to proceed.
Patch Changes
sp-styles: Remove unnecessary system theme references to reduce complexity for components that don't need the additional mapping layer.
sp-card: - Fixed: sp-card
component relies on sp-popover
for certain toggle interactive behaviors, but this dependency was missing from its dependency tree.
sp-menu: Fixes: Icons in menu stories weren't properly responding to theme changes when used in functional story components.
Switching to class-based LitElement components ensures proper component lifecycle hooks and shadow DOM context for icon initialization and theme integration.
sp-tabs: Added @spectrum-web-components/action-button
as a dependency for Tabs as its used in the direction button.
sp-split-view: Added @spectrum-web-components/shared dependency in splitview since it uses ranDomId from the shared package
sp-textfield: Replace deprecated word-break: break-word
with overflow-wrap: break-word
to align with modern CSS standards and improve cross-browser compatibility. This property was deprecated in Chrome 44 (July 2015) in favor of the standardized overflow-wrap
property.