---
title: ProgressBar
description: A bar that shows determinate, indeterminate, or segmented progress.
category: Feedback
status: beta
since: 0.3.4
tags: [progress, bar, loading]
syncStatus: reviewed
verified: true
---

## Usage

### States
`status` sets the status color; `success` marks completion and `loading` marks work of unknown duration.
:::TuffDemoWrapper{demo="ProgressBarStatefulProgressDemo" code-lang="vue"}
---
code: |
  <template>
    <TxProgressBar :percentage="32" show-text />
    <TxProgressBar :percentage="68" status="warning" show-text />
    <TxProgressBar success message="Done" />
    <TxProgressBar loading message="Syncing" />
  </template>
---
:::

### Upload Progress
`textPlacement="top"` puts a text row with `detail` above the track; `flowEffect="stardust"` drifts star points over a flat or gradient fill.
:::TuffDemoWrapper{demo="ProgressBarUploadDemo" code-lang="vue"}
---
code: |
  <template>
    <TxProgressBar
      :percentage="percentage"
      :format="p => `Uploading ${p}%`"
      detail="1.4 MB of 2.3 MB"
      aria-label="Uploading report.pdf"
      show-text
      text-placement="top"
      height="6px"
      flow-effect="stardust"
    />
    <TxProgressBar
      :percentage="percentage"
      aria-label="Uploading report.pdf"
      height="6px"
      color="linear-gradient(90deg, #3b82f6, #a855f7)"
      flow-effect="stardust"
    />
  </template>
---
:::

### Segments
Hovering a segment shows its `label` and its share of `segmentsTotal`; leave room above the bar for the tip.
:::TuffDemoWrapper{demo="ProgressBarSegmentsDemo" code-lang="vue"}
---
code: |
  <script setup lang="ts">
  const segments = [
    { value: 25, color: 'linear-gradient(90deg, #60a5fa, #34d399)', label: 'Video' },
    { value: 18, color: 'linear-gradient(90deg, #a78bfa, #f472b6)', label: 'Images' },
    { value: 12, color: 'linear-gradient(90deg, #fb7185, #f59e0b)', label: 'Documents' },
  ]
  </script>

  <template>
    <TxProgressBar :segments="segments" :segments-total="100" height="8px" />
  </template>
---
:::

### Operations Panel
Combined with metric cards and status badges to show dashboard health.
:::TuffDemoWrapper{demo="ComponentsOperationsStatusDemo" code-lang="vue"}
---
code: |
  <template>
    <TxProgressBar :percentage="86" status="success" height="10px" show-text flow-effect="shimmer" mask-variant="dashed" />
    <TxProgressBar :percentage="72" status="warning" height="10px" show-text flow-effect="wave" />
    <TxProgressBar :percentage="48" height="10px" show-text indicator-effect="sparkle" />
  </template>
---
:::

### Status Panel
:::TuffDemoWrapper{demo="ProgressBarStatusPanelDemo" code-lang="vue"}
---
code: |
  <template>
    <TxProgressBar :percentage="80" show-text message="Uploading" />
    <TxStatusBadge text="In progress" status="warning" />
  </template>
---
:::

### Best Practices

- Use `percentage` only when progress is known; use `loading` or `indeterminate` when the duration is unknown.
- On completion, pass `success` with a short `message` instead of faking 100%.
- Keep `message` short because it doubles as the accessible name; put upload and download amounts in `detail` with `textPlacement="top"`.
- Give every segment a `label`, and set `segmentsTotal` when segments cover only part of a total.
- Reserve flow effects for high-value progress; too much shimmer, wave, or stardust makes a dashboard noisy.

## API Reference

### Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `loading` | `boolean` | `false` | Indeterminate loading mode. |
| `indeterminate` | `boolean` | `false` | Indeterminate mode that doesn't imply loading. |
| `indeterminateVariant` | `'classic' \| 'sweep' \| 'bounce' \| 'elastic' \| 'split'` | `'sweep'` | Animation for loading / indeterminate states. |
| `error` | `boolean` | `false` | Error state; overrides `status`. |
| `success` | `boolean` | `false` | Success state; overrides `status`. |
| `status` | `'success' \| 'error' \| 'warning' \| ''` | `''` | Status color. |
| `message` | `string` | `''` | Visible text that also serves as the accessible name. |
| `detail` | `string` | `''` | Secondary copy, shown only with `textPlacement="top"`; never part of the accessible name. |
| `ariaLabel` | `string` | `''` | Accessible name; falls back to `message`, then `'Progress'`. |
| `percentage` | `number` | `0` | Determinate value, clamped to `0..100`. |
| `segments` | `ProgressSegment[]` | - | Multi-segment progress data. |
| `segmentsTotal` | `number` | `100` | Total used for the filled width when `segments` is set. |
| `height` | `string` | `'5px'` | Bar height. |
| `showText` | `boolean` | `false` | Shows percentage text for determinate progress. |
| `textPlacement` | `'inside' \| 'outside' \| 'top'` | `'inside'` | Text position; `top` puts a text row with `detail` above the track. |
| `format` | `(percentage: number) => string` | - | Custom percentage text. |
| `flowEffect` | `'none' \| 'shimmer' \| 'wave' \| 'stardust' \| 'particles'` | `'none'` | Fill effect; `particles` is a deprecated alias of `stardust`. Ignored for `segments`. |
| `indicatorEffect` | `'none' \| 'sparkle'` | `'none'` | Endpoint effect once progress is above zero. |
| `hoverEffect` | `'none' \| 'glow'` | `'none'` | Wrapper hover effect. |
| `color` | `string` | - | Custom fill color over the status color; gradient strings are used as-is. |
| `maskVariant` | `'solid' \| 'dashed' \| 'plain'` | `'plain'` | Track rim; `plain` draws none. |
| `maskBackground` | `'none' \| 'blur' \| 'glass' \| 'mask'` | `'none'` | Track mask layer; `none` renders no mask node. |
| `tooltip` | `boolean` | `false` | Shows a tooltip with the resolved text. |
| `tooltipContent` | `string` | - | Overrides the tooltip content. |
| `tooltipProps` | `Partial<TooltipProps>` | - | Props forwarded to `TxTooltip`. |

### Events

| Event | Payload | Description |
|------|---------|-------------|
| `complete` | - | Fires once per completion cycle when progress reaches `100`; fires again after it drops and completes again. |

### Types

`ProgressSegment`:

| Field | Type | Description |
|------|------|-------------|
| `value` | `number` | Segment value; only positive finite values render. |
| `color` | `string` | Segment fill; falls back to the bar's fill color. |
| `label` | `string` | Precedes the share in the hover tip (`Video · 25%`); without it the tip shows the share alone. |

## Overview

- The track is `role="progressbar"` (`aria-valuemin="0"`, `aria-valuemax="100"`); `aria-valuenow` is the clamped value and is omitted while `loading` or `indeterminate`.
- Text resolves from `message`, then `format`, then the rounded percentage. It shows only with `message` or `showText`, and only `message` shows while `loading` or `indeterminate`.
- When `success` or `error` has a `message` and `percentage` is `0`, the fill width resolves to `100%`.
- Segments skip non-positive values: the overall fill uses `segmentsTotal`, and widths inside it normalize by the positive sum.
- Width changes ease over 480ms; indeterminate animations touch only `transform` and `opacity`, and stop under reduced motion.

## Technologies

- The fill defaults to a faded-to-saturated `linear-gradient`, and the tip glow shows only strictly between 0% and 100%; a gradient `color` gets a white glow.
- The `hoverEffect="glow"` shadow and `indicatorEffect="sparkle"` sparks sit inside the `overflow: hidden` track and are clipped to its height.
- Source: `packages/tuffex/packages/components/src/progress-bar/`.

<TuffDocSourceLink />
