How the Button works with a keyboard and assistive tech, and where it stands against WCAG 2.2 AA.
The Button renders a native <button>, so the browser supplies its role, focus and keyboard behaviour. What is left to the component is keeping that intact through every variant, and meeting WCAG 2.2 AA for contrast, focus and target size.
Native role and keyboard handling. Inside a form, pass type="submit" deliberately.
aria-label
iconOnly
Set from the label, so the button still has a name when no text shows.
aria-busy="true"
loading
Announced as busy. The button is disabled while loading so it can't be pressed twice.
disabled
disabled or loading
Removed from the tab order and not announced as actionable. If users need to find out why an action is unavailable, keep it enabled and explain on press instead.
aria-hidden
Icons
Icons beside a label are decorative and hidden from assistive tech.
Every variant and state has to meet WCAG 2.2 Level AA. Measure the colours as they land on screen: a translucent hover or press wash over whatever sits behind the button.
RequirementRatioApplies toGuidance
Text label
4.5:1
Rest, Hover, Pressed
Label text against the button's fill in every state. The label is 10–18px bold, below the large-text threshold, so 4.5:1 applies at every size. Measure a translucent hover or press over the surface behind it.WCAG 1.4.3 Contrast (Minimum)
Icon-only glyph and spinner
3:1
Icon only, Loading
An icon that stands in for text, and the spinner's arc, need 3:1 against the fill. An icon beside a visible label does not need its own check.WCAG 1.4.11 Non-text Contrast
Visible boundary
3:1 if needed
Secondary
The stroke only needs 3:1 where it is the only thing that shows there's a control. A button with a readable label can rely on the label.WCAG 1.4.11 Non-text Contrast
Label against fill, for every intent, variant and state, measured from the component's colour tokens. Secondary and Tertiary are measured on white, Inverse on dark on #2a2a2a. 25 of 54 pairs fall below 4.5:1 and are marked in amber.
WCAG 2.5.8 (AA) asks for targets of at least 24 × 24px, or enough space around a smaller one. 44px (2.5.5, AAA) is the comfortable size for touch. Width grows with the label, so height is the measure that matters; icon-only buttons are square.
Every button has a name: visible text, or an aria-label on an icon-only button.
The label says what happens (Save changes, Delete project), not OK or Click here.
Use a link, not a button, when the only effect is going to another page.
Pairs the table marks below 4.5:1 — Success and Warning in most states, Error at rest, and the pressed washes of Secondary and Tertiary — need a darker shade before the code library ships.
A Tertiary XXS button is 22px tall, under the 24px minimum, so it passes only on spacing: keep 24px between the centres of neighbouring targets.