Button
Action primitive for native buttons, links, and custom button-like elements.
Button in motion
When to Use
Use Button when the user performs an action such as saving, submitting, or
opening a control. Provide href when the control navigates to another
location. Use Toggle when the pressed state must stay on or off, and use
Pressable for a custom interactive surface that needs press-state behavior
without Button's link and loading APIs.
Features
The behavior Atom owns before your product adds appearance.
- Renders a native
buttonby default. - Renders a native
awhenhrefis provided. - Preserves link semantics when an anchor or inactive-safe link adapter is
supplied through
asChildorrender. - Supplies button role, focusability, and keyboard activation to non-native custom renders.
- Supports disabled and loading states.
- Calls
onPressafteronClickwhen the click is not canceled. - Prevents inactive controls from firing consumer activation handlers.
- Adds
noopener noreferrerto new-tab links while preserving otherreltokens. - Supports
asChildandrender.
Import
Anatomy
API Reference
Root
Renders the action element and owns its activation, inactive-state, and safe
link behavior. Native button props pass through by default; anchor-related props
apply when href is provided.
| Prop | Type | Default |
|---|---|---|
href | string | - |
target | AnchorHTMLAttributes<HTMLAnchorElement>["target"] | - |
rel | AnchorHTMLAttributes<HTMLAnchorElement>["rel"] | - |
disabled | boolean | false |
loading | boolean | false |
onPress | MouseEventHandler<HTMLElement> | - |
onClick | MouseEventHandler<HTMLElement> | - |
onKeyDown | KeyboardEventHandler<HTMLElement> | - |
type | "button" | "submit" | "reset" | "button" |
asChild | boolean | false |
render | RenderProp | - |
| ARIA attribute | Values |
|---|---|
role | "button" for non-native action renders; "link" for an inactive direct or composed link |
aria-disabled | "true" when a non-native control is disabled or loading |
aria-busy | "true" when loading |
| Data attribute | Values |
|---|---|
[data-slot] | "button" |
[data-disabled] | Present when disabled |
[data-loading] | Present when loading |
A native button receives the native disabled attribute only when disabled
is true. A loading native button remains focusable, exposes aria-busy, and
blocks activation. Inactive direct and composed links omit href, target,
and rel, including when those props came from the asChild child or a
render element.
When composing a link, expose its destination through an href prop on
Button.Root, the asChild child, or the render element. Atom uses that prop
to preserve navigation semantics and replaces href, target, and rel with
null while disabled or loading. Native anchors and permissive adapters omit
those attributes from the rendered anchor. Link compositions keep native link
keyboard behavior: Enter is handled by the browser, and Space does not
synthesize a click.
Some router components require href to remain a string and will reject this
inactive prop shape. Do not compose those components directly for a Button
that can become disabled or loading. Use a render adapter that renders the
router component only while active and renders a destination-free anchor while
inactive. Atom intentionally does not add router-specific compatibility.
Examples
Action Button
Navigation Link
Composed Link
The example above is an inactive-safe adapter because it tolerates Atom's removed destination at runtime. For a strict router component, adapt the inactive render explicitly:
In an application, StrictRouterLink is the router component and remains
application-owned; Atom does not import or wrap it.
Loading Action
Custom Button Element
Accessibility
Button follows the
WAI-ARIA Button pattern.
Prefer the default native button because the browser supplies its semantics
and keyboard behavior. Every Button needs an accessible name from its text,
aria-label, or aria-labelledby.
Custom non-native action elements receive role="button", tabIndex={0}, and
keyboard activation. Native anchors and inactive-safe composed links retain
link semantics instead of receiving button role or Space-key activation. Disabled
native buttons use the native disabled attribute. Disabled or loading
non-native controls expose aria-disabled, and loading controls expose
aria-busy while remaining focusable. Inactive links have no live href, so
clicks, keyboard activation, and alternate navigation methods cannot follow the
destination.
| Key | Description |
|---|---|
Enter | Activates custom button-like renders; native controls keep browser behavior. |
Space | Activates custom button-like renders; native controls keep browser behavior. |
Changelog
Unreleased
- No unreleased changes.
0.2.1
- Fixed direct and composed Button links so
asChildandrenderanchors or inactive-safe link adapters retain link semantics and native keyboard behavior. - Removed
href,target, andrelfrom disabled or loading composed links and blocked their composed activation handlers so inactive links cannot navigate. - Documented the required render-adapter contract for router components that
reject a removed
href.
0.2.0
- Fixed
Button.RootasChildcomposition so non-native child elements receive button semantics and keyboard focus behavior.
0.1.0
- Initial Atom release.