Progress Bar

Known or unknown completion of an ongoing task.

Uploading60%

Progress Bar communicates completion of an ongoing task. Use Meter for a scalar measurement such as storage usage. The component is read-only; cancellation or retry actions belong in separate controls.

Anatomy

1234
Uploading60%
  1. 1 Label — names the task and also supplies the accessible name.
  2. 2 Percentage — optional visible rounded progress for a determinate task.
  3. 3 Track — the complete 0–100 range.
  4. 4 Fill — completed progress, or an animated indicator when the amount is unknown.

Options

Progress states

Uploading60%
Determinate
Processing
Indeterminate
Uploading0%
Not started · zero
Upload complete100%
Complete

Use determinate progress only when a meaningful completion value is available. An indeterminate indicator has no numeric percentage.

Variants

Default
Default
Positive
Positive
Negative
Negative

A variant changes appearance; it does not mark a task complete, pause it or report an error automatically. Update the label and surrounding message to explain the task state.

Sizes

Uploading
Small
Uploading
Medium · default
Uploading
Large

Container scaling

Use the Scale switch beside Light/Dark in the preview above, or set data-scale="small|medium|large" on a containing element. Font size, line height, spacing and radii inherit that context. A local size="sm" remains smaller within the chosen context; it does not cancel the container scale. Track/indicator dimensions and border widths keep their existing local-size behavior.

Uploading
Container small
Uploading
Container medium
Uploading
Container large

The default context is medium. Nested containers can replace the inherited context explicitly, without multiplying the parent context again. Brand and light/dark mode remain independent. The current adopters are Status Light, Meter and Progress Bar; existing components have not been migrated implicitly.

Table of options

Custom ElementNunjucksValues and defaults
valuevalueFinite completion value, clamped to 0–100. Omitted or empty by default: indeterminate. Numeric 0 is determinate.
labellabelVisible task text and accessible name. Default: empty; the accessible fallback is Progress or Loading. Supply a task-specific label.
show-valueshowValueBoolean. Default: false. Shows the rounded percentage only for determinate progress.
indeterminateindeterminateBoolean. Default: false. Forces unknown progress even when value is present.
variantvariantdefault (default), positive or negative.
sizesizesm, md (default) or lg, relative to container scale.

Custom Element booleans are enabled by attribute presence. Omit show-value or indeterminate to turn them off; writing indeterminate="false" still enables it. Macro booleans use actual true/false arguments.

Behaviors

Uploading60%

Determinate updates

Changing value updates the fill, accessible current value and optional percentage. Finite values outside 0–100 are clamped.

Processing

Unknown amount

Missing, empty or non-finite Custom Element values produce indeterminate progress. No aria-valuenow or visible percentage is emitted.

Processing

Reduced motion

The indeterminate animation stops when reduced motion is requested. This example shows the static result regardless of your system setting. The indicator remains visible and keeps unknown-value semantics.

Switch from unknown progress by removing indeterminate and setting a finite value. At 100 the component remains visible; the consuming workflow decides when to replace it with a completion message. It does not emit completion events or remove itself.

Usage guidelines

Uploading photos60%

Do

Name the task and show a percentage when it is based on meaningful progress.

Estimating progress50%

Don't

Do not invent a percentage while the amount of work is unknown. Use an indeterminate indicator instead.

Keep cancellation and retry controls outside the progressbar. Use a nearby message to explain failures; a negative fill alone is not an error explanation.

Content standards

  • Use task-specific wording, such as “Uploading photos” or “Preparing download”.
  • Keep the label stable while the percentage changes.
  • Do not promise a remaining duration unless the application can estimate it reliably.
  • For completion or failure, provide a clear outcome in nearby text.

Keyboard interactions

Progress Bar has no keyboard commands and does not enter the tab order. Related cancel, retry or navigation actions need separate buttons or links.

Accessibility

  • The root has role="progressbar" and a task name supplied through aria-label.
  • Determinate progress exposes aria-valuemin="0", aria-valuemax="100" and aria-valuenow.
  • Indeterminate progress omits aria-valuenow and the visible numeric percentage.
  • A progressbar is not an automatic live region. If completion must be announced, use a separate, appropriately timed status message rather than announcing every percentage change.
  • Reduced-motion preference disables the indeterminate animation.

Implementation


import "ui-foundations/elements/ui-progress-bar";


<uif-progress-bar id="upload-progress" value="0"
  label="Uploading photos" show-value></uif-progress-bar>


const progress = document.querySelector("#upload-progress");
progress.setAttribute("value", "60");

// Unknown work amount: no percentage is exposed.
progress.setAttribute("indeterminate", "");

// Resume known progress.
progress.removeAttribute("indeterminate");
progress.setAttribute("value", "75");

For static HTML without Custom Element JavaScript:


{% import "macros/ui.njk" as uif %}
{{ uif.progressBar(value=0, label="Uploading photos", showValue=true) }}
{{ uif.progressBar(label="Preparing download", indeterminate=true) }}

The macro emits the progressbar, optional header and styled track/fill. Pass finite numbers or an empty value to the macro. Both interfaces use the same CSS pattern; changes to static markup must keep its fill value and accessible current value aligned.

The scale belongs to the container, not to the component's size attribute:


<div data-scale="large">
  <uif-progress-bar size="sm" label="Uploading" value="60"></uif-progress-bar>
</div>

Theming

Use the brand and mode switches in the preview above. Visual values come from the pattern's --uif-progress-bar-* slots and existing Semantic roles. Labels use semantic content color. An inward outline keeps colored markers or fills discernible across light and dark surfaces.

Set data-brand="a", "b" or "c" and data-mode="light" or "dark" on the root element. Consumers own activation of these contexts. See Design Tokens.

Tokens

Use container scale and local size for typography and spacing. The table lists component overrides.

Token
--uif-progress-bar-border-radius
--uif-progress-bar-fill-default
--uif-progress-bar-fill-negative
--uif-progress-bar-fill-positive
--uif-progress-bar-gap
--uif-progress-bar-height-lg
--uif-progress-bar-height-md
--uif-progress-bar-height-sm
--uif-progress-bar-label-color
--uif-progress-bar-track-background

Design checklist

✓
Runtime and examplesCSS, Custom Element, static macro and playground are implemented.
✓
Bounded browser checksUpdates, semantics and text/visible-boundary contrast checked across three brands and two modes.
○
Figma parity and Code ConnectLive source access is unavailable. Design parity is unverified and mapping examples are inactive.

The browser checks cover specific Runtime behavior and contrast pairs; they do not certify complete accessibility or live design parity.