Morph Button
An async button that morphs between idle, loading, success, and error states.
@spectrumui/morph-button
Click to run the full idle → loading → success cycle
Login to view codeCreate a free account to access component source code
Installation
Login to view commandCreate a free account to access the install command
Usage
import { MorphButton } from "@/components/spectrumui/morph-button"<MorphButton onAction={() => saveChanges()}>Save changes</MorphButton>API Reference
MorphButton
Renders a single button element driven by a MorphButtonState — "idle" | "loading" | "success" | "error". Pass onAction to let the button run the full cycle itself, or pass state to drive it from outside (the internal machine is bypassed and onClick still fires). While not idle the button is aria-disabled and ignores clicks, and a polite live region announces each state change.
| Prop | Type | Default | Description |
|---|---|---|---|
*children | React.ReactNode | - | Idle content of the button — usually a short action label |
onAction | () => Promise<void> | void | - | Async work to run on click when uncontrolled. Loading while pending, success on resolve, error on throw, then auto-reset |
state | "idle" | "loading" | "success" | "error" | - | Controlled state. When provided the internal machine is bypassed |
onClick | React.MouseEventHandler<HTMLButtonElement> | - | Click handler; fires on idle clicks in both modes |
loadingLabel | string | - | Label rendered next to the spinner while loading; spinner-only if omitted |
successLabel | string | "Done" | Label shown next to the check in the success state |
errorLabel | string | "Failed" | Label shown next to the X in the error state |
resetDelay | number | 1800 | Milliseconds success/error is held before auto-resetting to idle |
size | "sm" | "md" | "lg" | "md" | Visual size of the button |
disabled | boolean | false | Disables pointer and keyboard interaction |
className | string | - | Additional classes merged with the default button styles |
Examples
Error state and sizes
The first action always rejects — error state with a tight shake
Login to view codeCreate a free account to access component source code