Status and feedback

Which component to use for telling someone what happened, what state a thing is in, or that it is loading. Find the job, take the component, and read the “not when” before you commit: it names the thing people reach for by mistake, and what to use instead.

At a glance

JobUseNot whenInsteadBecause
Say something about the page that stays until it is no longer trueAlertA figure or list is built from only some of its sourcesStateState kind="partial" sits right above the figures and says how many arrived; a banner is read past and the figure still looks like the total.
Confirming an action the person just took, which needs no further attentionToastA toast reports an event and leaves; an alert reports a condition and stays.
The region has nothing to show, failed to load, or is not allowedStateA state replaces the content it stands for; an alert sits above content that is still there.
A note inside prose that qualifies what is around itCalloutA callout is a rule beside text at reading scale; a tinted banner would make it an alert it is not.
The person must answer before anything else can happenDialogA dialog takes focus and must be dismissed; an alert can be read past.
A form step has fields that failed validationErrorSummaryThe error summary links each problem to its field and takes focus on submit.
Set a quiet aside inside proseCalloutThe message is about the page or a region, not the paragraphAlertAn alert is a banner with a tone and an action; a callout is a rule beside text.
The region has nothing to showStateA state says why the content is absent and what to do; a callout assumes there is prose around it.
A hint that belongs to one form fieldFieldA field hint is tied to its control by aria-describedby; a callout is not.
A short status wordTagA status is one or two words in a tag, never a sentence.
Keep one broken region from blanking the app, and say plainly that it could not be shownErrorBoundaryA fetch failed or a source did not answerStateA failed fetch is a state the screen expected and renders itself, with a retry; a boundary is for a render that threw.
The content is there and something about it is wrong or staleAlertAn alert sits above content that still shows; a boundary replaces content that could not be drawn.
Show one file on its way — how far, and cancel or retryFileProgressThe file has been attached and nothing is movingFileUploadFileItem lists what is attached; a transfer row exists only while bytes move or after they failed.
One task that is not a file — an import, an exportProgressA labelled bar carries the same layout without the file's size and actions.
A batch of many files where only the totals matterSegmentedProgressForty rows is a wall; a segmented bar says how many arrived, failed and wait.
Show an integration and the state it is in, with the way to fix itConnectionThe status is not about an integrationTagA tag is the general status word; ConnectionStatus has only the integration states.
The problem needs the reader to act before carrying on with the pageAlertAn alert is an inline banner with a title, body and action for one problem.
The thing on the row is an API key or a secretKeyListKeys have a fingerprint, scopes, last use and expiry; a connection has none of those.
Show how far one task has got toward doneProgressA level that is simply true — usage, capacity, a score against a targetMeterrole="meter" reports a level; a progress bar says a task is advancing, and swapping them misreports what is happening.
Many items, each finished one way or another — 6 done, 1 failed, 3 to goSegmentedProgressOne fill cannot say how things finished; a segmented bar splits the track by state and says each count.
The reader needs to see WHICH tasks are done, not just how manyProgressListA bar is a quantity; a checklist names each task and its state.
One row's live work in a list or table, with where it is and a countLiveProgressLive progress carries the pulse, the place being worked and the count, and turns into a tag when done or failed.
A file being uploaded or downloadedFileProgressA transfer row carries the name, the size, cancel and retry around the same bar.
The person is moving through named stepsStepperA stepper names each step and its state; a bar only says how much.
A short wait inside a control with nothing to measureSpinnerA spinner is the smallest "still working" and takes no room.
Mark one item's state with the progress family's disc or glyphProgressMarkA whole list of tasks with their states and a countProgressListThe checklist already lays out the marks, the labels and the count, and announces failures.
A status word with a tint, standing aloneTagA tag is the status; a mark is decoration beside words and is hidden from assistive tech.
Show how a set of items is going, split by how each one finishedSegmentedProgressOne task with one fraction doneProgressA single fill is clearer when there is only one way to finish.
The reader needs each item by nameProgressListA segmented bar counts; a checklist names.
The items move between states while the reader watches, by nameLanesLanes show each agent as a pill sliding between states; a segmented bar is the summary.
Parts of a whole that are not progress — a budget by category, a share of votesBarChartA stacked bar chart is a composition; this is work advancing, coloured by state.
Show a list of tasks the system is working through, each with its state, and how many are doneProgressListThe reader ticks the items off themselvesChecklistA checklist is checkboxes the reader owns; a progress list reports work the system does.
Steps of a form the reader moves through, one current, with back and nextStepperA stepper is a position in an order the reader walks; a progress list is work being done for them.
Many items, where only the counts matterSegmentedProgressNaming a hundred items is a wall; a segmented bar says how many in each state.
Several agents running at onceLanesLanes show concurrency — who is waiting, working and done; a list is one sequence.
Hold the shape of content that is still being readSkeletonThere is nothing to showStateA skeleton means "still reading" and never "nothing here"; an empty state names the cause and the way out.
The read failed, or a failed read is being retriedStateA skeleton never tells you it has finished; an error state says what went wrong, and the retry button shows its own wait.
A figure is shown from only some of its sourcesStateThe read finished; a skeleton would claim it is still loading. State kind="partial" says what is missing.
The wait is short and the layout is not knownSpinnerA spinner marks a brief wait without promising a shape.
A section is being written by a run right nowLiveLiveSection and LiveMark say the section is being written, in words.
Show that a short wait is under way, where its result will appearSpinnerThe shape of the content that is loading is knownSkeletonA skeleton holds the layout so nothing jumps when the content lands.
The work has a known amount done and to doProgressA progress bar says how far along it is; a spinner only says "busy".
An agent or a run is working on something the reader is watchingLiveLive work is drawn where the work is, with a word beside the pulse.
A circular indicator with a known amount doneProgressProgressRing is the same ring with a value; the spinner is that ring when nothing can be measured.
A button is submittingButtonThe button has its own loading state (.is-loading) and keeps its label and width.
Stand in for content that is loading, empty, partial, failed, denied or doneStateThe content is there and something about it needs sayingAlertAn alert sits above content that is still shown; a state replaces it.
The region is still loading and its shape is knownSkeletonA skeleton holds the layout while it reads; State kind="loading" is for when the shape is not known.
A sign-in or access page that stands before the productEntryA way in is not an empty state; read as one it looks like a dead end.
Confirming a quick action that workedToastA success state replaces a whole region; most successes only need a toast.
Show where someone is in a named sequence of stepsStepperBuilding the whole multi-step form, with back and forwardFlowThe flow shell already holds a vertical stepper, one content region and the footer.
How much of one task is done, with no named stepsProgressA bar says how much; a stepper says which.
Many agents or items moving through waiting, working and done at onceLanesLanes show many items by state; a stepper is one sequence.
A list of tasks the system works through for the reader — setup, an agent's runProgressListA stepper is a position the reader walks; a progress list reports work done for them, with a spinner on the running task.
Events that already happened, in orderTimelineA timeline is history; a stepper is position in a plan.
Say in one or two words what state a thing is inTagThe word is something the reader can press to do somethingButtonA status is a tag and an action is a button; where both sit on one row they must differ in shape, not only in colour.
The value is a neutral attribute — an owner, a standard, a type — that may narrow the listFacetA tag carries no status here and is decoration; a facet is a name and a value, and narrows when pressed.
The state is an integration being connected, degraded or offConnectionConnectionStatus carries the integration states with a decorative dot and the word.
The status needs a sentence to explain itAlertA tag is one or two words; prose belongs in an alert, a hint or a state body.
Confirm that something just happened, briefly, without taking focusToastYou want to raise a toast from anywhere in the app with timers handledToastProviderThe provider owns the queue, the timeout and the pause on hover; Toast is only the surface.
The condition is still true after the moment passes — a failed source, a stale figureAlertA toast leaves; a condition that leaves with it is a condition nobody can find again.
The person has to decide something before going onDialogAn action in a toast is right for undo, not for a decision: a toast is polite and can be missed, and a decision needs a modal that holds focus.
An agent proposes a change and the person has to confirm or approve itConfirmCardAn action in a toast is right for undo, not for a decision; the confirm card holds the values and waits in the conversation until it is answered.
The region the action was meant to fill is empty or failedStateThe result belongs where the content would be, not in a corner.
Raise toasts from anywhere in an app, with the queue and timers handledToastProviderYou render the toast markup yourself, or in static HTMLToastThe provider renders Toast for you; use the parts directly only when you own the queue.
The person has to decide something — confirm a delete, choose between two outcomesDialogAn action in a toast is right for undo, not for a decision; a decision needs a modal that holds focus until it is answered.
An agent asks the person to confirm or approve a changeConfirmCardAn action in a toast is right for undo, not for a decision; the confirm card shows what will change and waits for an answer.
The message describes a condition rather than an eventAlertA queued toast times out; a condition has to stay on the page.

