Back to catalog
Component detail entry
Data Display
@vean/ui
SProgress

Progress

Progress belongs to the Data Display category. Start with demos and usage, then use the API tables to finish integration and styling decisions.

Use the quick jump panel to reach overview, usage, demos, and API first, then continue through the full page.

Quick jump

Related components

If you are composing interactions in the same family, these components usually pair well together.

Progress

Overview

A progress indicator for determinate or indeterminate task completion. SProgress combines the Aria ProgressRoot/ProgressIndicator primitives with the progressVariants style recipe, and SProgressCircle offers a circular variant via progressCircleVariants. Both share an imperative API (progress.start()/done()) surfaced through SProgressProvider.

Use it for uploads, downloads, multi-step flows, or top-of-page loading bars. Prefer spinner for an indefinite wait, and skeleton for reserving content space before it loads.

Usage

Features

  • 🧩 Aria/styled split — ProgressRoot/ProgressIndicator own state, role="progressbar" ARIA and derived values; SProgress injects progressVariants
  • 🔢 Determinate / indeterminate — modelValue shows a concrete value; omitting it shows an indeterminate bar
  • 🎨 8 colors — ThemeColor values on the indicator
  • 📐 6 sizes — xs–2xl size
  • ⭕ Circle variant — SProgressCircle for a circular gauge with configurable strokeWidth
  • 🏷️ Custom label — getValueLabel/getValueText shape the aria-label/aria-valuetext
  • ⚡ Imperative API — progress.start()/set()/inc()/done() etc. via SProgressProvider for top-of-page loading
  • ♿ Accessible — role="progressbar" with aria-valuemin/max/now and a localized aria-label fallback

Component family

  • SProgress (styled) — the linear wrapper; progressVariants recipe
  • SProgressCircle (styled) — the circular wrapper; progressCircleVariants recipe
  • SProgressProvider (styled) — mounts the imperative progress layer
  • ProgressRoot (Aria) — the state owner; normalizes modelValue/max, derives state/value percent, renders role="progressbar"
  • ProgressIndicator (Aria) — the fill; sizes via CSS vars/transform per dir
  • ProgressCircleCompact / ProgressCompact (Aria) — the aggregated composites
  • progress (imperative) — the shared start/set/inc/done/configure controller

Demos

Basic

Slot

66%

Circle

25%
60%
85%
...

Provider

Circle Progress

<script setup lang="ts">
import { SProgressCircle } from '@vean/ui';
</script>

<template>
  <SProgressCircle :model-value="72" size="xl">
    <template #default="{ valuePercent }">{{ Math.round(valuePercent ?? 0) }}%</template>
  </SProgressCircle>
</template>

SProgressCircle supports the same props, emits, slot props, and Ui type as SProgress, and adds the following prop:

PropTypeDefaultDescription
strokeWidth
number
8
Stroke width of the circular indicator.

Progress Provider

Mount SProgressProvider once near your app root before calling the imperative progress(...) API. SConfigProvider mounts it automatically, so most applications can call progress directly.

<script setup lang="ts">
import { SButton, SProgressProvider, progress } from '@vean/ui';

const handleClick = () => {
  progress.start();

  window.setTimeout(() => {
    progress.done();
  }, 1200);
};
</script>

<template>
  <SProgressProvider />
  <SButton @click="handleClick">Start loading</SButton>
</template>

progress Methods

MethodDescription
start()Show the progress bar with the default start position and delay, then start trickling.
set(value)Set the raw progress value between minimum and maximum.
inc()Increment the current progress value.
dec()Decrement the current progress value.
trickle()Apply one automatic increment step.
done()Complete the progress bar and hide it after the configured delay.
configure()Update the shared progress options.
pause()Pause automatic trickling.
resume()Resume automatic trickling.
remove()Hide the progress bar immediately.
reset()Reset the shared progress state and options.
isStarted()Check whether the progress flow is active.
isRendered()Check whether a progress provider is currently mounted.
promise()Bind the progress lifecycle to a promise or promise factory.

API

Aria Layer

8

Progress

