Progress
A horizontal progress bar for displaying completion percentage (determinate) or indicating ongoing work without a known total (indeterminate).
Basic Usage
Determinate (known value)
Indeterminate (unknown duration)
Omit value to render an animated sliding bar for tasks with unknown duration.
Show Numeric Value
Renders: 2145 / 5000 next to the label.
Variants
The fill color signals semantic meaning:
Sizes
Radial (circular) progress
For a radial progress indicator — the ring shape for dashboards, stat tiles and compact metrics — use the dedicated Radial Progress component. It is the canonical radial progress in WireKit: size and intent options, threshold coloring that turns the ring warning/danger past a limit, and a required accessible name.
progress.circle is deprecated — use radial-progress
Do not use progress.circle in new code: it duplicates
radial-progress under a second name and will be
removed in v3.0.0 (a breaking change). Migrate <x-wirekit::progress.circle :value="75" />
to <x-wirekit::radial-progress :value="75" label="…">75%</x-wirekit::radial-progress>.
For an indeterminate ring, reach for the spinner — a radial
progress is determinate by definition.
Livewire Integration
Pass a reactive value — the bar animates smoothly on updates:
<x-wirekit::progress :value="$this->uploadPercent" label="Uploading file" show-value />
public int $uploadPercent = 0;
public function processChunk()
{
$this->uploadPercent = min(100, $this->uploadPercent + 10);
}
Width & Layout
The progress bar fills its parent width. Control the width with Tailwind classes directly on the component:
<x-wirekit::progress class="max-w-sm" :value="65" label="Upload" />
Height is controlled by the size prop (sm, md, lg).
Intent
intent is the canonical color axis (matching badge, button, and alert). variant keeps working as a back-compat alias; when both are present, intent wins.
Animated fill
animation adds optional motion to a determinate fill — the "work in flight"
affordance for uploads and streaming. stripes is the barber-pole; shimmer is a
single light sweep. Both are purely additive: the bar's value is unchanged, and the
motion is disabled under prefers-reduced-motion (stripes freeze but stay visible;
the shimmer sweep is removed).
Reduced Motion
WireKit disables all progress and skeleton animations when the user's OS has prefers-reduced-motion: reduce set. This is handled centrally in dist/wirekit.css — no extra configuration needed.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
value |
numeric|null | null |
Current value (null = indeterminate) |
max |
numeric | 100 |
Maximum value the bar represents |
label |
string|null | null |
Visible text label above the bar |
showValue |
bool | false |
Show current / max next to label |
intent |
string | 'primary' |
The color axis: 'primary', 'accent' (alias of primary), 'success', 'warning', 'danger', 'info', 'neutral'. See Variants & Intents. |
variant |
string | null |
Back-compat alias for intent. New code should use intent. |
size |
string | 'md' |
'sm', 'md', 'lg' |
animation |
string | 'none' |
Optional fill motion (determinate only): 'none', 'stripes', 'shimmer'. Disabled under prefers-reduced-motion. |
scope |
string|null | null |
Scoped personalization name |
Accessibility
role="progressbar"on the track — the WAI-ARIA progressbar role- Determinate: sets
aria-valuenow,aria-valuemin="0",aria-valuemax="{max}"— screen readers announce the current percentage - Indeterminate:
aria-valuenowis omitted (WAI-ARIA spec for unknown progress) aria-labelledbylinks the bar to its visible label whenlabelis set, so the label is part of the accessible name- Pass an
idwhen the bar lives in a polling region. The link between label and bar needs an id, and with noidof your own one is generated. That is fine for a bar rendered once — but awire:pollregion re-renders, and a generated id changes with it, so the accessible name is re-resolved on every poll. Anidyou supply stays put across renders. - The indeterminate animation respects
prefers-reduced-motion: users with reduced-motion settings see a static filled region instead of a sliding bar
Keyboard Interaction
This component is purely presentational and does not respond to keyboard input.
Pitfalls
- Don't omit
aria-labelif the progress is not visually labeled. A bare<x-wirekit::progress>carriesrole="progressbar"but screen readers need either a sibling<x-wirekit::label>or an explicitaria-label.
Design Tokens
| Element | Token |
|---|---|
| Track background | --color-wk-bg-muted |
| Track radius | --radius-wk-full |
| Fill (accent) | --color-wk-accent |
| Fill (success) | --color-wk-success |
| Fill (warning) | --color-wk-warning |
| Fill (danger) | --color-wk-danger |
| Label color | --color-wk-text |
| Value color | --color-wk-text-muted |
| Transition | --transition-wk-duration |
Customization
Override defaults without publishing views via config/wirekit.php:
'components' => [
'progress' => [
'variant' => 'success',
'size' => 'sm',
],
],
Usage & Conventions
Prop conventions — this component uses one or more of the shared semantic prop names (
intent/variant/tone/surface). See Prop naming conventions for the canonical vocabulary, alias matrix, and decision tree.