Skip to main content

Design system components

Progress

Linear progress indicator with determinate and indeterminate modes.

Status: stable. Group: feedback. Markdown version: /design-system/components/progress.md

When to use

Progress is the linear bar for work with visible movement: pass value (against max, default 100) when completion is measurable, or indeterminate when the duration is unknown but you want a bar-shaped affordance (e.g. a full-width page or panel load). The state prop recolors the fill semantically; success for a finished upload, error for a failed one. Rule of thumb across the loading family: Spinner for sub-second unknown waits, Progress for known or long-running work, Skeleton for placeholder layouts.

When not to use

  • Do not use Progress as a skeleton or layout placeholder; Skeleton owns loading layouts.
  • Do not leave the generic default "Progress" aria-label on user-facing bars; name the work being done.
  • Do not use Progress as a placeholder for content that is loading; Skeleton mirrors the layout; Progress claims measurable work.

Look-alikes

  • Skeleton: Do not use Progress as a skeleton or layout placeholder; Skeleton owns loading layouts.
  • Spinner: Do not use Spinner for waits you can measure or that routinely exceed a couple of seconds; that is Progress territory.

Props

Progress props
PropTypeDefaultDescriptionRequired
valuenumber0Current progress value, scaled against max and clamped to 0..max.No
maxnumber100Maximum value.No
labelstringnoneAccessible name for the progressbar. Defaults to the translated "Progress" (progress.label).No
size"sm" | "md" | "lg"mdTrack height token.No
state"info" | "success" | "warning" | "error" | "neutral"neutralSemantic fill color.No
indeterminatebooleanfalseUnknown duration: animates a sweeping bar and drops aria-valuenow.No
classNamestringnoneOptional utility classes on the root.No

Variants

  • Available sizes: sm, md, lg (default md).
  • Allowed state values: info, success, warning, error, neutral (default neutral).

Invalid combinations

  • SHOULD NOT: When indeterminate is true, then do not set value. An indeterminate bar drops aria-valuenow and ignores value. Pass value only for determinate progress.

Keyboard

The contract records no keyboard interaction.

Rules

Every item under When not to use is a MUST NOT. MUST and SHOULD follow RFC 2119.

Progress rules
LevelRuleHow it is checked
SHOULD NOTWhen indeterminate is true, then do not set value. An indeterminate bar drops aria-valuenow and ignores value. Pass value only for determinate progress.Checked by the MCP tool validate_component_usage (rule progress-indeterminate-ignores-value). Also enforced in code: Progress.tsx: aria-valuenow and scale are skipped when indeterminate.
MUSTARIA: Role=progressbar with aria-valuemin/aria-valuemax.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTARIA: Aria-valuenow is value clamped to 0..max and rounded, matching the visual fill; omitted in indeterminate mode.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTARIA: Aria-label from the label prop, which defaults to the translated "Progress" (progress.label)Not yet verified: no evidence record. WCAG 4.1.2.
MUSTRequired stories produce no axe violations at the configured severity.Automated by npm run test:stories:matrix:ci. WCAG 2.5.8.
MUSTThe accessibility tree (role, name, state) matches the committed snapshot for every required story.Automated by npm run test:stories:matrix:ci. WCAG 1.3.1, 4.1.2.
MUSTThe component remains legible and operable under a real browser forced-colors: active pass.Automated by npm run test:stories:hc.
MUSTA human completed an end-to-end accessibility review of this component.Manual review, last on 2026-11-04.
SHOULDName the work in the label prop ("Upload progress", "Profile completeness"); it is the aria-label AT users hear.Not stated in the contract.
SHOULDSwitch state to success or error at completion so the outcome is visible without reading numbers.Not stated in the contract.
SHOULDUse indeterminate for unknown durations that deserve a bar (panel or page loads); the sweep keeps motion under reduced-motion by slowing, not freezing.Not stated in the contract.
SHOULDPair the bar with a visible Text value or label when precision matters; the bar alone communicates proportion, not numbers.Not stated in the contract.
SHOULD NOTDo not animate value backwards or reset it mid-task; regressing progress reads as an error even when it is not.Not stated in the contract.

Install and import

  • Install: npm install @digitaltableteur/react (version 0.9.1, restricted access on npm).
  • Import: import { Progress } from "@digitaltableteur/react";
  • Entry point: @digitaltableteur/react/feedback exports it too.
  • Styles: import @digitaltableteur/react/style.css once at the app boundary.
  • Also available as the custom element <dt-progress>; see the custom elements manifest.