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

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

> A monochrome-plus-signal composite chart mixing area, bar, and line marks on shared axes, recharts-backed.

## Import path

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

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

## When to use it

Use **CompositeChart** when two related series read best as *different marks on one frame* — volume as bars, a moving average as a line; revenue as an area, margin as a line. When every series is the same kind, use the single-mark wrapper ([LineChart](/charts/line-chart), [AreaChart](/charts/area-chart), [BarChart](/charts/bar-chart)) instead — it is simpler.

Rank marks by role: bars for the base quantity, a line for the signal metric on the accent slot. Every prop beyond `data`/`series`/`xKey`/`height` forwards to the recharts `<ComposedChart>`.

## 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` | `CompositeSeries[]` | yes | — | Series to plot, in draw + legend order. `CompositeSeries` = `{ key: string; label?: string; color?: string; type?: 'area' \| 'bar' \| 'line' }` — `type` defaults to `'line'`. |
| `xKey` | `string` | yes | — | Datum key for the x-axis category. |
| `height` | `number` | no | `240` | Chart height in px. |
| `...rest` | `Omit<RechartsComposedChartProps, 'data' \| 'children' \| 'width' \| 'height' \| 'ref'>` | no | — | Remaining props spread onto the underlying recharts `<ComposedChart>`. |

## Examples

### Basics

Each series declares its own mark `type` — `bar`, `area`, or `line` — and they share the x and y axes. A common pattern: a bar series for volume with a line series for a rate laid over it.

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

const data = [
  { month: "Jan", volume: 120, margin: 12 },
  { month: "Feb", volume: 160, margin: 15 },
  { month: "Mar", volume: 140, margin: 13 },
  { month: "Apr", volume: 200, margin: 18 },
  { month: "May", volume: 175, margin: 16 },
  { month: "Jun", volume: 220, margin: 21 },
];

const series = [
  { key: "volume", label: "Volume", type: "bar" as const },
  { key: "margin", label: "Margin %", type: "line" as const, color: "var(--pds-chart-4)" },
];

export default function Demo() {
  return (
    <ChartContainer
      label="Volume & margin"
      legend={<ChartLegend items={series.map((s) => ({ label: s.label, color: s.color }))} />}
      height={260}
    >
      <CompositeChart data={data} xKey="month" series={series} />
    </ChartContainer>
  );
}
```

## Do & don't

**Do**

- Pair a bar (quantity) with a line (rate) rather than stacking many marks.
- Reserve the signal hue for the line that carries the story.
- Wrap it in a ChartContainer so it inherits the `--pds-chart-*` ramp.
- Give each series a `label` so the tooltip and legend read clearly.

**Don't**

- Don't mix so many mark types that the frame turns to noise.
- Don't use it when a single-mark wrapper would say the same thing.
- Don't import it from `@protocore/pds`; it lives on the `/charts` subpath.
- Don't rely on colour alone to separate marks — mark shape already does.

## Accessibility

**Notes**

- recharts renders the plot as SVG; provide surrounding context for assistive tech.
- Mark shape (bar vs area vs line) distinguishes series independently of colour.

## Related

`line-chart`, `area-chart`, `bar-chart`, `chart-container`

---

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