<!-- Protocore Design System — RadialProgress -->
# RadialProgress

- **Category:** Charts (`charts`)
- **Slug:** `charts/radial-progress`
- **Status:** stable
- **Platforms:** web
- **Import:** `import { RadialProgress } from "@protocore/pds/charts";`
- **Docs:** https://pds.protocore.io/components/charts/radial-progress

> A single-value radial gauge — a hand-rolled SVG ring with an accent (or tone) value arc and a mono tabular centre label.

## Import path

Unlike the recharts wrappers, **RadialProgress** is a hand-rolled SVG gauge with **no chart dependency**, so it ships from the main entry:

```tsx
import { RadialProgress } from "@protocore/pds";
```

## When to use it

Use **RadialProgress** for a *single* value against a bound where the compact ring earns its place — a KPI tile, a quota gauge, the centre of a [DonutChart](/charts/pie-chart), a sync/uptime readout. It draws the eye to one number.

For a value in a row or a dense list, a thin [ProgressBar](/feedback/progress-bar) reads faster and packs tighter. For a whole split into parts, use a [PercentageBarChart](/charts/percentage-bar-chart). RadialProgress is determinate only — for unknown-duration work use an indeterminate ProgressBar or a Spinner.

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `caption` | `ReactNode` | no | — | Optional mono-UPPER caption rendered under the value. |
| `className` | `string` | no | — | — |
| `formatValue` | `((value: number, max: number) => ReactNode)` | no | — | Format the centre value label. Defaults to a rounded percentage of `max`. |
| `label` | `string` | no | — | Accessible label describing what the gauge measures. |
| `max` | `number` | no | `100` | Upper bound of `value`. Defaults to `100`. |
| `showValue` | `boolean` | no | `true` | Render the centre value label. Defaults to `true`. |
| `size` | `number` | no | `120` | Diameter in px. Defaults to `120`. |
| `style` | `CSSProperties` | no | — | — |
| `thickness` | `number` | no | `8` | Ring stroke width in px. Defaults to `8`. |
| `tone` | `enum` | no | — | Swap the accent arc for a status tone. |
| `value` | `number` | yes | — | Current value. |

## Examples

### Basics

Pass a `value` (and `max`, defaulting to 100). The arc fills clockwise from 12 o'clock in the accent — the reserved brand signal for a single live figure — over a faint track, with a mono tabular percentage in the centre. The ring is the one place a radius is on-brand: it's a gauge, not a control.

```tsx
import { RadialProgress, HStack } from "@protocore/pds";

export default function RadialProgressBasics() {
  return (
    <HStack gap={6} align="center" wrap>
      <RadialProgress value={38} label="Migration progress" caption="Migrating" />
      <RadialProgress value={72} label="Index rebuild" caption="Rebuilding" />
      <RadialProgress value={100} label="Snapshot" caption="Done" />
    </HStack>
  );
}
```

### Tones, captions, and custom labels

A `tone` swaps the accent arc for a status colour when the gauge itself reports health (danger for near-full disk, success for uptime). Add a mono-UPPER `caption` under the number, and override `formatValue` to print a fraction (`3/5`) or a raw value instead of a percentage.

```tsx
import { RadialProgress, HStack } from "@protocore/pds";

export default function RadialProgressTones() {
  return (
    <HStack gap={6} align="center" wrap>
      <RadialProgress value={99.98} label="Uptime · 30d" tone="success" caption="Uptime" />
      <RadialProgress value={74} label="Disk used" tone="warning" caption="Disk" />
      <RadialProgress value={92} label="Quota used" tone="danger" caption="Quota" />
      <RadialProgress
        value={3}
        max={5}
        label="Onboarding steps"
        caption="Steps"
        formatValue={(v, m) => `${v}/${m}`}
      />
    </HStack>
  );
}
```

## Do & don't

**Do**

- Use it for one headline value against a clear bound.
- Keep the accent arc for neutral progress; switch to a `tone` only when the value reports health.
- Pair it with a mono caption so the number's meaning is unambiguous.
- Nest it in a DonutChart's hole to show a part-to-whole plus its total.

**Don't**

- Don't use it for indeterminate work — it's determinate; reach for a Spinner.
- Don't crowd a table row with rings; a ProgressBar packs tighter.
- Don't spend the accent arc on a status meaning — use a `tone` for that.
- Don't rely on the arc alone; the centre label carries the exact value.

## Accessibility

**Notes**

- Exposes `role="progressbar"` with `aria-valuemin`/`aria-valuemax`/`aria-valuenow`; pass a `label` describing what it measures.
- The SVG ring and centre label are decorative (aria-hidden) — the value is announced through the progressbar semantics.
- Out-of-range values are clamped into `[0, max]` so the arc and reported value stay honest.

## Related

`progress-bar`, `percentage-bar-chart`, `pie-chart`, `metric-delta`

---

© Protocore. All rights reserved. Use of the Protocore Design System requires prior written authorization from Protocore (contact@protocore.io). These machine-readable materials must not be ingested into ML-training datasets or derivative design systems. See https://pds.protocore.io/legal/
