Show what is in progress and preserve useful context while an operation runs.
Loading feedback explains that work is continuing. Place it near the action or region it describes and keep unrelated content usable when possible. The application decides when work begins, what progress means, and when the operation has actually finished.
Use Button loading for a pending action and ProgressIndicator for a content region or longer operation. Button suppresses activation while loading but does not await its callback or manage the request. ProgressIndicator is a display, not a task runner.
| Information available | ProgressIndicator configuration |
|---|---|
| Work is happening but completion is unknown | Omit value for the default circular indicator |
| A bar is needed before measurable progress is available | variant="linear" without value |
| A measured fraction is available | variant="linear" with value from 0 to 1 |
An explicit circular variant remains indeterminate even when given a value. A linear value of 0.4 represents 40 percent; do not pass 40. Do not invent progress by incrementing a timer when the service does not report it.
Figure in preparation
Loading: component composition
Activity, measured progress, and a pending action compared.
If progress will become measurable, an initially indeterminate linear indicator can retain its shape when a value arrives. Reserve enough room for the label and result so the task does not jump as feedback changes.
Separate initial loading from refreshing existing information. During refresh, retain usable previous content where appropriate and identify it as previous data if freshness matters. Avoid treating a temporarily empty response buffer as a completed empty collection.
Cancellation requires an application operation. A Cancel Button does not abort a request by itself, and dismissing the loading presentation does not necessarily stop work. Explain whether completed portions are retained and whether retry resumes or restarts.
If a request fails, preserve recoverable input and clear pending state. If the outcome is unknown, reconcile it before allowing a duplicate operation. Do not leave a spinner running indefinitely after the application already knows it cannot make progress.
Name the task: “Uploading report” is more informative than “Please wait.” Show a percentage only when it represents the actual scope of work. If upload is followed by processing, name those stages so 100 percent uploaded is not confused with completed processing.
Give ProgressIndicator an accessible name through aria-label or aria-labelledby. Its root exposes progressbar semantics, with a value only for determinate linear progress. A progressbar alone is not a guarantee that every update will be announced; provide concise status feedback when the task needs it.
Keep keyboard focus stable while work runs and avoid blocking unrelated actions. Review reduced motion, both themes, and long labels. Do not make cancellation or recovery depend on reading animation or color.
See ProgressIndicator and Button. Use Empty states for known absence and Notifications for outcomes.