Button
Atombeta@macaw-ds/ui · since 0.1.0Triggers 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.
| Keys | Behaviour |
|---|---|
| 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.
| Token | On | Light | Dark |
|---|---|---|---|
| action.disabled-fg | action.disabled | 4.23:1 AA-large | 4.54:1 AA |
| focus.ring | surface.layer-1 | 6.00:1 AA | 6.72:1 AA |