Skip to main content

Button

Atombeta@macaw-ds/ui · since 0.1.0

Triggers an action. Not navigation; for links use asChild with an anchor.

Contract

From the manifest's a11y block: what assistive technology sees, and every key the component handles.

Role
button (or the child's role with asChild)
Focusable
Yes. Uses the shared focus ring.
Accessible name
From the visible label (children). Icon-only buttons take it from aria-label, which TypeScript requires.
Notes
  • Focus ring is 2 px outline with 2 px offset at 3:1 or better against every surface.
  • loading keeps the label visible and sets aria-busy; it never swaps the label for a spinner alone.
  • Use a real button for actions and an anchor (asChild) for navigation so assistive technology announces the right thing.
  • A disabled asChild link gets aria-disabled and its clicks are blocked, so it never navigates.
Keyboard
KeysBehaviour
Tab

focus

Enter, Space

activate

—

Disabled buttons leave the tab order; loading buttons stay focusable and ignore activation

Motion

What moves
Background and border colours ease on hover and press; the loading spinner rotates. Visible when loading is on.
Tokens
duration.fastease.standardanimation.spinduration.spin
Reduced motion
Every token above collapses to 0 ms (and the spin animation to none) under the OS preference or inside any data-motion="reduced" scope. The component has no motion code of its own.

Contrast

Computed at build time from the token values, against the background each colour is paired with.

TokenOnLightDark
action.disabled-fgaction.disabled4.23:1 AA-large4.54:1 AA
focus.ringsurface.layer-16.00:1 AA6.72:1 AA