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

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

> A monochrome-plus-signal bar chart with sharp (radius 0) bars capped at 24px, recharts-backed.

## Import path

`BarChart` ships from the **`@protocore/pds/charts`** subpath so recharts stays out of the core bundle. `recharts` (>=3) is an **optional peer**; install it in apps that render charts.

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

## When to use it

Use **BarChart** to compare a value across *discrete categories* — regions, plans, validators, status classes — where length is easy to read against a shared baseline. For a continuous trend over an ordered axis use [LineChart](/charts/line-chart) or [AreaChart](/charts/area-chart); for a frameless glance, [Sparkline](/charts/sparkline).

Keep the categorical differentiation contract in mind: bars are sharp and monochrome by default; spend a signal hue only on the series that carries meaning (see the doctrine on [ChartContainer](/charts/chart-container)). Recharts stacking/layout props pass through via `...rest`.

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `data` | `ReadonlyArray<Record<string, string \| number \| null \| undefined>>` | yes | — | Row-oriented data; each datum keyed by `xKey` and by every series `key`. |
| `series` | `ChartSeries[]` | yes | — | Series to plot, in draw + legend order. `ChartSeries` = `{ key: string; label?: string; color?: string }` — color defaults to `--pds-chart-N` by position. |
| `xKey` | `string` | yes | — | Datum key for the x-axis category. |
| `height` | `number` | no | `240` | Chart height in px. |
| `...rest` | `Omit<RechartsBarChartProps, 'data' \| 'children' \| 'width' \| 'height' \| 'ref'>` | no | — | Remaining props spread onto the underlying recharts `<BarChart>` (e.g. `margin`, `barGap`, `layout`, `stackOffset`). |

## Examples

### Basics

Give it `data`, an `xKey`, and one `series`. Bars are sharp (radius 0, matching the system's control geometry) and capped at 24px wide so a short category axis doesn't produce slab-like bars. The hover cursor is a faint accent-muted wash.

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

const data = [
  { node: "val-01", blocks: 142 },
  { node: "val-02", blocks: 128 },
  { node: "val-03", blocks: 156 },
  { node: "val-04", blocks: 119 },
  { node: "val-05", blocks: 134 },
];

export default function Demo() {
  return (
    <ChartContainer label="Blocks proposed / epoch" height={240}>
      <BarChart data={data} xKey="node" series={[{ key: "blocks", label: "Blocks" }]} />
    </ChartContainer>
  );
}
```

### Grouped series

Multiple `series` render as grouped bars per category, each in the next ramp slot. This is where the signal hues earn their place — e.g. a grey "2xx" bar beside an amber "5xx" bar makes the failure rate pop without a color legend.

```tsx
import { ChartContainer } from "@protocore/pds";
import { BarChart, ChartLegend } from "@protocore/pds/charts";

const data = [
  { tier: "Free", success: 940, failed: 60 },
  { tier: "Team", success: 1820, failed: 40 },
  { tier: "Scale", success: 3110, failed: 90 },
  { tier: "Enterprise", success: 4600, failed: 25 },
];

const series = [
  { key: "success", label: "2xx" },
  { key: "failed", label: "5xx" },
];

export default function Demo() {
  return (
    <ChartContainer
      label="API responses by plan / req"
      legend={<ChartLegend items={series.map((s) => ({ label: s.label }))} />}
      height={240}
    >
      <BarChart data={data} xKey="tier" series={series} />
    </ChartContainer>
  );
}
```

## Do & don't

**Do**

- Use it for comparison across discrete categories with a shared baseline.
- Let bars stay grey and spend a signal hue on the meaningful series (e.g. failures).
- Wrap it in a ChartContainer so it inherits the `--pds-chart-*` ramp.
- Keep grouped series to a handful so each category stays readable.

**Don't**

- Don't use bars for a continuous time series — that's a line or area chart.
- Don't round the bars or add shadows; sharp geometry is the house style.
- Don't import it from `@protocore/pds`; it lives on the `/charts` subpath.
- Don't truncate the y-axis baseline — bar length must be honest.

## Accessibility

**Notes**

- recharts renders the plot as SVG; provide surrounding context (a ChartContainer `label`, caption, or data table) since individual bars are not labelled.
- Bar length encodes value independently of color, so the chart stays readable in grayscale and for color-vision deficiencies; pair grouped series with a legend.
- The default tooltip surfaces per-series values on hover and keyboard focus via recharts.

## Related

`line-chart`, `area-chart`, `chart-container`, `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/
