WebberUI

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.

Loading preview…
npx shadcn@latest add https://webberui.com/r/multi-step-loader.json

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

1500
5
<MultiStepLoader />

Installation

npx shadcn@latest add https://webberui.com/r/multi-step-loader.json

Or, 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

PropTypeDefaultDescription
stepsstring[]Loading copy shown step by step and checked off in order
loadingbooleanWhether the loading overlay is shown (controlled)
durationnumber1500How long each step holds (milliseconds)
loopbooleanfalseWhether to loop back to the start after the last step
visibleRowsnumber5Number of rows the visible area holds, deciding the overlay height and the top/bottom fade range
overlaybooleantruetrue fills the positioned ancestor; false renders an inline card
onComplete() => voidFires once when the last step is reached and looping is off
classNamestringForwarded to the overlay container

Customization

  • Use the --wb-loader-accent CSS 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" and aria-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-hidden to 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.

On this page