Loading State
Show that long-running work is in progress, with a label and the time elapsed.
Overview
Loading State is one line: a small animated mark, a label that says what is in progress, and how long it has been running. Use it when work takes long enough that a person may wonder whether anything is happening.
Render it while the work runs and remove it when the work ends. Loading State does not know when your work finishes and reports no progress of its own. The elapsed time is real: it counts from startedAt, or from when the component mounted.
Use Thinking State instead when you have steps to show.
Anatomy
- MarkA 3 by 3 grid of cells that light in a pattern
- LabelWhat is in progress
- ElapsedSeconds, then minutes and seconds, since the work began
Installing loading-state brings Text Shimmer along as a registry dependency.
Behavior
Patterns
pattern is drive, dots, or orbit. Drive and dots sweep a wave across the grid, in square or round cells. Orbit laps the edge. The pattern is decoration and carries no meaning.
Elapsed time
The time updates once a second and reads as 42s, then 1m 12s. Pass startedAt when the work began before the component mounted, for example after a page reload. Set showElapsed to false to leave it out.
Accessibility
The label is a polite status, so it is announced when the component appears and when the label changes. The elapsed time is hidden from screen readers, because a status that changes every second would be read every second. The mark is decorative.
With reduced motion, the cells stay dim and the label stops shimmering. The elapsed time still updates.
Installation
Usage
import { LoadingState } from "@/components/ai/loading-state"
{run.isPending && <LoadingState label="Building the export" startedAt={run.startedAt} />}Write the label as the work, not as "Loading". "Building the export" tells the person what they are waiting for.
Examples
Patterns
The three patterns, without the elapsed time.
API reference
LoadingState
Accepts native div props beyond those listed.