Alert

Say something about the page that stays until it is no longer true.

Use when

  • A condition that holds for the whole page or region — a source is stale, eleven items are unanswered, the run failed.
  • A message with a way out of it: put the action in AlertActions, beside the problem it fixes.
  • Set live when the banner appears after load; danger and warning announce assertively, the rest politely.

Not when

  • A figure or list is built from only some of its sources → State. State kind="partial" sits right above the figures and says how many arrived; a banner is read past and the figure still looks like the total.
  • Confirming an action the person just took, which needs no further attention → Toast. A toast reports an event and leaves; an alert reports a condition and stays.
  • The region has nothing to show, failed to load, or is not allowed → State. A state replaces the content it stands for; an alert sits above content that is still there.
  • A note inside prose that qualifies what is around it → Callout. A callout is a rule beside text at reading scale; a tinted banner would make it an alert it is not.
  • The person must answer before anything else can happen → Dialog. A dialog takes focus and must be dismissed; an alert can be read past.
  • A form step has fields that failed validation → ErrorSummary. The error summary links each problem to its field and takes focus on submit.

Confused with Toast, State, Callout, ErrorSummaryReact Alert AlertTitle AlertBody AlertActionsClasses .alert

See it on the demo page

Callout

Set a quiet aside inside prose.

Use when

  • A note, caveat or rule that qualifies the text around it — "Figures exclude the March import."
  • A short absence or warning at reading scale: tone="warning" tints the rule, nothing else.