12 Props2 Emits1 Slots
Props
PropTypeDefaultDescription
class
ClassValue
—
Additional class names applied to the root element.
color
ThemeColor
—
Theme color of the component.
size
ThemeSize
—
Visual size of the component.
ui
Partial<ProgressUi>
—
Per-slot class overrides for the component.
indicatorProps
ProgressIndicatorProps
—
Properties forwarded to the indicator element.
dir
Direction
—
Reading direction of the component.
modelValue
number | null
—
The controlled progress value. Can be bind as `v-model`.
max
number
—
The maximum progress value.
getValueLabel
((value: number | null, max: number) => string)
—
The accessible label of the current progress value.
getValueText
((value: number | null, max: number) => string)
—
The accessible text of the current progress value.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`
Emits
Emit NameParametersDescription
update:modelValue
number | null | undefined
Emitted when the model value changes.
update:max
number
Emitted when the max value changes.
Slots
Slot NameParametersDescription
default
ProgressSlotProps
Custom content for the default slot.

ProgressCircle

13 Props2 Emits1 Slots
Props
PropTypeDefaultDescription
class
ClassValue
—
Additional class names applied to the root element.
color
ThemeColor
—
Theme color of the component.
size
ThemeSize
—
Visual size of the component.
ui
Partial<ProgressUi>
—
Per-slot class overrides for the component.
strokeWidth
number
—
Stroke width.
circleSvgProps
ProgressCircleSvgProps
—
Properties forwarded to the ProgressCircleSvg component.
dir
Direction
—
Reading direction of the component.
modelValue
number | null
—
The controlled progress value. Can be bind as `v-model`.
max
number
—
The maximum progress value.
getValueLabel
((value: number | null, max: number) => string)
—
The accessible label of the current progress value.
getValueText
((value: number | null, max: number) => string)
—
The accessible text of the current progress value.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`
Emits
Emit NameParametersDescription
update:modelValue
number | null | undefined
Emitted when the model value changes.
update:max
number
Emitted when the max value changes.
Slots
Slot NameParametersDescription
default
ProgressSlotProps
Custom content for the default slot.

ProgressCircleCompact

9 Props2 Emits1 Slots
Props
PropTypeDefaultDescription
strokeWidth
number
—
Stroke width.
circleSvgProps
ProgressCircleSvgProps
—
Properties forwarded to the ProgressCircleSvg component.
dir
Direction
—
Reading direction of the component.
modelValue
number | null
—
The controlled progress value. Can be bind as `v-model`.
max
number
—
The maximum progress value.
getValueLabel
((value: number | null, max: number) => string)
—
The accessible label of the current progress value.
getValueText
((value: number | null, max: number) => string)
—
The accessible text of the current progress value.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`
Emits
Emit NameParametersDescription
update:modelValue
number | null | undefined
Emitted when the model value changes.
update:max
number
Emitted when the max value changes.
Slots
Slot NameParametersDescription
default
ProgressSlotProps
Custom content for the default slot.

ProgressCircleSvg

1 Props
Props
PropTypeDefaultDescription
strokeWidth
number
—
Stroke width.

ProgressCompact

8 Props2 Emits1 Slots
Props
PropTypeDefaultDescription
indicatorProps
ProgressIndicatorProps
—
Properties forwarded to the indicator element.
dir
Direction
—
Reading direction of the component.
modelValue
number | null
—
The controlled progress value. Can be bind as `v-model`.
max
number
—
The maximum progress value.
getValueLabel
((value: number | null, max: number) => string)
—
The accessible label of the current progress value.
getValueText
((value: number | null, max: number) => string)
—
The accessible text of the current progress value.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`
Emits
Emit NameParametersDescription
update:modelValue
number | null | undefined
Emitted when the model value changes.
update:max
number
Emitted when the max value changes.
Slots
Slot NameParametersDescription
default
ProgressSlotProps
Custom content for the default slot.

ProgressIndicator

2 Props
Props
PropTypeDefaultDescription
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`

ProgressProvider

7 Props
Props
PropTypeDefaultDescription
direction
Direction
—
Direction.
minimum
number
—
Minimum.
maximum
number
—
Maximum.
easing
string
—
Easing.
speed
number
—
Speed.
trickle
boolean
—
Whether trickle.
trickleSpeed
number
—
Trickle speed.

ProgressRoot

7 Props2 Emits
Props
PropTypeDefaultDescription
dir
Direction
—
Reading direction of the component.
modelValue
number | null
—
The controlled progress value. Can be bind as `v-model`.
max
number
—
The maximum progress value.
getValueLabel
((value: number | null, max: number) => string)
—
The accessible label of the current progress value.
getValueText
((value: number | null, max: number) => string)
—
The accessible text of the current progress value.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`
Emits
Emit NameParametersDescription
update:modelValue
number | null | undefined
Emitted when the model value changes.
update:max
number
Emitted when the max value changes.

