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

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

> A monochrome-plus-signal bubble chart — a scatter plot with a third (size) dimension mapped through a recharts ZAxis.

## Import path

`BubbleChart` ships from the **`@protocore/pds/charts`** subpath. `recharts` (>=3) is an **optional peer**.

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

## When to use it

Use **BubbleChart** when a third measure — volume, weight, count — matters alongside an x/y correlation. Without that third dimension, reach for [ScatterChart](/charts/scatter-chart). Keep bubbles translucent so dense clusters remain legible, and rank series by luminance on the ramp.

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `data` | `ReadonlyArray<Record<string, string \| number \| null \| undefined>>` | yes | — | Row-oriented data; each datum keyed by `xKey`, `zKey`, and every series `key` (its y value). |
| `series` | `ChartSeries[]` | yes | — | Series to plot, in draw + legend order. `ChartSeries` = `{ key: string; label?: string; color?: string }` — each `key` is the datum's y value. |
| `xKey` | `string` | yes | — | Datum key for the numeric x-axis value. |
| `zKey` | `string` | yes | — | Datum key for the bubble-size (z) dimension. |
| `zRange` | `[number, number]` | no | `[60, 600]` | Bubble area range `[min, max]` in px². |
| `height` | `number` | no | `240` | Chart height in px. |
| `...rest` | `Omit<RechartsScatterChartProps, 'data' \| 'children' \| 'width' \| 'height' \| 'ref'>` | no | — | Remaining props spread onto the underlying recharts `<ScatterChart>`. |

## Examples

### Basics

Give it `data`, a numeric `xKey`, a `zKey` for the size dimension, and one or more `series` (each `key` is the y value). Bubble area encodes `zKey` between `zRange`; the fill is a translucent ramp hue with a hairline outline so overlaps stay readable.

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

const data = [
  { risk: 2, impact: 30, effort: 40 },
  { risk: 4, impact: 55, effort: 90 },
  { risk: 5, impact: 80, effort: 60 },
  { risk: 7, impact: 45, effort: 120 },
  { risk: 9, impact: 90, effort: 75 },
];

export default function Demo() {
  return (
    <ChartContainer label="Risk / impact / effort" height={260}>
      <BubbleChart
        data={data}
        xKey="risk"
        zKey="effort"
        series={[{ key: "impact", label: "Impact" }]}
      />
    </ChartContainer>
  );
}
```

## Do & don't

**Do**

- Map a meaningful magnitude to `zKey` — area reads as quantity.
- Wrap it in a ChartContainer so it inherits the `--pds-chart-*` ramp.
- Tune `zRange` so the smallest bubble is still visible and the largest doesn't dominate.
- Give each series a human `label` for the tooltip and legend.

**Don't**

- Don't encode area by radius yourself — pass `zKey` and let recharts scale area.
- Don't use opaque fills that hide overlapping bubbles.
- Don't import it from `@protocore/pds`; it lives on the `/charts` subpath.
- Don't add more than a couple of series — bubbles crowd fast.

## Accessibility

**Notes**

- recharts renders the plot as SVG; provide surrounding context for assistive tech.
- Area encodes magnitude independently of colour, so quantity stays readable in grayscale.

## Related

`scatter-chart`, `chart-container`, `line-chart`

---

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