Design guidance

Buttons communicate an action that will occur when the user triggers them. The visual weight โ€” filled, outline, or quiet โ€” signals the action's importance relative to other elements on the page.

Visual hierarchy

Use no more than one primary (filled) button per view. Secondary and quiet buttons de-emphasize less critical actions so the primary action is clear.

Sizes

Spectrum buttons come in five sizes: XS, S, M (default), L, and XL. Match the size to the surrounding content density and target area requirements.

๐Ÿ’ก The Spectrum 2 design system updates the button anatomy: rounded corners are now more pronounced and static-color variants have been consolidated. Check the S2 code docs for migration details.

States

StateDescription
defaultThe button's resting state.
hoverMouse pointer is over the button.
pressedActive click / touch state.
focusKeyboard or programmatic focus.
disabledButton is non-interactive. Use isDisabled prop.
pendingAsync action in progress (S2). Shows a spinner.

React Spectrum implementation

๐Ÿ†• The examples below use React Spectrum S2. For v3, see the migration guide.

Basic button

import {Button} from '@react-spectrum/s2';

function Example() {
  return (
    <Button variant="accent" onPress={handlePress}>
      Save changes
    </Button>
  );
}

ActionButton with icon

import {ActionButton} from '@react-spectrum/s2';
import EditIcon from '@react-spectrum/s2/icons/Edit';

<ActionButton>
  <EditIcon />
  <Text>Edit</Text>
</ActionButton>

ToggleButton

import {ToggleButton} from '@react-spectrum/s2/ToggleButton';
import {useState} from 'react';
import Star from '@react-spectrum/s2/icons/Star';

function StarToggle() {
  const [selected, setSelected] = useState(false);
  return (
    <ToggleButton
      aria-label="Star"
      isSelected={selected}
      onChange={setSelected}>
      <Star />
    </ToggleButton>
  );
}

Key props โ€” Button (S2)

PropTypeDefaultDescription
variant'accent' | 'primary' | 'secondary' | 'negative''primary'Visual style / importance.
style'fill' | 'outline''fill'Filled vs outlined.
size'XS'|'S'|'M'|'L'|'XL''M'Size of the button.
isPendingbooleanfalseShows spinner while async op runs (S2).
isDisabledbooleanfalseDisables interaction.
onPress(e: PressEvent) => voidโ€”Called on pointer/keyboard activation.

Accessibility

Spectrum buttons are built on React Aria, providing keyboard, pointer, and screen-reader support out of the box.

  • Always provide a meaningful label โ€” either visible text or aria-label for icon-only buttons.
  • Use isDisabled instead of HTML disabled to preserve tab order and aria state.
  • For async actions, isPending communicates the loading state to screen readers automatically.