# Progress (/docs/charts/progress)

68% complete, or 3 of 5 steps: the label _is_ the datum, which is why it is on by default. The bar gives the instant
read, and the track never shrinks to make room for the label — the viewBox widens instead — so fractions stay comparable
down a table column.

```tsx
<Progress value={0.68} title="Onboarding" width={160} height={22} />
```

## Install

```tsx
import { Progress } from "@microcharts/react/progress";

<Progress value={0.68} title="Onboarding" />
```

Setup (package + stylesheet): [Quickstart](/docs/quickstart#set-up-with-an-ai-agent) or paste [`/agent-setup.md`](/agent-setup.md) into your agent.

## Try it

```tsx
import { Progress } from "@microcharts/react/progress/interactive";

<Progress
  value={0.68}
/>
```

## When to use it

Use it for KPI cards, table completion columns, and step counts (`segments`). For icon-size slots use ProgressRing; for
composition use SegmentedBar.

## Sizing

**table column**

```tsx
// fixed width per row — fractions stay comparable down the column
<Progress value={row.done} max={row.total} style={{ width: 96 }} />
```

**stepped onboarding**

```tsx
<Progress value={3} max={5} segments={5} label="fraction" />
```

## Variants

```tsx
// discrete steps — the chart now says "3 of 5", not "60%"
<Progress value={3} max={5} segments={5} label="fraction" />
```

```tsx
<Progress value={34} max={50} label="value" />
<Progress value={0.68} label="none" />
```

```tsx
// less is good — wording flips, the bar stays factual
<Progress value={0.68} positive="down" />
```

```tsx
<Progress value={34} max={50} label="value" locale="de-DE" />
```

With `label="percent"` (the default) the accessible name follows `format`/`locale` too — "68 %" under `de-DE` rather
than the English "68%".

## Edge cases

```tsx
// the bar clamps at full; the LABEL tells the truth
<Progress value={112} max={100} />
```

```tsx
<Progress value={0} title="Not started" />
```

```tsx
// usable = value/max is computable only when max > 0 — an empty track,
// not an invented fraction
<Progress value={5} max={0} title="Unknown goal" />
```

Past 100% the bar clamps at full and the label carries the true figure ("112%"). That is the one documented case where
the bar and the number disagree, and the number wins. `max <= 0` (or a non-finite `value`/`max`) renders an empty track
with no fill, and the label becomes an em dash ("—") rather than a fabricated number; the accessible name says "No
data." instead of computing a ratio it can't compute. A `value` of `0` renders a real, empty-but-present bar rather than
the no-data state, so "not started" and "unmeasurable" stay visually distinct.

`max` — not `total` — is the deliberate exception across the library. Every other denominator prop names a discrete
count (`total` on IconArray, TallyMarks, Honeycomb…), but Progress tracks a continuous goal that can be overshot, so it
keeps the word for a ceiling.

## Four homes

**In a sentence**

```tsx
<p>
  Database migration to the new cluster is{" "}
  <span className="mc-inline">
    <Progress value={0.68} title="Migration status" width={90} height={18} summary={false} />
  </span>
  {" "}
  — on track for Friday's cutover.
</p>
```

**In a table cell**

```tsx
<td>
  <Progress value={release.done} title={`${release.name} readiness`} style={{ width: 96 }} />
</td>
```

**In a KPI card**

```tsx
<div className="kpi">
  <span className="figure">$34.9k</span>
  <span className="unit">of $50k</span>
  <Progress value={34900} max={50000} title="Budget burn" width={140} height={22} />
</div>
```

**In a tab header**

```tsx
<button className="tab">
  Setup <Progress value={3} max={5} segments={5} label="fraction" />
</button>
```

## Accessibility

The accessible name is the completion — **"68% complete."**, or **"3 of 5 steps."** when segmented, or **"32%
remaining."** with `positive="down"`. The interactive entry re-announces through a polite live region, throttled to
whole-percent changes so a streaming value doesn't spam screen readers, and the fill-width transition is gated on
reduced motion.

This chart is a single unit, so there is nothing to rove between: a click, tap, `Enter` or `Space` selects it
and fires `onSelect`, and no selection stays pinned. That is the scalar half of the shared
[interaction contract](/docs/accessibility#one-interaction-contract).
Hover or focus also reveals the reading itself in a floating chip, for the sizes and label modes where the mark
does not print it; `readout={false}` drops the chip and keeps everything else.

## Props

| Prop | Type | Description |
| --- | --- | --- |
| `value` (required) | `number` | The progressed amount. |
| `max` | `number` | Denominator (default 1). |
| `segments` | `number` | Discrete-chunk track — the chart says step count, not ratio. |
| `label` | `"percent" \| "value" \| "fraction" \| "none"` | The direct label; percent is the default datum. |
| `positive` | `"up" \| "down"` | down = burn-down wording (summary only; the bar stays factual). |
| `animate` | `boolean` | (interactive) Opt-in entrance motion when the chart mounts client-side — add `import "@microcharts/react/motion"` once. Inert on the server, on hydrated server HTML, and under `prefers-reduced-motion`. |

Plus the shared grammar — `data`, `domain`, `color`, `title`, `summary`, `format` — and the layout props (`width`, `height`, `className`, `style`) that every chart accepts. Interactive entries also share `animate` and `live`, and — wherever a chart has more than one navigable unit — `onActive`, `onSelect`, `selectedIndex` and `defaultSelectedIndex`; and — wherever the chart shows a hover value — `readout`. See [the shared grammar](/docs/quickstart#the-shared-grammar).