Not when

  • The message is about the page or a region, not the paragraph → Alert. An alert is a banner with a tone and an action; a callout is a rule beside text.
  • The region has nothing to show → State. A state says why the content is absent and what to do; a callout assumes there is prose around it.
  • A hint that belongs to one form field → Field. A field hint is tied to its control by aria-describedby; a callout is not.
  • A short status word → Tag. A status is one or two words in a tag, never a sentence.

Confused with Alert, Tooltip, Field, PaperReact Callout CalloutTitleClasses .callout

See it on the demo page

ErrorBoundary

Keep one broken region from blanking the app, and say plainly that it could not be shown.

Use when

  • Around a routed page, inside the frame, so the header and navigation stay when the page throws: <ErrorBoundary resetKey={path}>, and leaving the page recovers it.
  • Around a panel that renders data it does not control — a detail pane, a chart, an embedded preview — with the record id as resetKey.
  • Hand the error to onError for the log. The person sees State kind="error", never the error text.

Not when

  • A fetch failed or a source did not answer → State. A failed fetch is a state the screen expected and renders itself, with a retry; a boundary is for a render that threw.
  • The content is there and something about it is wrong or stale → Alert. An alert sits above content that still shows; a boundary replaces content that could not be drawn.

Confused with State, AlertReact ErrorBoundary

See it on the demo page

FileProgress

Show one file on its way — how far, and cancel or retry.

Use when

  • An upload or download in a FileList: name and percent above a 4px bar, the size or the reason below, cancel while it moves and retry when it fails.
  • Arriving and failing are announced once; the percentage is never read aloud.

Not when

  • The file has been attached and nothing is moving → FileUpload. FileItem lists what is attached; a transfer row exists only while bytes move or after they failed.
  • One task that is not a file — an import, an export → Progress. A labelled bar carries the same layout without the file's size and actions.
  • A batch of many files where only the totals matter → SegmentedProgress. Forty rows is a wall; a segmented bar says how many arrived, failed and wait.

Confused with FileUpload, Progress, SegmentedProgressReact FileProgressClasses .file-progress

See it on the demo page

Connection

Show an integration and the state it is in, with the way to fix it.

