Skip to main content

Progress

Info:Feedback html svelte astro Success: coverage 43/43

A determinate progress meter: a linear bar or a circular ring, across six semantic tones.

Live demo

live · @xoji/astro

Progress

Linear, six tones

accent
64%
neutral
40%
info
52%
success
100%
warn
78%
danger
22%

Every tone

Accents

accent
accent-2
accent-3
accent-4
neutral

Statuses

success
info
warn
danger

Named hues

red
orange
yellow
green
blue
purple
brown
pink
cyan
gray
white
black

Value readouts

percent
33%
value
123
of max
123/456

Thresholds, tone & pulse

12%
12%
38%
38%
76%
76%

Inset readout

66%
92%

Circular ring

64%
accent
40%
neutral
52%
info
100%
success
78%
warn
22%
danger

Sizes & indeterminate

Small
Medium
Large
48%
Indeterminate — linear
Indeterminate — circular

Progress shows how far along a task is. The variant axis picks the shape (a horizontal linear bar or a circular svg ring) and the tone axis picks the semantic color, so any of the six tones (accent, neutral, danger, success, warn, info) can paint either shape.

A determinate meter fills to value between min and max; an indeterminate mode animates a moving sweep when the amount of work is unknown. It exposes role="progressbar" with aria-valuenow/aria-valuemin/aria-valuemax for screen readers, and an optional inline percentage readout.

When to use

How this component composes with the rest of the set.

Pair with a status Badge or text label to spell out the percentage in words when show-value alone is not enough.
Drive value from an upload/download stream; flip to indeterminate for the indefinite handshake phase.
Use the success tone on completion and danger on a stalled or failed transfer to reinforce state with color.

Props

9 props, straight from the manifest.

PropTypeDefaultBindingsDescription
variant ProgressVariant
linear circular
linear
html svelte astro
Shape of the meter: a horizontal bar or a circular ring.
tone FullTone
accent neutral danger success warn info accent-2 accent-3 accent-4 red orange yellow green blue purple brown pink cyan gray white black
accent
html svelte astro
Semantic color of the filled indicator.
size ProgressSize
sm md
md
html svelte astro
Meter size; `sm` thins the bar or shrinks the ring.
value number 0
html svelte astro
Current amount of work done, clamped between `min` and `max`.
min number 0
html svelte astro
Lower bound of the range.
max number 100
html svelte astro
Upper bound of the range.
indeterminate boolean false
html svelte astro
Animates a moving sweep instead of a fixed fill when progress is unknown; drops `aria-valuenow`.
showValue boolean false
html svelte astro
Renders an inline percentage readout beside (or inside) the meter.
ariaLabel string
html svelte astro
Accessible name for the meter. Required. A progressbar with no name is not announced.

Appearance

Variants

linear

.xoji-progress--linear

A horizontal bar that fills left-to-right.

circular

.xoji-progress--circular

An SVG ring whose stroked arc sweeps clockwise from the top.

Sizes

sm

.xoji-progress--sm

Thin bar / small ring.

md

default
.xoji-progress

Default.

States

indeterminate

.xoji-progress--indeterminate

Work of unknown duration; the indicator animates a continuous sweep.

focus-visible

.xoji-progress:focus-visible

Keyboard focus: a token-colored ring, plus a transparent outline that becomes real in forced-colors mode.

Anatomy

The named parts that make up the component, with their selectors.

progress

.xoji-progress

The root element carrying the variant, tone, and size classes and the progressbar role.

--font-sans --fg-1 --space-2

track

.xoji-progress__track

The unfilled groove (a bar rail or an SVG ring) the indicator runs along.

--neutral-bg --radius-full --space-1 --space-2

indicator

.xoji-progress__indicator

The filled portion, colored by tone: a bar segment or a stroked arc.

--accent --duration-base --ease-emphasized

value

.xoji-progress__value

The optional inline percentage readout shown when show-value is set.

--text-sm --text-xs --fg-2 --fg-1

Tokens & coverage

What the component consumes, checked live against what the algorithm produces.

Success:fully covered 43/43 consumed tokens produced default register: 276 tokens

Live coverage check against the xoji-default register (derive(xojiDefault, { anchors })coverComponent(manifest, register)). Every token this component consumes must be a key the algorithm produces.

--accent --accent-2 --accent-3 --accent-4 --bg-0 --black --blue --border-normal --border-thick --brown --cyan --danger --duration-base --ease-emphasized --ease-standard --fg-0 --fg-1 --fg-2 --font-sans --gray --green --info --neutral --neutral-bg --orange --pink --purple --radius-full --radius-sm --red --ring --space-1 --space-2 --space-3 --space-6 --space-8 --success --text-body --text-sm --text-xs --warn --white --yellow

Slots

default
html svelte astro

Optional custom content rendered in place of the built-in value readout (e.g. a label).

Accessibility

Exposes role="progressbar" with aria-valuemin, aria-valuemax, and aria-valuenow so assistive tech announces the current amount.
indeterminate drops aria-valuenow (the value is unknown) while keeping the min/max bounds.
Requires an accessible name via aria-label; the binding warns at runtime when one is missing.
The visual fill is presentational; progress state lives in the ARIA value attributes, not the geometry.
Focus is shown with a token ring and a transparent outline that the forced-colors base rule promotes to a real system outline.
Motion (the indeterminate sweep) is routed through duration/easing tokens, so the reduced-motion base rule neutralizes it.

Code

Linear and circular

Both shapes carry any tone; add show-value for a readout or indeterminate for unknown work.

<xoji-progress value="42" aria-label="Upload progress"></xoji-progress>

<xoji-progress value="80" tone="success" show-value aria-label="Storage used"></xoji-progress>

<xoji-progress variant="circular" value="65" tone="info" show-value aria-label="Sync"></xoji-progress>

<xoji-progress variant="circular" indeterminate aria-label="Loading"></xoji-progress>
<script lang="ts">
	import { Progress } from "@xoji/svelte";

	let value = $state(42);
</script>

<Progress {value} ariaLabel="Upload progress" />

<Progress value={80} tone="success" showValue ariaLabel="Storage used" />

<Progress variant="circular" value={65} tone="info" showValue ariaLabel="Sync" />

<Progress variant="circular" indeterminate ariaLabel="Loading" />
---
import { Progress } from "@xoji/astro";
---

<Progress value={42} aria-label="Upload progress" />

<Progress value={80} tone="success" showValue aria-label="Storage used" />

<Progress variant="circular" value={65} tone="info" showValue aria-label="Sync" />

<Progress variant="circular" indeterminate aria-label="Loading" />