Notes

Architecture and benchmark differences

ProgressRoot owns the value normalization (getValidMax/getValidModelValue), state derivation (indeterminate/loading/complete) and the role="progressbar" ARIA contract, while the primitives stay style-free and only the UI wrapper injects the recipe classes. This mirrors shadcn/ui’s headless/styled split, unlike Ant Design, Element Plus, Mantine and Naive UI which ship a single config-driven progress. Vean’s distinguishing feature is the nprogress-style imperative controller (progress.start()/done()) and the SProgressCircle gauge, both of which the single-package libraries handle as separate components or omit.

CapabilityVeanUIshadcn/uiAnt Design ProgressElement Plus ProgressMantine ProgressNaive UI Progress
Linear progress✅✅✅✅✅✅
Circle progress✅—✅✅✅✅
Indeterminate✅—✅✅✅✅
Imperative API (start/done)✅—————
Color variants (8)✅✅✅✅✅✅
Size variants (6)✅—————
role="progressbar" ARIA✅✅✅✅✅✅
Custom value label✅——✅✅✅

— = unsupported or a different interaction model.

Cautions

  • For a determinate value the aria-label falls back to the localized percentage label (45%); the localized progress.ariaLabel only applies to indeterminate progress. Set an explicit aria-label to override either.
  • Indeterminate progress (no modelValue) has no aria-valuenow; its data-state is indeterminate.
  • The imperative progress API requires a mounted SProgressProvider — SConfigProvider mounts one automatically.
  • SProgressCircle stroke width is clamped between 1 and viewbox/4; pass strokeWidth for a thinner/thicker gauge.
  • The indicator uses transform + CSS vars and swaps direction under RTL via dir.

Roadmap

No blocking gaps identified for the core progress API.

FAQ

How do I show a determinate value?

Pass model-value:

<SProgress :model-value="45" />

How do I show an indeterminate bar?

Omit model-value:

<SProgress />

How do I use the top-of-page loading bar?

Mount SProgressProvider (or rely on SConfigProvider) and call the imperative API:

<script setup>
const load = () => {
  progress.start();
  setTimeout(() => progress.done(), 1200);
};
</script>
<template><SButton @click="load">Load</SButton></template>

How do I customize the announced label?

Pass get-value-label/get-value-text or an explicit aria-label:

<SProgress :model-value="45" aria-label="Upload progress" />

Circle or linear?

Use SProgressCircle for a compact gauge in a dashboard/stat, and SProgress for a full-width linear indicator or the top-of-page bar.

Changelog

Version history is grouped by release so you can quickly see what changed for this component across published versions.

v0.40.0

2026-09-14

Compare release

Fix

fix progress hydration style

Scope: progressAuthors: soybeanfeView commit3f9c7

Fix

fix progress hydration style

Scope: progressAuthors: soybeanfeView commit3f9c7

v0.20.0

2026-05-12

Compare release

Fix

update query selectors to use data-soybean-progress-provider

Scope: progressAuthors: soybeanjsView commitbc952

v0.19.0

2026-05-11

Compare release

Feature

Implement compact progress components

Scope: progressAuthors: soybeanjs, CopilotKitView commit5e53d

v0.15.3

2026-04-27

Compare release

Docs

update progress documentation and improve structure

Scope: progressAuthors: soybeanfe, CopilotView commitd86ac

v0.15.0

2026-04-26

Compare release

Feature

add imperative progress provider api and remove loading-bar wrapper. closed #129

Scope: progressAuthors: CopilotKit in https://github.com/soybeanjs/soybean-ui/issues/129View commit5f90a

Refactor

Refactor ProgressProvider and progress api

Scope: progressAuthors: soybeanjs, soybean-js, CopilotKitView commitc60cf

Docs

update class name descriptions and improve API documentation

Scope: progressAuthors: soybeanjsView commitd1327

Feature

add imperative progress provider api and remove loading-bar wrapper. closed #129

Scope: progressAuthors: CopilotKit in https://github.com/soybeanjs/soybean-ui/issues/129View commit5f90a

Refactor

Refactor ProgressProvider and progress api

Scope: progressAuthors: soybeanjs, soybean-js, CopilotKitView commitc60cf

Docs

update class name descriptions and improve API documentation

Scope: progressAuthors: soybeanjsView commitd1327