# StackedArea (/docs/charts/stacked-area)

StackedArea answers "how is the composition shifting over time?" Layer thickness is share; the stack always sums to
100%. Three series is the hard cap — beyond that, thickness at 16 px stops being readable.

```tsx
<StackedArea
  data={[
    { label: "Mobile", values: [30, 34, 36, 40, 44, 47, 52, 56, 58, 60, 63, 66] },
    { label: "Web", values: [50, 48, 47, 45, 42, 41, 38, 36, 35, 33, 32, 30] },
    { label: "API", values: [20, 18, 17, 15, 14, 12, 10, 8, 7, 7, 5, 4] },
  ]}
  title="Traffic mix"
  width={220}
  height={30}
/>
```

## Install

```tsx
import { StackedArea } from "@microcharts/react/stacked-area";

<StackedArea data={mix} title="Traffic mix" />
```

Setup (package + stylesheet): [Quickstart](/docs/quickstart#set-up-with-an-ai-agent) or paste [`/agent-setup.md`](/agent-setup.md) into your agent.


## When to use it

- **Good for** — traffic/revenue mix in KPI cards, share-shift stories in sentences.
- **Avoid for** — 4+ series, or exact values over time (SparkGroup of Sparklines).


## Variants

```tsx
// same stack throughout — a ridge skin, smallest-on-top order, and a localized read
const mix = [
  { label: "Mobile", values: [30, 34, 36, 40, 44, 47, 52, 56, 58, 60, 63, 66] },
  { label: "Web", values: [50, 48, 47, 45, 42, 41, 38, 36, 35, 33, 32, 30] },
  { label: "API", values: [20, 18, 17, 15, 14, 12, 10, 8, 7, 7, 5, 4] },
];

<StackedArea data={mix} mode="ridge" />
<StackedArea data={mix} order="asc" />
<StackedArea data={mix} locale="de-DE" label="last" />
```

`format`/`locale` control the share numbers — the accessible summary and endpoint labels follow the locale's own percent
formatting ("66 %" in German, with a space before the sign, not "66%"). The stack itself never changes shape; only the
announced and printed numbers localize.

## Edge cases

```tsx
<StackedArea data={[{ label: "A", values: [10] }, { label: "B", values: [5] }]} title="Single column" />
```

```tsx
<StackedArea
  data={[
    { label: "A", values: [0, 0, 0, 0] },
    { label: "B", values: [5, 5, 5, 5] },
  ]}
/>
```

A single column still stacks normally — share is well-defined from one point, it's just a vertical slice with no width
to run across. A series pinned at zero collapses to a zero-height layer rather than distorting the others: the remaining
series still sum to 100% of what's left.


## Why this default

Values are normalized to shares before stacking, so the stack reads composition — not magnitude and composition tangled
together. `order="asc"` puts the smallest series on top, where curvature distorts thickness the least.

## Accessibility

The accessible name is the share-shift read — **"3 series over 12 points; Mobile leads at 66% share."** The interactive
entry announces every layer at once (**"Point 8 of 12: Mobile 56%, Web 36%, API 8%."**).

The interactive entry follows the shared [interaction contract](/docs/accessibility#one-interaction-contract):
arrow keys rove between units on both axes, `Home` and `End` jump to the ends, and a click, tap, `Enter` or
`Space` selects a unit — pinning its readout so it survives blur, until you select it again or press `Escape`.
On touch, a tap pins and a drag scrubs.

## Props

| Prop | Type | Description |
| --- | --- | --- |
| `data` (required) | `{ label; values }[]` | ≤ 3 series (hard cap). |
| `mode` | `"stacked" \| "ridge"` | Ridge = same stack, overlapping-crest skin. |
| `order` | `"data" \| "asc"` | "asc" puts the smallest series on top (least distortion). |
| `label` | `"last" \| "none"` | Endpoint share labels per series (deterministic drop-out). |
| `labelAt` | `number` | Column whose shares feed label="last" (default: final column). The interactive entry passes the focused column so the labels track the crosshair. |
| `curve` | `"linear" \| "smooth" \| "step"` | Line interpolation (default linear); ridge forces smooth. |
| `colors` | `string[]` | Per-series colours, cycled; overrides --mc-cat-N. |
| `animate` | `boolean` | (interactive) Opt-in entrance motion when the chart mounts client-side — add `import "@microcharts/react/motion"` once. Inert on the server, on hydrated server HTML, and under `prefers-reduced-motion`. |

Plus the shared grammar — `data`, `domain`, `color`, `title`, `summary`, `format` — and the layout props (`width`, `height`, `className`, `style`) that every chart accepts. Interactive entries also share `animate` and `live`, and — wherever a chart has more than one navigable unit — `onActive`, `onSelect`, `selectedIndex` and `defaultSelectedIndex`; and — wherever the chart shows a hover value — `readout`. See [the shared grammar](/docs/quickstart#the-shared-grammar).
