Stateful Button for React

A stateful button component designed to integrate seamlessly with shadcn/ui. It extends the standard Button component to elegantly handle asynchronous operations, providing visual feedback for loading/progress, success, and error states. It's perfect for time-consuming operations, including but not limited to file uploads, slow API requests, or data processing, keeping users informed that the task is still running and awaiting completion.

Installation

npx shadcn@latest add https://stateful-button.vercel.app/r/stateful-button.json

Usage

import { StatefulButton } from '@/components/ui/stateful-button';
<StatefulButton onClick={loading}>Button</StatefulButton>

Examples

The stateful button automatically handles success and error states based on the outcome of the onClick event. If the promise resolves, the button enters a success state; if it rejects, it enters an error state. The "Default" variant examples below demonstrate both scenarios.

Default

Secondary

Destructive

Outline

Ghost

API Reference

The StatefulButton component extends standard HTML button attributes and shadcn/ui's button variants, in addition to its own specific props:

PropTypeDefaultDescription
onClick(event: React.MouseEvent<HTMLButtonElement>) => void | Promise<unknown>-Click handler invoked when the button is pressed. Can return a Promise if the click handler is asynchronous.
onComplete() => void-Callback triggered when the action completes successfully.
onError(error: Error) => void-Callback triggered when onClick throws (or a rejection occurs).
buttonType'spinner' | 'progress''spinner'Specifies the button's behavior mode. 'spinner' shows a loading spinner. 'progress' displays a progress bar.
progressnumber-The current progress value (0-100). This is a controlled prop used to update the progress bar. Only applicable when buttonType is 'progress'.
childrenReact.ReactNode-Content to render inside the button while in the idle state.
ariaMessagesAriaMessagesDefault English messages for all states.Customizable ARIA messages for accessibility.
variantstring'default'The visual style of the button (e.g., default, destructive, outline). Inherited from shadcn/ui's Button component.
sizestring'default'The size of the button (e.g., default, sm, lg). Inherited from shadcn/ui's Button component.
...other native button propsReact.ButtonHTMLAttributes<HTMLButtonElement>-All standard HTML button attributes are supported.