---
title: Progress
description: Progress bar with optional value display
related:
  - /components/radial-progress
  - /components/spinner
  - /components/usage-meter
visibility: guest
draft: false
---

# Progress

A horizontal progress bar for displaying completion percentage (determinate) or indicating ongoing work without a known total (indeterminate).

## Basic Usage

### Determinate (known value)

:::preview{title="Determinate progress at 42%"}
<x-wirekit::progress :value="42" :max="100" label="Upload Progress" />
:::

### Indeterminate (unknown duration)

Omit `value` to render an animated sliding bar for tasks with unknown duration.

:::preview{title="Indeterminate — sliding animation"}
<x-wirekit::progress label="Processing…" />
:::

### Show Numeric Value

:::preview{title="With current / max readout"}
<x-wirekit::progress :value="2145" :max="5000" label="Storage" show-value />
:::

Renders: `2145 / 5000` next to the label.

## Variants

The fill color signals semantic meaning:

:::preview{title="All four variants"}
<x-wirekit::progress :value="75" variant="accent" label="Accent — default" />

<x-wirekit::progress :value="100" variant="success" label="Success — task complete" />

<x-wirekit::progress :value="60" variant="warning" label="Warning — approaching limit" />

<x-wirekit::progress :value="95" variant="danger" label="Danger — quota full" />
:::

## Sizes

:::preview{title="Three size variants"}
<x-wirekit::progress :value="50" size="sm" label="Small (h-1)" />

<x-wirekit::progress :value="50" size="md" label="Medium (h-2) — default" />

<x-wirekit::progress :value="50" size="lg" label="Large (h-3)" />
:::

## Radial (circular) progress

For a **radial** progress indicator — the ring shape for dashboards, stat tiles
and compact metrics — use the dedicated [**Radial Progress**](/components/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.

::: warning `progress.circle` is deprecated — use radial-progress
**Do not** use `progress.circle` in new code: it duplicates
[`radial-progress`](/components/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](/components/spinner) — a radial
progress is determinate by definition.
:::

## Livewire Integration

Pass a reactive value — the bar animates smoothly on updates:

```blade
<x-wirekit::progress :value="$this->uploadPercent" label="Uploading file" show-value />
```

```php
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:

```blade
<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.

:::preview{title="Progress intents"}
<x-wirekit::stack gap="md">
    <x-wirekit::progress :value="80" intent="success" label="Storage" show-value />
    <x-wirekit::progress :value="55" intent="warning" label="Quota" show-value />
    <x-wirekit::progress :value="20" intent="neutral" label="Draft" show-value />
</x-wirekit::stack>
:::

## 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).

:::preview{title="Animated stripes while uploading"}
<x-wirekit::progress :value="42" animation="stripes" label="Uploading archive.zip" show-value />
:::

:::preview{title="Shimmer sweep while uploading"}
<x-wirekit::progress :value="68" intent="accent" animation="shimmer" label="Downloading update" show-value />
:::

## 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](../variants-and-intents.md). |
| `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](https://www.w3.org/WAI/ARIA/apg/patterns/meter/)
- Determinate: sets `aria-valuenow`, `aria-valuemin="0"`, `aria-valuemax="{max}"` — screen readers announce the current percentage
- Indeterminate: `aria-valuenow` is omitted (WAI-ARIA spec for unknown progress)
- `aria-labelledby` links the bar to its visible label when `label` is set, so the label is part of the accessible name
- **Pass an `id` when the bar lives in a polling region.** The link between label and bar needs an id, and with no `id` of your own one is generated. That is fine for a bar rendered once — but a `wire:poll` region re-renders, and a generated id changes with it, so the accessible name is re-resolved on every poll. An `id` you 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-label` if the progress is not visually labeled.** A bare `<x-wirekit::progress>` carries `role="progressbar"` but screen readers need either a sibling `<x-wirekit::label>` or an explicit `aria-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`:

```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](/extending/prop-naming-conventions) for the canonical vocabulary, alias matrix, and decision tree.

## Further Reading

- [WAI-ARIA Authoring Practices — Meter / Progress](https://www.w3.org/WAI/ARIA/apg/patterns/meter/)
- [MDN: `aria-valuenow`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-valuenow)
- [MDN: `prefers-reduced-motion`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion)
