Multi Step Loader
A checklist-style loading indicator that ticks off steps one by one for long tasks.
A checklist-style loading overlay: it advances step by step, checking off the steps already completed, keeping the current step smoothly centered while the top and bottom edges fade out.
npx shadcn@latest add https://webberui.com/r/multi-step-loader.jsonPlayground
Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.
<MultiStepLoader />
Installation
npx shadcn@latest add https://webberui.com/r/multi-step-loader.jsonOr, once registries are configured in components.json, install it as @webberui/multi-step-loader.
Usage
By default the overlay fills the nearest positioned ancestor, so all you need to do is put it inside a relative container. Control visibility with the controlled loading prop.
import * as React from "react";
import { MultiStepLoader } from "@/components/ui/multi-step-loader";
const steps = ["Connecting to server", "Verifying identity", "Syncing data", "Ready"];
export function Example() {
const [loading, setLoading] = React.useState(false);
return (
<div className="relative h-80 w-full">
<button onClick={() => setLoading(true)}>Start</button>
<MultiStepLoader
steps={steps}
loading={loading}
onComplete={() => setLoading(false)}
/>
</div>
);
}Each step holds for duration milliseconds before advancing. In non-looping mode, reaching the last step fires onComplete, letting you set loading back to false after you wrap up.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
steps | string[] | — | Loading copy shown step by step and checked off in order |
loading | boolean | — | Whether the loading overlay is shown (controlled) |
duration | number | 1500 | How long each step holds (milliseconds) |
loop | boolean | false | Whether to loop back to the start after the last step |
visibleRows | number | 5 | Number of rows the visible area holds, deciding the overlay height and the top/bottom fade range |
overlay | boolean | true | true fills the positioned ancestor; false renders an inline card |
onComplete | () => void | — | Fires once when the last step is reached and looping is off |
className | string | — | Forwarded to the overlay container |
Customization
- Use the
--wb-loader-accentCSS variable to change the accent color of the check circles; it defaults to emerald#10b981. - With
overlay={false}the component renders as a bordered inline card, which suits placing it inside a flow panel.
Accessibility
- The overlay carries
role="status"andaria-live="polite", and the current step is announced through hidden text as "step name (n of total)". - The split-out list is hidden from assistive technology with
aria-hiddento avoid announcing it twice. - When the user has "reduce motion" enabled at the system level, the centering offset and the spinner animation switch instantly instead.