Appearance
@vibe-labs/design-vue-progress
Vue 3 progress indicators for the Vibe Design System. Linear bars, radial rings, auto-color thresholds, shimmer effects, and ETA estimation.
Installation
ts
import { VibeProgressBar, VibeProgressRing } from "@vibe-labs/design-vue-progress";Requires the CSS layer from @vibe-labs/design-components-progress. The package also ships side-effect CSS (shimmer, inside labels, ring spin) imported automatically from progress-extras.css.
Components
VibeProgressBar
Linear progress bar with label positions, shimmer, stripes, and auto-color.
Usage
vue
<!-- Basic -->
<VibeProgressBar :value="65" />
<!-- With title and above label -->
<VibeProgressBar :value="65" title="Upload" label="above" />
<!-- Inside label -->
<VibeProgressBar :value="80" label="inside" size="lg" />
<!-- Right label -->
<VibeProgressBar :value="42" label="right" />
<!-- Custom label format -->
<VibeProgressBar :value="750" :max="1000" label="above" :format-label="(v, min, max) => `${v} / ${max} MB`" />
<!-- Sizes -->
<VibeProgressBar :value="50" size="xs" />
<VibeProgressBar :value="50" size="sm" />
<VibeProgressBar :value="50" size="md" />
<VibeProgressBar :value="50" size="lg" />
<!-- Color variants -->
<VibeProgressBar :value="80" variant="success" />
<VibeProgressBar :value="50" variant="warning" />
<VibeProgressBar :value="20" variant="danger" />
<!-- Auto-color (changes color based on value) -->
<VibeProgressBar :value="progress" variant="auto" />
<!-- Custom auto thresholds -->
<VibeProgressBar
:value="progress"
variant="auto"
:auto-thresholds="[
{ max: 25, color: 'var(--progress-fill-danger)' },
{ max: 75, color: 'var(--progress-fill-warning)' },
{ max: 100, color: 'var(--progress-fill-success)' },
]"
/>
<!-- Custom color -->
<VibeProgressBar :value="65" color="#7c3aed" />
<!-- Indeterminate -->
<VibeProgressBar indeterminate />
<!-- Striped -->
<VibeProgressBar :value="70" striped />
<!-- Animated stripes -->
<VibeProgressBar :value="70" striped animated />
<!-- Shimmer effect -->
<VibeProgressBar :value="70" shimmer />
<!-- Custom min/max -->
<VibeProgressBar :value="3" :min="0" :max="10" label="above" />
<!-- Chromeless (for composing segmented bars) -->
<VibeProgressBar :value="40" chromeless />Props
| Prop | Type | Default | Description |
|---|---|---|---|
value | number | 0 | Current value |
min | number | 0 | Minimum |
max | number | 100 | Maximum |
size | ProgressSize | "md" | xs · sm · md · lg |
variant | ProgressVariant | "accent" | accent · success · warning · danger · auto |
color | string | — | Custom CSS color (overrides variant) |
autoThresholds | AutoColorThreshold[] | danger→warning→success | Thresholds for variant="auto" |
label | ProgressLabelPosition | "none" | above · inside · right · none |
labelText | string | — | Custom label text |
formatLabel | (value, min, max, percentage) => string | — | Label format function |
title | string | — | Field title above the bar |
indeterminate | boolean | false | Loading state |
striped | boolean | false | Striped pattern |
animated | boolean | false | Animate stripes (requires striped) |
shimmer | boolean | false | Shimmer/liquid leading edge |
chromeless | boolean | false | No border-radius or background |
ariaLabel | string | "Progress" | Accessible label |
VibeProgressRing
Radial/circular progress indicator with centre label.
vue
<!-- Basic -->
<VibeProgressRing :value="72" />
<!-- Sizes -->
<VibeProgressRing :value="72" size="sm" />
<VibeProgressRing :value="72" size="lg" />
<VibeProgressRing :value="72" size="xl" />
<!-- Custom stroke width -->
<VibeProgressRing :value="72" :stroke-width="4" />
<!-- Auto-color -->
<VibeProgressRing :value="progress" variant="auto" />
<!-- Custom color -->
<VibeProgressRing :value="72" color="#7c3aed" />
<!-- Custom label -->
<VibeProgressRing :value="3" :max="10" :format-label="(v, min, max) => `${v}/${max}`" />
<!-- Label slot -->
<VibeProgressRing :value="72">
<template #default="{ percentage, formatted }">
<strong>{{ formatted }}</strong>
</template>
</VibeProgressRing>
<!-- No label -->
<VibeProgressRing :value="72" :show-label="false" />
<!-- Indeterminate spinner -->
<VibeProgressRing indeterminate />Props
| Prop | Type | Default | Description |
|---|---|---|---|
value | number | 0 | Current value |
min | number | 0 | Minimum |
max | number | 100 | Maximum |
size | ProgressRadialSize | "md" | sm · md · lg · xl |
variant | ProgressVariant | "accent" | accent · success · warning · danger · auto |
color | string | — | Custom CSS color |
autoThresholds | AutoColorThreshold[] | — | Thresholds for auto variant |
strokeWidth | number | — | Stroke width in px |
showLabel | boolean | true | Show centre label |
labelText | string | — | Custom label text |
formatLabel | (value, min, max, percentage) => string | — | Label format function |
indeterminate | boolean | false | Spinner mode |
ariaLabel | string | "Progress" | Accessible label |
Scoped Slot
| Property | Type | Description |
|---|---|---|
value | number | Clamped value |
percentage | number | Percentage 0–100 |
formatted | string | Formatted label string |
Composables
useProgress(options)
Shared computation for percentage, clamping, and auto-color resolution. Used internally by both components.
ts
import { useProgress } from "@vibe-labs/design-vue-progress";
const { percentage, clampedValue, resolvedColor } = useProgress({
value: toRef(props, "value"),
min: toRef(props, "min"),
max: toRef(props, "max"),
variant: toRef(props, "variant"),
color: toRef(props, "color"),
autoThresholds: toRef(props, "autoThresholds"),
});useProgressTimer(options)
ETA estimation for long-running operations. Tracks progress samples over time, computes a smoothed rate, and estimates time remaining.
ts
import { useProgressTimer } from "@vibe-labs/design-vue-progress";
const { percentage } = useProgress({ value, min, max });
const { state, reset } = useProgressTimer({ percentage });
// state.value.etaFormatted → "~2m 30s"
// state.value.rate → 0.65 (% per second)
// state.value.completionTime → Date
// state.value.reliable → true (enough samples)Options
| Option | Type | Default | Description |
|---|---|---|---|
percentage | Ref<number> | required | Reactive percentage (0–100) |
sampleSize | number | 10 | Samples to keep for smoothing |
minSamples | number | 3 | Minimum samples before showing estimate |
State
| Property | Type | Description |
|---|---|---|
eta | number | null | Estimated seconds remaining |
etaFormatted | string | null | Formatted ETA (e.g. "~2m 30s") |
rate | number | null | Progress rate (% per second) |
reliable | boolean | Enough samples collected |
completionTime | Date | null | Predicted completion time |
Auto-Color Thresholds
The variant="auto" mode changes the bar/ring color based on the current percentage. Default thresholds:
| Range | Color |
|---|---|
| 0–33% | var(--progress-fill-danger) (red) |
| 34–66% | var(--progress-fill-warning) (yellow) |
| 67–100% | var(--progress-fill-success) (green) |
Override with the autoThresholds prop for custom breakpoints.
Dependencies
| Package | Purpose |
|---|---|
@vibe-labs/design-components-progress | CSS tokens + generated styles |
Build
bash
npm run buildBuilt with Vite + vite-plugin-dts. Outputs ES module with TypeScript declarations. Note: sideEffects: ["*.css"] is set in package.json to ensure the extras CSS is not tree-shaken.