Feedback/Progress

Progress

Displays an indicator showing the completion progress of a task.

Themed

When to Use

Use Progress when you need to:

  • Show completion status of a task like file upload, download, or form submission
  • Indicate loading progress when the duration is known or estimable
  • Display step-by-step progress through a multi-part workflow
  • Visualize capacity or quota usage (storage, bandwidth, etc.)
  • Provide visual feedback during background operations

When Not to Use

  • Unknown duration without any progress data — use Spinner instead
  • Content placeholder while loading — use Skeleton instead
  • User-adjustable numeric ranges — use Slider instead
  • Brief operations under 1 second — avoid progress indicators entirely

Default

Progress bar with animated value change on mount.

Different Values

Progress bars at various completion levels from 25% to 100%.

25%
50%
75%
100%

Indeterminate

When the progress amount is unknown, omit the value prop for an indeterminate state.

Custom Sizes

Adjust the track height using className. The default is h-2.

Thin (h-1)
Default (h-2)
Medium (h-3)
Thick (h-4)

With Label

Pair the progress bar with a label and percentage for clear user feedback.

Uploading...0%

Animated Steps

Progress bar cycling through discrete step values with built-in transition animation.

Step 1 of 50%

UX & Design Guidelines

Visual Hierarchy

Use the default bg-primary indicator color for standard progress. Pair with a text label showing the percentage or step count so users can gauge remaining time. Avoid stacking multiple progress bars without clear labels differentiating each one.

Spacing & Layout

Place progress bars at full width within their container using w-full. Add gap-2 between the label and bar. In card layouts, position the progress bar at the bottom of the card content for natural reading flow.

Responsive Behavior

Progress bars scale naturally with container width. On mobile, use a thicker track (h-3 or h-4) for better visibility. Always pair with a numeric percentage label on small screens where the bar alone may be too narrow to convey precise progress.

Color & Contrast

The track uses bg-primary/20 and the indicator uses bg-primary, providing strong contrast in both light and dark modes. Avoid overriding the indicator color without verifying WCAG 2.1 AA contrast against the track background in both themes.

Accessibility

Keyboard Navigation

  • Tab — Move focus to the progress bar (when focusable)
  • Progress is a read-only indicator; no keyboard interaction is expected beyond focus traversal
  • If the progress bar is within a form, Tab will skip to the next interactive element

Screen Reader Support

  • Uses role="progressbar" automatically via Radix UI primitive
  • Announces aria-valuenow, aria-valuemin, and aria-valuemax
  • Use getValueLabel to provide a human-readable description (e.g., "66% complete")
  • Indeterminate state omits aria-valuenow, signaling unknown progress to assistive technology

Live Regions

For progress that updates frequently, wrap the percentage label in an aria-live="polite" region so screen readers announce updates without interrupting the user. Avoid aria-live="assertive" as frequent progress announcements can be disruptive.

Labeling Best Practices

Always provide an accessible name via aria-label or aria-labelledby when the progress bar lacks a visible text label. For multiple progress bars on the same page, each must have a unique accessible name to distinguish them.

ARIA Attributes

{/* Basic progress with accessible label */}
<Progress
  value={66}
  getValueLabel={(value, max) =>
    `${Math.round((value / max) * 100)}% complete`
  }
/>

{/* Progress with visible label and aria-label */}
<div role="group" aria-label="File upload progress">
  <span id="upload-label" className="text-sm">
    Uploading document.pdf
  </span>
  <Progress
    value={45}
    aria-labelledby="upload-label"
  />
</div>

{/* Multiple progress bars with distinct labels */}
<Progress
  value={80}
  aria-label="Storage usage: 80% of 100GB used"
/>

API Reference

The Progress component accepts the following props in addition to standard Radix UI Progress primitive attributes.

PropTypeDefaultDescription
valuenumber | nullnullThe progress value (0-100). Null or omitted shows indeterminate state.
maxnumber100The maximum value for the progress indicator.
getValueLabel(value: number, max: number) => stringA function to return the accessible label text for screen readers.
classNamestringAdditional CSS classes to apply to the progress track.