Use when

  • A list of connected systems, each with its mark, name, a note and its state — connected, degraded, error, pending or off.
  • The state is a word in ConnectionStatus; the dot is decorative, so colour is never the only signal.
  • Actions to connect, reconnect or configure sit on the row in ConnectionActions.

Not when

  • The status is not about an integration → Tag. A tag is the general status word; ConnectionStatus has only the integration states.
  • The problem needs the reader to act before carrying on with the page → Alert. An alert is an inline banner with a title, body and action for one problem.
  • The thing on the row is an API key or a secret → KeyList. Keys have a fingerprint, scopes, last use and expiry; a connection has none of those.

Confused with Tag, Alert, KeyListReact Connection ConnectionMark ConnectionBody ConnectionName ConnectionNote ConnectionActions ConnectionStatusClasses .connection

See it on the demo page

Progress

Show how far one task has got toward done.

Use when

  • An upload, an import or an export with a known fraction — value of max; label, helper and the value lay out by the family rule: label start, value end, helper under.
  • Under way with no known fraction: omit value for the indeterminate bar; tone only once it has ended (success, warning, danger).
  • ProgressRing where a bar does not fit — 16 to 64px, the value inside from 48px, an icon or nothing in the centre.

Not when

  • A level that is simply true — usage, capacity, a score against a target → Meter. role="meter" reports a level; a progress bar says a task is advancing, and swapping them misreports what is happening.
  • Many items, each finished one way or another — 6 done, 1 failed, 3 to go → SegmentedProgress. One fill cannot say how things finished; a segmented bar splits the track by state and says each count.
  • The reader needs to see WHICH tasks are done, not just how many → ProgressList. A bar is a quantity; a checklist names each task and its state.
  • One row's live work in a list or table, with where it is and a count → LiveProgress. Live progress carries the pulse, the place being worked and the count, and turns into a tag when done or failed.
  • A file being uploaded or downloaded → FileProgress. A transfer row carries the name, the size, cancel and retry around the same bar.
  • The person is moving through named steps → Stepper. A stepper names each step and its state; a bar only says how much.
  • A short wait inside a control with nothing to measure → Spinner. A spinner is the smallest "still working" and takes no room.

Confused with Meter, SegmentedProgress, ProgressList, LiveProgress, FileProgress, Stepper, SpinnerReact Progress ProgressRingClasses .progress .progress-ring

See it on the demo page

ProgressMark

Mark one item's state with the progress family's disc or glyph.

Use when

  • ProgressMark — a 24px (or 16px) disc in one of the six states: queued, current (a spinner), complete, failed, stopped, skipped. The same disc a stepper marker draws.
  • ProgressGlyph — the tick, cross, dash or ! inline at 1em, beside a word that says the same thing.

Not when

  • A whole list of tasks with their states and a count → ProgressList. The checklist already lays out the marks, the labels and the count, and announces failures.
  • A status word with a tint, standing alone → Tag. A tag is the status; a mark is decoration beside words and is hidden from assistive tech.

Confused with ProgressList, Tag, StepperReact ProgressMark ProgressGlyphHooks PROGRESS_STATE_WORDS PROGRESS_STATE_GLYPHClasses .progress-mark .progress-glyph

See it on the demo page

SegmentedProgress

Show how a set of items is going, split by how each one finished.

Use when

  • A batch, a run or a set of checks: one track split into done, failed, stopped, skipped, running and to go, with a legend that says every count in words.
  • The value is how many have finished however they finished, and assistive tech hears the whole breakdown — "6 done, 1 failed, 3 to go".

Not when

  • One task with one fraction done → Progress. A single fill is clearer when there is only one way to finish.
  • The reader needs each item by name → ProgressList. A segmented bar counts; a checklist names.
  • The items move between states while the reader watches, by name → Lanes. Lanes show each agent as a pill sliding between states; a segmented bar is the summary.
  • Parts of a whole that are not progress — a budget by category, a share of votes → BarChart. A stacked bar chart is a composition; this is work advancing, coloured by state.

Confused with Progress, ProgressList, Lanes, BarChartReact SegmentedProgressClasses .progress-segments .progress-legend

See it on the demo page

ProgressList

Show a list of tasks the system is working through, each with its state, and how many are done.

Use when

  • Setup, onboarding or an agent's run: each task with its mark, an optional description, and 3 of 7 with a 4px bar.
  • The running task's mark is the spinner and the list is aria-busy; a failure and the end of the list are announced, nothing else.

