Progress Spinner overview
Headless progress spinner gives you range semantics and ARIA wiring, while the SVG, circles, motion, and visual scale stay fully owner-authored.
Imports
Use the primitive directive when you want to own the circular markup and motion yourself.
Primitive import
ts
import { TngProgressSpinner } from '@tailng-ui/primitives';
Basic composition
The primitive only marks the root as a progressbar. You provide the SVG, track circle, indicator circle, and any indeterminate animation.
Minimal headless markup
html
<span tngProgressSpinner [value]="72" class="progress-spinner" aria-label="Sync progress">
<svg class="progress-spinner__svg" viewBox="0 0 40 40">
<circle class="progress-spinner__track" cx="20" cy="20" r="18"></circle>
<circle
class="progress-spinner__indicator"
cx="20"
cy="20"
r="18"
stroke-dasharray="113.097"
[attr.stroke-dashoffset]="113.097 - (113.097 * 72) / 100"
></circle>
</svg>
</span>
<span tngProgressSpinner [indeterminate]="true" class="progress-spinner" aria-label="Loading report">
<svg class="progress-spinner__svg" viewBox="0 0 40 40">
<circle class="progress-spinner__track" cx="20" cy="20" r="18"></circle>
<circle
class="progress-spinner__indicator progress-spinner__indicator--indeterminate"
cx="20"
cy="20"
r="18"
stroke-dasharray="70"
stroke-dashoffset="20"
></circle>
</svg>
</span>
Style variants
Use the same primitive root inside a lightweight CSS shell or a utility-authored Tailwind surface.
Headless spinner (plain CSS)
Headless spinner (Tailwind)
Range semantics
min,max, andvalueare normalized and clamped on the root directive.- Indeterminate mode removes
aria-valuenow,aria-valuemin, andaria-valuemax. - The primitive does not render circles or size the spinner for you.
- Provide visible context or an explicit
aria-labelwhen the surrounding UI does not already explain the task.