Progress spinner
<aparte-progress-spinner>
AparteProgressSpinner
Circular progress spinner web component.
- Indeterminate (no
valueattribute): continuous rotation animation - Determinate (
value="0–100"): fills the arc proportionally
The ABSENCE of the attribute is what selects indeterminate, so value="" is not
“unknown progress” — it parses to 0, i.e. an empty determinate arc. value is clamped
to 0–100 and anything non-numeric reads as 0; nothing throws.
It renders its own SVG into itself on connect and on every value change, so it takes
no children: whatever you put inside is overwritten. The SVG is aria-hidden and the
ARIA lives on the host (role="progressbar", aria-valuemin/aria-valuemax, plus
aria-valuenow only when determinate) — there is no accessible NAME, so give the
element an aria-label unless the surrounding text already says what is loading.
It draws an arc; it does not manage a loading lifecycle — no delay before appearing, no
timeout, no label, no live announcement. Under prefers-reduced-motion: reduce the
rotation stops (aparte.css scopes that rule to the library’s own elements), which is the
other reason the indeterminate arc must not be the only signal that work is in flight.
Example
Section titled “Example”<!-- Omit `value` for the indeterminate spin; set it to show real progress. --><aparte-progress-spinner></aparte-progress-spinner><aparte-progress-spinner value="62"></aparte-progress-spinner>Attributes
Section titled “Attributes”| Attribute | Description |
|---|---|
value | Progress percentage 0–100 (omit for indeterminate) |
Theming
Section titled “Theming”Override any of these on :root, on a subtree, or on one instance — custom properties inherit downward. Some are this element’s own; others are site-wide tokens that also style it, and overriding one of those at :root moves everything that reads it. The full set is in the CSS variables reference.
<aparte-progress-spinner>
Section titled “<aparte-progress-spinner>”| Variable | Default | Description |
|---|---|---|
--aparte-spinner-size | var(--aparte-spinner-size-md) | Width and height of the element; the SVG fills it. |
--aparte-spinner-color | currentColor | Stroke of the filled (progress) arc. |
--aparte-spinner-track | var(--aparte-border-control) | Stroke of the track arc behind it. |
In a framework
Section titled “In a framework”The element is the same object everywhere — the tag does not change. What changes is how an attribute is written and how an event reaches you.
<aparte-progress-spinner value="…"></aparte-progress-spinner><aparte-progress-spinner value="…"></aparte-progress-spinner>The aparte-* tags are typed JSX intrinsics as soon as you import from @aparte/react.
<template> <aparte-progress-spinner value="…"></aparte-progress-spinner></template>Declared through Vue’s GlobalComponents, so vue-tsc checks the tag in any template.
<aparte-progress-spinner value="…"></aparte-progress-spinner>Declared through SvelteHTMLElements, so svelte-check covers the attributes and the on: handlers.
import { AparteProgressSpinnerDirective } from '@aparte/angular';<aparte-progress-spinner value="…"></aparte-progress-spinner>A standalone directive whose selector IS the tag, so the real element sits in the template — @if, @for and content projection all reach it — and no CUSTOM_ELEMENTS_SCHEMA is needed.
Installation and the framework-specific traps: React · Vue · Svelte · Angular.