Not when

  • The reader ticks the items off themselves → Checklist. A checklist is checkboxes the reader owns; a progress list reports work the system does.
  • Steps of a form the reader moves through, one current, with back and next → Stepper. A stepper is a position in an order the reader walks; a progress list is work being done for them.
  • Many items, where only the counts matter → SegmentedProgress. Naming a hundred items is a wall; a segmented bar says how many in each state.
  • Several agents running at once → Lanes. Lanes show concurrency — who is waiting, working and done; a list is one sequence.

Confused with Checklist, Stepper, SegmentedProgress, LanesReact ProgressListClasses .progress-list

See it on the demo page

Skeleton

Hold the shape of content that is still being read.

Use when

  • A page or a list is loading and its layout is known — lines of text, a title, a block, an avatar circle.
  • Inside a region that announces its own loading (aria-busy); each bar is always aria-hidden.

Not when

  • There is nothing to show → State. A skeleton means "still reading" and never "nothing here"; an empty state names the cause and the way out.
  • The read failed, or a failed read is being retried → State. A skeleton never tells you it has finished; an error state says what went wrong, and the retry button shows its own wait.
  • A figure is shown from only some of its sources → State. The read finished; a skeleton would claim it is still loading. State kind="partial" says what is missing.
  • The wait is short and the layout is not known → Spinner. A spinner marks a brief wait without promising a shape.
  • A section is being written by a run right now → Live. LiveSection and LiveMark say the section is being written, in words.

Confused with Spinner, State, LiveReact SkeletonClasses .skeleton

See it on the demo page

Spinner

Show that a short wait is under way, where its result will appear.

Use when

  • A brief wait inside a control or a small region — a button submitting, a panel refreshing.
  • Decorative by default: the surrounding region carries aria-busy; pass label only when it stands alone.
  • It is the indeterminate ring of the progress family at 16, 24 and 32px — the same track, arc colour and stroke as ProgressRing.

Not when

  • The shape of the content that is loading is known → Skeleton. A skeleton holds the layout so nothing jumps when the content lands.
  • The work has a known amount done and to do → Progress. A progress bar says how far along it is; a spinner only says "busy".
  • An agent or a run is working on something the reader is watching → Live. Live work is drawn where the work is, with a word beside the pulse.
  • A circular indicator with a known amount done → Progress. ProgressRing is the same ring with a value; the spinner is that ring when nothing can be measured.
  • A button is submitting → Button. The button has its own loading state (.is-loading) and keeps its label and width.

Confused with Skeleton, Progress, Live, ButtonReact SpinnerClasses .spinner

See it on the demo page

State

Stand in for content that is loading, empty, partial, failed, denied or done.

Use when

  • A region has no content to show and needs to say why: kind is loading, empty, partial, error, denied or success.
  • A figure or list built from some sources but not all: kind="partial" directly above the figures that did arrive, saying which are missing and offering a retry. Use it instead of an Alert so the figure cannot be read as the full total.
  • An empty list or a failed read that names its cause and offers the way out in StateActions (Create…, Retry); art gives an empty place a line drawing. A retry shows its wait on the button, not by swapping in a Skeleton.

Not when

  • The content is there and something about it needs saying → Alert. An alert sits above content that is still shown; a state replaces it.
  • The region is still loading and its shape is known → Skeleton. A skeleton holds the layout while it reads; State kind="loading" is for when the shape is not known.
  • A sign-in or access page that stands before the product → Entry. A way in is not an empty state; read as one it looks like a dead end.
  • Confirming a quick action that worked → Toast. A success state replaces a whole region; most successes only need a toast.

Confused with Alert, Skeleton, Entry, Toast, SpinnerReact State StateIcon StateTitle StateBody StateActions StateDetail StateArtClasses .state

See it on the demo page

Stepper

Show where someone is in a named sequence of steps.

Use when

  • A multi-step task where each step is an act the person performs — markers, one per step.
  • A sequence that is a position the work is somewhere in — rail, which fills what is behind.
  • A step that was refused (failed), interrupted (stopped) or passed over (skipped) — never left at current or marked complete. size="sm" and description for dense or explained steps.

