Progress
A progress bar or capacity meter: a linear bar or circular ring with value thresholds that recolor and pulse.
Live demo
Progress shows how far along a task is, or how full a capacity is. The variant axis picks the shape (a horizontal linear bar or a circular svg ring) and the tone axis picks the color from the full roster (the six semantic roles, the accent variants, the twelve named hues).
A determinate bar fills to value between min and max; an indeterminate mode animates a moving sweep when the amount of work is unknown. Declarative <threshold below tone pulse> children turn it into a self-coloring meter: each band names a percentage ceiling, and the active band (the first the current value falls under) overrides the tone and can pulse the fill (slow or fast) to flag a critical level, the pulse routed through motion tokens so the reduced-motion base rule stills it. Set meter to report role="meter" (a measurement against a capacity, like disk used) instead of the default role="progressbar" (a task advancing); either way it carries aria-valuenow/aria-valuemin/aria-valuemax. An optional inline readout (show-value) shows the percentage, the raw value, or value/max (value-format), sits at the end or inset over the bar (value-position), and can take the active tone (colorize-value).
When to use
How this component composes with the rest of the set.
Props
18 props, straight from the manifest.
| Prop | Type | Default | Bindings | Description |
|---|---|---|---|---|
Appearance
Variants
linear
A horizontal bar that fills left-to-right.
circular
An SVG ring whose stroked arc sweeps clockwise from the top.
Sizes
sm
Thin bar / small ring.
md
Default.
States
indeterminate
Work of unknown duration; the indicator animates a continuous sweep.
pulse
An active <threshold pulse> band; the fill breathes (slow or fast) to flag a critical level, stilled under reduced-motion.
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
The root element carrying the variant, tone, and size classes and the progressbar (or meter) role.
track
The unfilled groove (a bar rail or an SVG ring) the indicator runs along.
indicator
The filled portion, colored by tone: a bar segment or a stroked arc.
value
The optional inline readout shown when show-value is set.
Tokens & coverage
What the component consumes, checked live against what the algorithm produces.
Live coverage check against the xtyle-default register
(derive(xtyleDefault, { 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
Optional custom content for the readout, in place of the built-in show-value text (e.g. a formatted label).
The <threshold below tone pulse> config children (hidden from view); the bar reads them to recolor and pulse by value.
Accessibility
Code
Linear and circular
Both shapes carry any tone; add show-value for a readout or indeterminate for unknown work.
<xtyle-progress value="42" aria-label="Upload progress"></xtyle-progress>
<xtyle-progress value="80" tone="success" show-value aria-label="Storage used"></xtyle-progress>
<xtyle-progress variant="circular" value="65" tone="info" show-value aria-label="Sync"></xtyle-progress>
<xtyle-progress variant="circular" indeterminate aria-label="Loading"></xtyle-progress>
<script lang="ts">
import { Progress } from "@xtyle/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 "@xtyle/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" />
A capacity meter with thresholds
Set meter for the measurement role and add <threshold below tone pulse> children: the bar greens under 75%, ambers past it, and reds and pulses once it crosses 90% full, the value/max readout carrying its unit. This is the gauge use once served by a separate Meter.
<xtyle-progress meter value="910" max="1000" show-value value-format="value-max" unit=" GB" colorize-value aria-label="Disk usage">
<threshold below="75" tone="success"></threshold>
<threshold below="90" tone="warn"></threshold>
<threshold below="101" tone="danger" pulse="fast"></threshold>
</xtyle-progress>
<Progress meter value={910} max={1000} showValue valueFormat="value-max" unit=" GB" colorizeValue ariaLabel="Disk usage">
<threshold below="75" tone="success" />
<threshold below="90" tone="warn" />
<threshold below="101" tone="danger" pulse="fast" />
</Progress>
<Progress meter value={910} max={1000} showValue valueFormat="value-max" unit=" GB" colorizeValue aria-label="Disk usage">
<threshold below="75" tone="success" />
<threshold below="90" tone="warn" />
<threshold below="101" tone="danger" pulse="fast" />
</Progress>
A fill that colors by its value
Set ramp to color the fill along a scale by its own value instead of a flat tone: solid (the default) samples one color at the current value, so a busier bar reads hotter; ramp-mode="gradient" sweeps the whole scale as pure CSS. Both track the theme's own hues, so the ramp restyles with the algorithm.
<xtyle-progress ramp="thermal" value="30" aria-label="Load, cool"></xtyle-progress>
<xtyle-progress ramp="thermal" value="70" aria-label="Load, warm"></xtyle-progress>
<xtyle-progress ramp="thermal" value="95" aria-label="Load, hot"></xtyle-progress>
<xtyle-progress ramp="thermal" ramp-mode="gradient" value="80" aria-label="Capacity sweep"></xtyle-progress>
<Progress ramp="thermal" value={30} ariaLabel="Load, cool" />
<Progress ramp="thermal" value={70} ariaLabel="Load, warm" />
<Progress ramp="thermal" value={95} ariaLabel="Load, hot" />
<Progress ramp="thermal" rampMode="gradient" value={80} ariaLabel="Capacity sweep" />
<Progress ramp="thermal" value={30} aria-label="Load, cool" />
<Progress ramp="thermal" value={70} aria-label="Load, warm" />
<Progress ramp="thermal" value={95} aria-label="Load, hot" />
<Progress ramp="thermal" rampMode="gradient" value={80} aria-label="Capacity sweep" />