Luke UI
GitHub repository

Button

A labelled control for actions in an interface.

Button triggers an action, such as saving a form, opening a dialog, or deleting an item. Use Link when the interaction takes someone to another URL or route.

Button — Basic

Best practices

GuidancePractices
DoUse Button for an action, such as saving, submitting, or opening a dialog.
DoUse Link with an href when the interaction navigates to another URL or route.
Don'tNavigate from a Button. It loses native link semantics and browser link behaviours.

Size

medium is the default size. Use small in dense toolbars, tables, and other compact interfaces. Keep related controls at the same size.

Button — Size
Small
Medium

Appearance

Use appearance to set a button's visual weight. solid is the default. Choose subtle or ghost for secondary actions that should recede beside the main action. Appearance sets emphasis. Use tone to communicate intent.

Button — Appearance
Solid
Subtle
Ghost

Tone

Use tone to communicate intent. neutral is the default, accent identifies a primary action, and danger marks a destructive one. Tone and appearance are independent, so every combination is available.

Button — Tone
Neutral
Accent
Danger

Block layout

Set isBlock when the button should fill the inline size of its container. A typical case is a primary action at the end of a narrow form or panel.

<Button isBlock>Continue</Button>

Content slots

Use startContent or endContent for non-interactive adornments beside the label, such as an icon, badge, count, or keyboard hint. Nested interactive controls are unsupported. Button sizes nested icons for you, so an Icon needs no size prop. Pass one only to override it. Use IconButton only when the icon is familiar without a text label.

Button — Content slots

Pending and Actions

onPress handles the interaction. pressAction performs the resulting operation. When both are set, onPress runs first, then pressAction.

Prefer a native form Action when the operation is a form submission. Pass the form’s pending state to Button. This example uses React’s useActionState.

Button — Form Action

Use pressAction for Button-owned operations that are not form submissions. Combining pressAction with type="submit" is usually the wrong pattern, because both paths may run.

pressAction creates pending state automatically. Explicit isPending shows a spinner immediately. An Action-owned spinner waits briefly so a fast Action never flashes one.

Button — Pending

Set isPending for externally owned pending state, such as a parent mutation or router transition. Pending buttons stay focusable and ignore further presses.

Button — External pending

Unexpected failures from pressAction use React’s normal Action and Error Boundary behaviour. Handle expected domain errors inside the Action.

Button — Action error

Disabled

Set isDisabled only when the action is unavailable. Disabled buttons cannot receive focus or respond to presses.

Button — Disabled

Accessibility

The visible label provides the accessible name, so most buttons do not need aria-label. Write a label that describes the action, such as “Save changes” or “Delete account”, rather than a vague label such as “OK”.

The spinner is hidden from assistive technology. Pending state is announced through the button’s pending semantics, so the label does not need to change while pending.

Button is the normal component for application UI. It wraps its label for truncation, provides content slots, and supplies the pending spinner. Use the button primitive when you need to own the child layout or loading treatment.

API

ButtonProps also accepts compatible DOM and ARIA attributes and event handlers for its rendered element.

Prop

Type