Components/ProgressBar

ProgressBar

Determinate, indeterminate, segmented, and stateful progress feedback.

VerifiedSince 0.3.4

Usage

Stateful Progress

Loading demo...

Upload progress

:::TuffDemoWrapper{demo="ProgressBarUploadDemo" code-lang="vue" description="The text row sits above the track: the label takes the fill colour and detail is muted behind a separator dot. The default track has no rim, the fill fades in toward the tip, and the tip carries a soft glow. flow-effect=\"stardust\" drifts two depths of white star points over the fill, the near layer twinkling; it sits on a flat colour or on your own gradient alike, and a gradient bar's tip glow turns white to match."}

code: |

<script>
  import { ref } from 'vue'

  const percentage = ref(65)
  </script>

Segments

Hover a segment: it lifts, its neighbours dim, and a tip shows the segment's `label` with its share of `segmentsTotal`. Leave room above the bar for the tip.

Loading demo...

Dashboard Operations Progress

Operations status panel

Progress bars combine with metric cards and status badges to express dashboard health.

Loading demo...

Status Panel

Loading demo...

Best Practices

  • Use percentage only for known progress. Use loading or indeterminate when duration is unknown.
  • Do not fake 100% for success states; pass success with a message when the operation is complete.
  • Keep message short because it is also used for the progressbar accessible label.
  • Use segmentsTotal to keep segmented bars honest when segments represent a partial total.
  • Reserve animated effects for high-value progress moments; excessive shimmer/wave/stardust usage makes dashboards noisy.
  • Give every segment a label: the hover tip is the only place a segmented bar explains what each colour stands for.
  • The default is a flat, rimless track. Pass maskBackground explicitly (with maskVariant="solid" for a rim) when you need a blurred or glass track instead of relying on the old default.
  • For uploads and downloads with a known size, put the "how much so far" copy in textPlacement="top" + detail rather than in message, which doubles as the accessible name.

API Reference

Props

