Action button

A compact button for frequent toolbar actions.

pnpm dlx shadcn@latest add @uiarc/action-button
Live · keyboard ready
  • A single async commit such as Save, Publish, or Submit where the result should appear on the button.
  • Call-to-action buttons where a trailing arrow invites the next step.
  • Flows where the button should reset to idle on its own after success, via resetAfterMs.
  • Use button with loading for plain form submits that do not need a success state.
  • Use action-swap when the control toggles between lasting states.
  • Use hold-to-confirm when the action is destructive and needs a deliberate press.

Installation

Add Action button with the shadcn CLI, or copy the source by hand.

pnpm dlx shadcn@latest add @uiarc/action-button

Adds the component and its local dependencies, and installs motion, lucide-react. First time? Add the @uiarc registry to components.json, or use the full URL:

example.tsx
import { ActionButton } from "@/registry/components/action-button/action-button"; export function PublishButton() {  return (    <ActionButton      label="Publish"      pendingLabel="Publishing"      successLabel="Published"      onAction={publish}      onActionError={error => toast.error(String(error))}    />  );}

ActionButton

A call-to-action button with a trailing arrow that runs an async action and morphs through pending and success.

PropTypeDefaultDescription
labelRequiredstring–Idle label and accessible name.
onActionRequired() => void | Promise<void>–Runs on press. The pending state lasts until the promise settles.
pendingLabelstring"Saving"Label while onAction runs.
successLabelstring"Saved"Label after onAction resolves.
resetAfterMsnumber2400Delay before returning to idle after success. 0 keeps the success state.
onActionError(error: unknown) => void–Called when onAction rejects; the button returns to idle.
...propsButtonHTMLAttributes<HTMLButtonElement>–Forwarded to the button, except onClick.
EnterorSpace
Runs the action.
  • Native button; the visible label is aria-hidden and a visually hidden copy of label names it.
  • Pending sets aria-busy and aria-disabled instead of disabled, so keyboard focus stays through the save.
  • A role="status" region announces the pending and success labels.
  • Changed letters rise from a soft blur while the width springs to fit; the arrow leaves forward and a check draws itself in.
  • Presses scale to about 0.97 on a snappy spring.
  • Reduced motion drops the press scale, width spring, and stroke draw, and swaps with an instant fade.
  • Width springs to fit pending and success labels, so keep them close in length inside tight toolbars.
  • Hover shadow applies only on hover-capable fine pointers; touch gets the press scale.
  • Every letter is a motion span with layout position animation plus a small blur; fine for a few buttons, not for dense tables.
  • A ResizeObserver drives the width spring.

Notes for AI

Give your coding assistant the Markdown reference instead of screenshots.

  • Use for a single async commit (save, publish, submit) where the result should show on the button itself.
  • Prefer button with loading for plain forms, and action-swap when the control toggles between lasting states.
  • Return the real promise from onAction; handle errors in onActionError since the button just resets.

The full library index for assistants is at /llms.txt.