Styling contract
Headless progress bar only guarantees stable slot names. Track height, fill tone, striping, and loading motion all stay in owner CSS.
Slot hooks
Style the semantic root with [data-slot="progress-bar"] and the fill element with [data-slot="progress-bar-indicator"]. These hooks stay stable across headless and wrapper usage.
CSS starter
This starter keeps the primitive minimal while giving you a solid default track and animated indeterminate segment.
Progress bar starter CSS
css
[data-slot="progress-bar"] {
background: var(--tng-semantic-background-surface);
border-radius: 9999px;
height: 0.625rem;
overflow: hidden;
}
[data-slot="progress-bar-indicator"] {
background: var(--tng-semantic-accent-brand);
border-radius: inherit;
display: block;
height: 100%;
}
[data-slot="progress-bar-indicator"][data-indeterminate] {
animation: tng-progress-bar-indeterminate 1.1s ease-in-out infinite;
width: 40%;
}
@keyframes tng-progress-bar-indeterminate {
0% { transform: translateX(-100%); }
100% { transform: translateX(250%); }
}
Motion guidance
- Keep indeterminate motion smooth and lateral so the task still reads as a linear bar.
- Use duration and easing that feel calm in dashboards where the bar may stay visible for a while.
- Prefer subtle width transitions over dramatic easing when progress updates frequently.
- Pair the bar with text labels when completion percentage alone is not enough context.