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

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

> A single 100%-stacked horizontal distribution bar with sharp, tokened segments and a swatch/label/percent legend.

## Import path

`PercentageBarChart` ships from the **`@protocore/pds/charts`** subpath. Unlike the recharts wrappers it is hand-rolled SVG-free markup — **no recharts dependency** — so it is safe to render anywhere, but it is grouped with the charts family for its ramp and legend conventions.

```tsx
import { PercentageBarChart } from "@protocore/pds/charts";
import { ChartContainer } from "@protocore/pds";
```

## When to use it

Use a **PercentageBarChart** to show a *single* whole split into parts along one row — status-class mix, pass/fail/skip, storage used vs free. It reads more precisely than a [PieChart](/charts/pie-chart) for near-equal shares and packs into a table cell or a stat row.

For a *value* progressing to a target (not a part-to-whole split) use a [ProgressBar](/feedback/progress-bar) or [RadialProgress](/charts/radial-progress); to compare a value across many categories use a [BarChart](/charts/bar-chart).

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `data` | `PercentageSegment[]` | yes | — | Segments in draw + legend order (left to right). `PercentageSegment` = `{ key?: string; label?: ReactNode; value: number; color?: string }` — each segment's share of the summed total sets its width. |
| `thickness` | `number` | no | `12` | Bar thickness in px. |
| `legend` | `boolean` | no | `true` | Render the swatch/label/percent legend beneath the bar. |
| `formatValue` | `(pct: number, segment: PercentageSegment) => string` | no | `trimmed 0–1 decimal %` | Format a segment's percentage for display. |
| `label` | `string` | no | `auto-composed` | Accessible summary of the distribution (role=img aria-label). Composed from segments when omitted. |

## Examples

### Basics

Pass `data` as an array of `{ label, value }` segments. Values are normalised to their share of the total, so they need not sum to 100. Each segment is sharp (radius 0), hairline-separated, and coloured from the `--pds-chart-N` ramp; the legend beneath carries the label and a tabular percentage.

```tsx
import { ChartContainer } from "@protocore/pds";
import { PercentageBarChart } from "@protocore/pds/charts";

const data = [
  { key: "passed", label: "Passed", value: 214 },
  { key: "flaky", label: "Flaky", value: 18 },
  { key: "failed", label: "Failed", value: 9 },
];

export default function PercentageBarBasics() {
  return (
    <ChartContainer label="CI suite · last run" height={120}>
      <PercentageBarChart data={data} />
    </ChartContainer>
  );
}
```

### Signal colour + custom format

Override a segment's `color` to spend a signal hue on the part that matters — a red `5xx` slice against grey `2xx`/`4xx`. `formatValue` controls the printed percentage (here to one decimal).

```tsx
import { ChartContainer } from "@protocore/pds";
import { PercentageBarChart } from "@protocore/pds/charts";

const data = [
  { key: "ok", label: "2xx", value: 91_400 },
  { key: "client", label: "4xx", value: 6_120, color: "var(--pds-color-warning)" },
  { key: "server", label: "5xx", value: 880, color: "var(--pds-color-danger)" },
];

export default function PercentageBarSignal() {
  return (
    <ChartContainer label="Edge responses · 1h" height={120}>
      <PercentageBarChart data={data} thickness={16} formatValue={(pct) => `${pct.toFixed(1)}%`} />
    </ChartContainer>
  );
}
```

## Do & don't

**Do**

- Use it for one whole split into a few labelled parts.
- Let segments stay grey and spend a signal hue on the meaningful part.
- Rely on the normalisation — pass raw counts, not pre-computed percentages.
- Give each segment a readable `label` so the legend and aria summary are meaningful.

**Don't**

- Don't use it to track a single value to a target — that's a ProgressBar.
- Don't round the segments or add shadows; sharp geometry is the house style.
- Don't pack in so many segments that the thin slivers become unreadable.
- Don't rely on colour alone — the legend labels every segment.

## Accessibility

**Notes**

- The bar exposes `role="img"` with an aria-label composed from each segment's label and percentage (override via `label`).
- Segment length encodes share independently of colour, so the distribution stays readable in grayscale and for colour-vision deficiencies.
- The legend labels every segment with a tabular percentage for exact values.

## Related

`pie-chart`, `bar-chart`, `progress-bar`, `chart-legend`

---

© 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/
