Skip to content

Progress

A progress bar component that communicates the completion status of a task to sighted users and screen readers.

Export data
x

Usage guidelines

  • Use Progress for task completion that changes over time (uploads, downloads, installations). For static measurements of a known range, prefer Meter.
  • Set value to null to render an indeterminate bar for tasks whose completion rate is unknown. The root exposes the data-indeterminate attribute so you can style a looping animation in CSS.
  • Provide an accessible name via <ProgressLabel> or aria-label / aria-labelledby on <ProgressRoot>. Without a label, screen readers only announce the raw percentage.
  • The default value is treated as a percentage (0–100). When format is supplied, the raw value is passed to Intl.NumberFormat instead; make sure min / max still describe the same scale.

Anatomy

Import the component and assemble its parts:

vue
<script setup lang="ts">
import {
  ProgressIndicator,
  ProgressLabel,
  ProgressRoot,
  ProgressTrack,
  ProgressValue,
} from 'base-ui-vue'
</script>

<template>
  <ProgressRoot :value="40">
    <ProgressLabel>Export data</ProgressLabel>
    <ProgressValue />
    <ProgressTrack>
      <ProgressIndicator />
    </ProgressTrack>
  </ProgressRoot>
</template>

Examples

Indeterminate progress

Set value to null when the completion rate is not known. The root, track, and indicator all receive a data-indeterminate attribute that you can target from CSS:

vue
<ProgressRoot :value="null">
  <ProgressLabel>Syncing</ProgressLabel>
  <ProgressTrack>
    <ProgressIndicator />
  </ProgressTrack>
</ProgressRoot>

Formatting the value

Pass Intl.NumberFormat options via the format prop to render the raw value in a different unit. When format is provided, the same formatted string is also used as aria-valuetext:

vue
<ProgressRoot :value="750" :max="1000" :format="{ style: 'unit', unit: 'megabyte' }">
  <ProgressLabel>Uploaded</ProgressLabel>
  <ProgressValue />
  <ProgressTrack>
    <ProgressIndicator />
  </ProgressTrack>
</ProgressRoot>

Custom screen-reader text

Use get-aria-value-text to produce a human-readable announcement for assistive technology. It receives the formatted value (or null when indeterminate) and the raw value:

vue
<ProgressRoot
  :value="60"
  :get-aria-value-text="(formatted, value) => value == null ? 'Still working…' : `${formatted} complete`"
>
  <ProgressLabel>Upload</ProgressLabel>
  <ProgressTrack>
    <ProgressIndicator />
  </ProgressTrack>
</ProgressRoot>

Custom value rendering

ProgressValue exposes the formatted and raw values through its default slot. The formattedValue slot prop is the string "indeterminate" when the value is null:

vue
<ProgressRoot :value="80">
  <ProgressValue v-slot="{ formattedValue, value }">
    <strong v-if="value == null">working…</strong>
    <template v-else>
      <strong>{{ formattedValue }}</strong>
    </template>
  </ProgressValue>
</ProgressRoot>

API reference

Root

Groups all parts of the progress bar and provides the task completion status to screen readers. Renders a <div> element.

PropTypeDefaultDescription
valuenumber | nullThe current value of the progress bar. Pass null for an indeterminate bar. Required.
minnumber0The minimum allowed value.
maxnumber100The maximum allowed value.
formatIntl.NumberFormatOptionsundefinedOptions to format the value. When omitted, the value is formatted as a percentage of 100.
localeIntl.LocalesArgumentundefinedThe locale used by Intl.NumberFormat when formatting the value. Defaults to the user's runtime locale.
aria-valuetextstringundefinedA string value that provides a user-friendly name for aria-valuenow. Takes precedence over get-aria-value-text.
get-aria-value-text(formattedValue: string | null, value: number | null) => stringundefinedA function that returns a string value for aria-valuetext. Receives null for the formatted value when indeterminate.
asstring | Component'div'Allows you to replace the component's HTML element with a different tag or component. Pass Slot for renderless mode.
classany | ((state: State) => any)undefinedCSS class applied to the element, or a function that returns a class based on the component's state.
styleStyleValue | ((state: State) => StyleValue)undefinedStyle applied to the element, or a function that returns a style object based on the component's state.
State propTypeDescription
status'indeterminate' | 'progressing' | 'complete'The current status, derived from value / max. Exposed as a data attribute (see below).
AttributeDescription
roleDefaults to "progressbar" (can be overridden by user attributes).
aria-valuenowReflects the current value. Omitted when indeterminate.
aria-valueminDefaults to min (can be overridden by user attributes).
aria-valuemaxDefaults to max (can be overridden by user attributes).
aria-valuetextThe human-readable value announced by screen readers.
aria-labelledbyPoints to the <ProgressLabel> id when one is rendered.
data-progressingPresent while determinate progress is not complete.
data-completePresent when the value equals max.
data-indeterminatePresent when the value is null (or non-finite).

Label

An accessible label for the progress bar. Its id is automatically wired to the root's aria-labelledby. Renders a <span> element.

PropTypeDefaultDescription
idstringundefinedThe id of the label element. When provided, it overrides the automatically generated one.
asstring | Component'span'Allows you to replace the component's HTML element with a different tag or component. Pass Slot for renderless mode.
classany | ((state: State) => any)undefinedCSS class applied to the element, or a function that returns a class based on the component's state.
styleStyleValue | ((state: State) => StyleValue)undefinedStyle applied to the element, or a function that returns a style object based on the component's state.

Value

A text element displaying the current value. Hidden from assistive technology with aria-hidden because the root already exposes aria-valuetext. Renders a <span> element.

When the progress is indeterminate, the default slot content is an empty string.

PropTypeDefaultDescription
asstring | Component'span'Allows you to replace the component's HTML element with a different tag or component. Pass Slot for renderless mode.
classany | ((state: State) => any)undefinedCSS class applied to the element, or a function that returns a class based on the component's state.
styleStyleValue | ((state: State) => StyleValue)undefinedStyle applied to the element, or a function that returns a style object based on the component's state.
Slot propTypeDescription
formattedValuestring | 'indeterminate'The formatted current value. Equals the string "indeterminate" when the root value is null.
valuenumber | nullThe raw numeric current value, or null when indeterminate.

Track

Contains the progress indicator. Renders a <div> element.

Must be rendered inside <ProgressRoot>, otherwise it throws at render time.

PropTypeDefaultDescription
asstring | Component'div'Allows you to replace the component's HTML element with a different tag or component. Pass Slot for renderless mode.
classany | ((state: State) => any)undefinedCSS class applied to the element, or a function that returns a class based on the component's state.
styleStyleValue | ((state: State) => StyleValue)undefinedStyle applied to the element, or a function that returns a style object based on the component's state.

Indicator

Visualizes the completion status of the task. When determinate, its default styles set inset-inline-start: 0, height: inherit, and width: <percentage>%. When indeterminate, no inline styles are applied — use CSS to drive a looping animation (the data-indeterminate attribute is available on every Progress part). Renders a <div> element.

PropTypeDefaultDescription
asstring | Component'div'Allows you to replace the component's HTML element with a different tag or component. Pass Slot for renderless mode.
classany | ((state: State) => any)undefinedCSS class applied to the element, or a function that returns a class based on the component's state.
styleStyleValue | ((state: State) => StyleValue)undefinedStyle applied to the element, or a function that returns a style object based on the component's state.