One button that shows ready, running, review and done — without a modal.
Live preview
Documents · shared workspace
Quarterly review — draft
Last edited 12 minutes ago · 12 pages
Revenue held steady through the quarter while support volume fell for the second time this year. The appendix lists every change to the pricing table; two passages are still waiting on legal review.
4 charts·2 open comments·Draft v0.9
Nothing has run yet.
ActionReview stepAuto-run demoWidth
Press the button to walk the phases
01What it does
Long-running actions usually mean a spinner, then a toast, then a modal asking you to confirm what you just asked for. This button keeps the whole small workflow in one control: idle, running with real progress, a review beat, then a done state with a way to run again. The host owns the work; the button owns the honesty.
In this previewA plausible export/summarise action that walks its phases in place. Turn on auto-run to watch the whole cycle, or press the button yourself.
02Install
Registry install
Works with the shadcn CLI in any project that has a components.json. The component lands in components/lab/progressive-action/ with its stylesheet beside it.
/** * PROGRESSIVE ACTION — one control that walks a small workflow in * place: ready, running with real progress, an optional review beat, * then done or error. No modal, no toast; the host owns the work and * this button owns the honesty. Phase changes are announced politely. */ export function ProgressiveAction({ phase, progress, onRun, onAccept, onRetry, onReset, reviewSummary, labels, fixedWidth, className, }: ProgressiveActionProps) { const [announcement, setAnnouncement] = useState(""); const lastPhaseRef = useRef<ActionPhase | null>(null);
components/lab/progressive-action/progressive-action.css— press enter to show or hide the sourcecss
/* ============================================================ PROGRESSIVE ACTION — self-contained styles. Tokens are scoped on the root with fallbacks, so the control carries its own theme into any codebase. ============================================================ */