Not when

  • Building the whole multi-step form, with back and forward → Flow. The flow shell already holds a vertical stepper, one content region and the footer.
  • How much of one task is done, with no named steps → Progress. A bar says how much; a stepper says which.
  • Many agents or items moving through waiting, working and done at once → Lanes. Lanes show many items by state; a stepper is one sequence.
  • A list of tasks the system works through for the reader — setup, an agent's run → ProgressList. A stepper is a position the reader walks; a progress list reports work done for them, with a spinner on the running task.
  • Events that already happened, in order → Timeline. A timeline is history; a stepper is position in a plan.

Confused with Flow, Progress, ProgressList, Lanes, Timeline, ChecklistReact Stepper StepClasses .stepper .step

See it on the demo page

Tag

Say in one or two words what state a thing is in.

Use when

  • A row, card or heading reports a status — Draft, Approved, At risk, Failed — and the variant maps to its meaning.
  • A quiet marker on a dense row: dot puts a filled dot before the word instead of a tint.

Not when

  • The word is something the reader can press to do something → Button. A status is a tag and an action is a button; where both sit on one row they must differ in shape, not only in colour.
  • The value is a neutral attribute — an owner, a standard, a type — that may narrow the list → Facet. A tag carries no status here and is decoration; a facet is a name and a value, and narrows when pressed.
  • The state is an integration being connected, degraded or off → Connection. ConnectionStatus carries the integration states with a decorative dot and the word.
  • The status needs a sentence to explain it → Alert. A tag is one or two words; prose belongs in an alert, a hint or a state body.

Confused with Facet, Button, Connection, LiveProgressReact TagClasses .tag

See it on the demo page

Toast

Confirm that something just happened, briefly, without taking focus.

Use when

  • The result of an action the person took — "Saved", "Invite sent", "Export ready" — with at most one way to take it back: ToastAction for Undo, before ToastClose.
  • An event that happened elsewhere while they work, worth a glance and no more.
  • Rendering the surface yourself; mount ToastRegion once, near the root, before any toast is added.

Not when

  • You want to raise a toast from anywhere in the app with timers handled → ToastProvider. The provider owns the queue, the timeout and the pause on hover; Toast is only the surface.
  • The condition is still true after the moment passes — a failed source, a stale figure → Alert. A toast leaves; a condition that leaves with it is a condition nobody can find again.
  • The person has to decide something before going on → Dialog. An action in a toast is right for undo, not for a decision: a toast is polite and can be missed, and a decision needs a modal that holds focus.
  • An agent proposes a change and the person has to confirm or approve it → ConfirmCard. An action in a toast is right for undo, not for a decision; the confirm card holds the values and waits in the conversation until it is answered.
  • The region the action was meant to fill is empty or failed → State. The result belongs where the content would be, not in a corner.

Confused with ToastProvider, Alert, State, ConfirmCardReact ToastRegion Toast ToastTitle ToastBody ToastAction ToastCloseClasses .toast

See it on the demo page

ToastProvider

Raise toasts from anywhere in an app, with the queue and timers handled.

Use when

  • Wrap the app once and call useToast().toast({ title, tone }) from any component.
  • Toasts should time out, pause while the pointer is over them, and cap at a few on screen.
  • Undo after the fact: toast({ title, action: { label: 'Undo', onAction } }). A toast with an action stays until dismissed (it defaults to duration: 0), and its button is announced with it and reached by Tab.

Not when

  • You render the toast markup yourself, or in static HTML → Toast. The provider renders Toast for you; use the parts directly only when you own the queue.
  • The person has to decide something — confirm a delete, choose between two outcomes → Dialog. An action in a toast is right for undo, not for a decision; a decision needs a modal that holds focus until it is answered.
  • An agent asks the person to confirm or approve a change → ConfirmCard. An action in a toast is right for undo, not for a decision; the confirm card shows what will change and waits for an answer.
  • The message describes a condition rather than an event → Alert. A queued toast times out; a condition has to stay on the page.

Confused with Toast, Alert, Dialog, ConfirmCardReact ToastProviderHooks useToast

No demo page yet.

Other guides: Screens · Overlays · Navigation · Data · Input · Reading · Agents and live work

Generated from the when.ts beside each component — the same data the Claude Code plugin reads.