PropTypeDefaultDescription
loadingbooleanfalseIndeterminate loading mode.
indeterminatebooleanfalseIndeterminate progress mode without implying loading.
indeterminateVariant'classic' | 'sweep' | 'bounce' | 'elastic' | 'split''sweep'Animation variant for loading/indeterminate states.
errorbooleanfalseError state. Overrides status.
successbooleanfalseSuccess state. Overrides status.
status'success' | 'error' | 'warning' | ''''Visual status tone.
messagestring''Visible/accessible text label.
detailstring''Secondary copy such as 1.4 MB of 2.3 MB. Rendered only under textPlacement="top"; never part of the accessible name.
percentagenumber0Determinate progress value before clamping.
segmentsProgressSegment[]-Multi-segment progress data.
segmentsTotalnumber100Total used to compute filled width when segments are present.
heightstring'5px'Progress bar height.
showTextbooleanfalseShow percentage text for determinate progress.
textPlacement'inside' | 'outside' | 'top''inside'Location for message/percentage text; top renders a text row (with optional detail) above the track.
format(percentage: number) => string-Custom percentage formatter.
flowEffect'none' | 'shimmer' | 'wave' | 'stardust' | 'particles''none'Determinate fill overlay effect. stardust drifts two depths of white star points over the fill; particles is its deprecated alias. Ignored for segments.
indicatorEffect'none' | 'sparkle''none'Endpoint indicator effect when progress is greater than zero.
hoverEffect'none' | 'glow''none'Wrapper hover effect.
colorstring-Custom fill color. Overrides state color.
maskVariant'solid' | 'dashed' | 'plain''plain'Track rim style; plain draws no rim.
maskBackground'none' | 'blur' | 'glass' | 'mask''none'Track mask layer; none renders no mask node and leaves the track a flat tint.
tooltipbooleanfalseEnable tooltip using resolved text.
tooltipContentstring-Tooltip content override.
tooltipPropsPartial<TooltipProps>-Extra props forwarded to TxTooltip.

ProgressSegment

FieldTypeDescription
valuenumberSegment value. Only positive finite values render.
colorstringSegment fill color. Falls back to progress fill color.
labelstringShown in the segment's hover tip ahead of its share (Video · 25%); without it the tip shows the share alone.

Events

EventPayloadDescription
complete-Emitted once per completion cycle when resolved progress reaches 100.

Slots

SlotPropsDescription
--TxProgressBar does not expose slots. Use message, format, tooltipContent, and tooltipProps for labels and tooltip content.

Overview

  • The track renders role="progressbar" with aria-valuemin="0" and aria-valuemax="100".
  • Determinate progress clamps percentage to 0..100 and exposes it as aria-valuenow.
  • loading and indeterminate omit aria-valuenow; use message to describe the work.
  • error and success boolean props take precedence over status.
  • When success or error has a message and percentage is 0, the visual width resolves to 100% for completion-style labels.
  • message wins over format, and format wins over the default rounded percentage text.
  • Text renders only when message is present or showText=true; loading/indeterminate states only show text when message is present. textPlacement="top" follows the same rule as outside and renders the text row above the track.
  • detail renders only under textPlacement="top", after the label and muted behind a separator dot. It is visible text and never enters the progressbar's accessible name (still ariaLabel > message > Progress).
  • The default track is a flat 10% tint of the text colour: no .tx-progress-bar__mask node and no rim. maskVariant="solid" | "dashed" draws the rim; the mask layer renders only when maskBackground is not 'none'.
  • The fill defaults to linear-gradient(90deg, faded → saturated); a color that is already a gradient string is used verbatim. .tx-progress-bar__glow is mounted for every determinate bar that is not segmented, sits outside the track's clipping, and is visible only strictly between 0% and 100%. A gradient color has no single hue, so its glow is white and the top label falls back to the text colour (--tx-progress-glow, --tx-progress-accent).
  • flowEffect="stardust" draws two white point fields over the fill (::before far, small and slow; ::after near, larger, faster and twinkling), each tiling by whole tile widths so the drift never shows a seam. Points are sized in px, so a 5px and a 14px bar get the same grain. 'particles' is a deprecated alias that renders the same layers. No flow effect draws over segments or while indeterminate.
  • Width changes ease over 480ms on --tx-ease-out-strong; the five indeterminate sweeps animate composited properties only (transform, plus opacity on split), never left or width, and stop under prefers-reduced-motion. The travelling sweeps (sweep, classic, elastic) run linear and start and end fully off the track, so the loop point is never on screen and the bar never appears to stall.
  • segments ignore non-positive values. The filled width uses segmentsTotal; segment widths inside the fill normalize by the sum of positive segment values. Each segment paints its colour on an inner .tx-progress-bar__segment-fill and carries a data-tip of label · share% (share of segmentsTotal, or the share alone without a label). On hover the fill scales up, the other segments dim, and the tip rises above the bar; a segmented track sets overflow: visible to give the lift room.
  • complete emits once when resolved progress reaches 100, and can emit again after progress drops below 100 and completes again.
  • tooltip or tooltipContent wraps the bar in TxTooltip; tooltipProps are forwarded to that tooltip.

Technologies

  • Reviewed against packages/tuffex/packages/components/src/progress-bar/src/types.ts, TxProgressBar.vue, and progress-bar.test.ts.
  • Existing tests cover determinate clamping, progressbar ARIA state, indeterminate aria-valuenow omission, complete once-per-cycle emission, and segment normalization by positive segment sum.
  • Verified coverage (2026-09 redesign): no mask node by default and no --bg-* wrapper class; --tx-progress-fill is linear-gradient(90deg, …) and a gradient color passes through verbatim; the glow node sits outside the track and is hidden or absent at 0% / 100% / indeterminate / segments; the top text row's label / detail rendering and visibility rules; every @keyframes tx-progress-* block is free of left / width (with a positive control on the extractor); sweeps stop under prefers-reduced-motion.
  • Verified coverage (stardust and segment hover): stardust classes the fill and particles resolves to the same class; no flow class over segments or while indeterminate; a gradient color keeps the glow and sets --tx-progress-glow: #fff; segment tips are built from label and the share of segmentsTotal (not of the segment sum) in both templates; the colour sits on the inner fill node; the travelling sweeps are infinite linear and elastic starts at -100% and ends at 454.5%; the stardust layers drift by exactly their tile widths and never read --tx-progress-color; the segmented track is overflow: visible.
  • Known and left in place: the hoverEffect="glow" box-shadow and the indicatorEffect="sparkle" sparks both live inside the overflow: hidden track and get clipped to its height; the source carries comments marking both.
  • API note: segments use positive values only. The outer fill width is based on segmentsTotal, while widths inside the fill normalize by the positive segment sum.
  • Accessibility note: keep message short and status-specific because it is used as the accessible progress label.
  • Component source: packages/tuffex/packages/components/src/progress-bar/src/TxProgressBar.vue.
  • Types: packages/tuffex/packages/components/src/progress-bar/src/types.ts.
  • Verified coverage: packages/tuffex/packages/components/src/progress-bar/__tests__/progress-bar.test.ts verifies determinate clamping and ARIA state, indeterminate aria-valuenow omission, once-per-cycle complete emits, segment normalization by positive segment sum, the redesign (no mask node by default, gradient fill and glow placement, the top text row, layout-free keyframes and the reduced-motion stop), the stardust flow (class, alias, white glow for gradients, seamless tile drift) and the segment hover (tips, inner fill, visible overflow, linear sweeps).
查看源码
packages/tuffex/packages/components/src/progress-bar/index.ts