Overview
A submit-style control that morphs width and content across idle → loading → success | error. Icons cross-fade with scale + blur (not a hard toggle). First paint skips enter animation via initial={false}.
Installation
Basic Usage
tsx
import { MorphButton } from "@/components/ui/morph-button"; <MorphButton status={status} onClick={send} onReset={() => setStatus("idle")} resetAfterMs={2000} idleLabel="Send invite" loadingLabel="Sending" successLabel="Sent"/>
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| status | "idle" | "loading" | "success" | "error" | No | "idle" | Controlled visual state. |
| onClick | () => void | No | — | Click handler (ignored while loading). |
| idleLabel | string | No | "Send invite" | Label for the idle state. |
| loadingLabel | string | No | "Sending" | Label while loading. |
| successLabel | string | No | "Sent" | Label on success. |
| errorLabel | string | No | "Failed" | Label on error. |
| resetAfterMs | number | No | 0 | Auto-call onReset after success/error. 0 disables. |
| onReset | () => void | No | — | Called when resetAfterMs elapses. |
| layoutId | string | No | — | Shared layout id for the shell morph. |
| className | string | No | — | Optional class names on the button. |
Best Practices
- Own
statusin the parent — this component is presentational about the state machine. - Icon enter uses scale
0.25 → 1, opacity, and blur4px → 0withbounce: 0. - Press scale is
0.96and disabled during loading. - Prefer
resetAfterMsfor success toast-like feedback; keep error sticky until the user retries.