# AreaChart

A filled series over a continuous axis, where the area means something.

- Group: Charts
- Import: `import { AreaChart } from '@misoto22/folio/charts'`
- Page: https://ui.misoto22.com/components/area-chart/
- Related: line-chart, bar-chart, composed-chart

## When to reach for it

Reading one magnitude over time. Comparing several series against each other is a LineChart — four translucent fills stacked on each other answer neither question.

## Anatomy

- **Figure frame** (required) — The <figure> ChartFigure draws, named through aria-labelledby rather than left to the figcaption, because deriving a name from a <figcaption> resolves in only some screen readers. The caption holds title and description together and is sr-only until showTitle is set, so a caveat written into description is announced and never printed.
- **Plot** (required) — ChartContainer: a 16:9 box floored at 13rem and capped at 26rem, and the one place Recharts’ hard-coded #ccc axis and grid strokes are re-pointed at --chart-grid and --chart-axis.
- **Areas** (required) — <AreaChart.Area>, one per series. Each generates its own id and scopes its gradient, its texture pattern and its reveal mask under it, so six variants share a plot without one overwriting another’s definitions.
- **Brush strip** — <AreaChart.Brush>, rendered in the container’s footer rather than inside the SVG. Both handles are role="slider" with aria-valuetext naming the row they sit on, so the window is reachable by arrow key.
- **Toolbar** — <AreaChart.Toolbar>, a role="group" row of at most five 44px icon buttons above the plot. Composing it also switches the plot’s own wheel, drag and keyboard zoom on, and the two drive one window rather than two.
- **Hidden data table** — An sr-only <table> built from the FULL data rather than the brushed window, so a reader on the table is never shown less than the CSV export holds. hideDataTable removes it, and zero rows render nothing.

## Best practices

### Do

- Stack only quantities that genuinely add up. Under stackType="stacked" a band’s HEIGHT is its own value but its POSITION is the sum of everything under it, so stacking four independent rates draws a running total nobody measured.
- Reach for stackType="expanded" when the reading is share rather than volume: it sets Recharts’ expand offset and <AreaChart.YAxis> swaps in percentTick on its own, so the axis reads 0% to 100% without a formatter at the call site. A tickFormatter of your own still wins — the axis defers to it rather than dropping it, which it used to do without a word.
- Vary variant before the ramp on a two-area chart. The six fills are the primary encoding in the monochrome default, and under forced colours every --series-* token resolves to CanvasText — at which point the texture is the only thing left separating two areas.
- Pass xDataKey. It is the rowKey of the hidden table, and without it the table renders no row-header column at all: a screen reader gets a column of numbers with no month beside them.

### Don’t

- Four translucent fills over each other is this form’s failure mode — the third area is read through two layers of --chart-fill and its own height stops being recoverable. Several series compared against each other is a LineChart, where nothing occludes anything.
- connectNulls defaults to false for a reason: turned on, a gap in the data is drawn as a straight segment indistinguishable from a measured flat period. Set it only where the gap is a rendering artefact rather than a missing observation.
- A single row draws nothing. One point has no segment to fill, dot is false unless <AreaChart.Dot> is composed, and the empty state does not fire because there IS a row — so the axes render over a blank plot.

## Accessibility

- title is required and becomes the figure’s accessible name, printed or not.
- The rows are rendered again as a visually hidden table, so the numbers are reachable rather than only drawn. hideDataTable opts out when the page already prints them.
- Six fill variants exist because in the monochrome default TEXTURE is the primary carrier of identity and the grey ramp is the second — which is also what keeps two series apart in greyscale print and under forced colours.
- The intro reveal is a per-frame SVG mask and is dropped entirely under prefers-reduced-motion, as is the crawling dash.

## Keyboard

- Tab — Reaches the plot, which Recharts’ accessibility layer makes navigable.
- ← / → — Moves the cursor between points, announcing each.

## AreaChart

A filled series over a category axis — the shape for a magnitude that is continuous, where the area under the line means something. Composed rather than configured: axes, grid, tooltip, legend and the areas themselves are children, so a chart renders exactly the parts it asked for and nothing is switched on by a prop nobody can see. Reach for `<LineChart>` instead when the reader is comparing several series against each other rather than reading one total, and for `<BarChart>` when the categories are discrete.

### Props

- `config` (required) — `TConfig & ValidateKeys<TData, TConfig>`. Series keys → their label and paint. Declaration order is ramp order.
- `data` (required) — `TData[]`. The rows the chart draws. One entry per point, bar or category.
- `title` (required) — `string`. What the chart shows, in a sentence a reader could act on. Required, and announced to a screen reader even when it is not printed.
- `showTitle` — `boolean`. Prints the title above the plot instead of hiding it from sight.
- `description` — `ReactNode`. A line under the title — the unit, the window, the caveat.
- `children` (required) — `ReactNode`. The composed parts — axes, grid, tooltip, legend, and the marks themselves.
- `className` — `string`. Merged onto the figure, last, so a call site can size or space it.
- `chartProps` — `ComponentProps<typeof RechartsAreaChart>`. Escape hatch onto the raw Recharts chart element.
- `curveType` — `ChartCurveType` default `'linear'`. The curve every `<AreaChart.Area>` inherits.
- `animationType` — `ChartRevealType` default `'forward'`. The intro wipe every `<AreaChart.Area>` inherits.
- `stackType` — `AreaStackType` default `'default'`. How several marks combine: side by side, stacked, or normalised to 100%.
- `defaultSelectedDataKey` — `string | null` default `null`. The series lit on first render, when the chart keeps its own selection.
- `selectedDataKey` — `string | null`. The selected series, driven from outside. Give this and the chart follows it; leave it undefined and the chart keeps its own, starting from `defaultSelectedDataKey`.
- `onSelectionChange` — `(selectedDataKey: string | null) => void`. Fires when the selection changes, and with null when it is cleared.
- `isLoading` — `boolean` default `false`. Swaps the marks for an animated skeleton, keeping the measured height so the page does not jump when the data lands.
- `loadingPoints` — `number`. How many points the skeleton draws.
- `xDataKey` — `keyof TData & string`. The row field on the category axis. Needed by the brush and by the table view.
- `hideDataTable` — `boolean` default `false`. Drops the hidden table view. Only correct when the page prints the data itself.
- `empty` — `ChartEmptyProps | false`. What the chart shows when it has nothing to draw. Rendered instead of the plot whenever `data` is empty and the chart is not loading — the state a real dashboard reaches within a week, and the one an empty pair of axes is indistinguishable from a failed load. `false` keeps the axes, for a chart whose emptiness is itself the reading.

## Example — default

```tsx
import { AreaChart, type ChartConfig } from '@misoto22/folio/charts'

<AreaChart title="Visitors per month" config={config} data={data} xDataKey="month">
  <AreaChart.Grid />
  <AreaChart.XAxis dataKey="month" />
  <AreaChart.YAxis />
  <AreaChart.Legend />
  <AreaChart.Tooltip />
  <AreaChart.Area dataKey="desktop" />
  <AreaChart.Area dataKey="mobile" variant="hatched" />
</AreaChart>
```

## Example — fill variants

```tsx
import { ToggleGroup, ToggleGroupItem } from '@misoto22/folio'
import { AreaChart, type AreaVariant, type ChartConfig } from '@misoto22/folio/charts'

<div className="flex w-full flex-col gap-4">
  <ToggleGroup
    type="single"
    value={variant}
    onValueChange={(next) => next && setVariant(next as AreaVariant)}
    aria-label="Fill variant"
  >
    {VARIANTS.map((option) => (
      <ToggleGroupItem key={option} value={option}>
        {option}
      </ToggleGroupItem>
    ))}
  </ToggleGroup>

  <AreaChart title={`Visitors per month — ${variant} fill`} config={config} data={data}>
    <AreaChart.Grid />
    <AreaChart.XAxis dataKey="month" />
    <AreaChart.Tooltip />
    <AreaChart.Area dataKey="desktop" variant={variant} />
  </AreaChart>
</div>
```

## Example — stroke and curve

```tsx
import { ToggleGroup, ToggleGroupItem } from '@misoto22/folio'

<div className="flex w-full flex-col gap-4">
  <div className="flex flex-wrap gap-3">
    <ToggleGroup
      type="single"
      value={stroke}
      onValueChange={(next) => next && setStroke(next as AreaStrokeVariant)}
      aria-label="Stroke"
    >
      {STROKES.map((option) => (
        <ToggleGroupItem key={option} value={option}>
          {option}
        </ToggleGroupItem>
      ))}
    </ToggleGroup>

    <ToggleGroup
      type="single"
      value={String(curve)}
      onValueChange={(next) => next && setCurve(next as ChartCurveType)}
      aria-label="Curve"
    >
      {CURVES.map((option) => (
        <ToggleGroupItem key={option} value={option}>
          {option}
        </ToggleGroupItem>
      ))}
    </ToggleGroup>
  </div>

  <AreaChart title="Visitors per month" config={config} data={data} curveType={curve}>
    <AreaChart.Grid />
    <AreaChart.XAxis dataKey="month" />
    <AreaChart.Tooltip />
    <AreaChart.Area dataKey="desktop" variant="solid" strokeVariant={stroke} />
  </AreaChart>
</div>
```

## Example — stacking

```tsx
import { ToggleGroup, ToggleGroupItem } from '@misoto22/folio'
import { AreaChart, type AreaStackType, type ChartConfig } from '@misoto22/folio/charts'

<div className="flex w-full flex-col gap-4">
  <ToggleGroup
    type="single"
    value={stackType}
    onValueChange={(next) => next && setStackType(next as AreaStackType)}
    aria-label="Stacking"
  >
    {STACKS.map((option) => (
      <ToggleGroupItem key={option} value={option}>
        {option}
      </ToggleGroupItem>
    ))}
  </ToggleGroup>

  <AreaChart
    title={`Visitors per month — ${stackType}`}
    config={config}
    data={data}
    stackType={stackType}
  >
    <AreaChart.Grid />
    <AreaChart.XAxis dataKey="month" />
    <AreaChart.YAxis />
    <AreaChart.Legend />
    <AreaChart.Tooltip />
    <AreaChart.Area dataKey="desktop" variant="solid" />
    <AreaChart.Area dataKey="mobile" variant="lines" />
  </AreaChart>
</div>
```

## Example — dots and reveal

```tsx
import { ToggleGroup, ToggleGroupItem } from '@misoto22/folio'

<div className="flex w-full flex-col gap-4">
  <div className="flex flex-wrap gap-3">
    <ToggleGroup
      type="single"
      value={dot}
      onValueChange={(next) => next && setDot(next as ChartDotVariant)}
      aria-label="Dot"
    >
      {DOTS.map((option) => (
        <ToggleGroupItem key={option} value={option}>
          {option}
        </ToggleGroupItem>
      ))}
    </ToggleGroup>

    <ToggleGroup
      type="single"
      value={reveal}
      onValueChange={(next) => next && setReveal(next as ChartRevealType)}
      aria-label="Reveal"
    >
      {REVEALS.map((option) => (
        <ToggleGroupItem key={option} value={option}>
          {option}
        </ToggleGroupItem>
      ))}
    </ToggleGroup>
  </div>

  <AreaChart
    key={`${dot}-${reveal}`}
    title="Visitors per month"
    config={config}
    data={data}
    animationType={reveal}
  >
    <AreaChart.Grid />
    <AreaChart.XAxis dataKey="month" />
    <AreaChart.Tooltip />
    <AreaChart.Area dataKey="desktop" variant="solid">
      <AreaChart.Dot variant={dot} />
      <AreaChart.ActiveDot variant="colored-border" />
    </AreaChart.Area>
  </AreaChart>
</div>
```

## Example — brush

```tsx
import { AreaChart, type ChartConfig } from '@misoto22/folio/charts'

<AreaChart title="Visitors per day" config={config} data={data} xDataKey="day">
  <AreaChart.Grid />
  <AreaChart.XAxis dataKey="day" />
  <AreaChart.Tooltip />
  <AreaChart.Area dataKey="desktop" variant="gradient" />
  <AreaChart.Brush height={56} />
</AreaChart>
```

## Example — loading

```tsx
import { AreaChart, type ChartConfig } from '@misoto22/folio/charts'

<AreaChart title="Visitors per month" config={config} data={[]} isLoading>
  <AreaChart.Grid />
  <AreaChart.Area dataKey="desktop" />
</AreaChart>
```

## Example — chroma palette

```tsx
import { AreaChart, type ChartConfig } from '@misoto22/folio/charts'

<div data-chart-palette="chroma" className="w-full">
  <AreaChart title="Visitors per month" config={config} data={data} xDataKey="month">
    <AreaChart.Grid />
    <AreaChart.XAxis dataKey="month" />
    <AreaChart.Legend />
    <AreaChart.Tooltip />
    <AreaChart.Area dataKey="desktop" variant="gradient" />
    <AreaChart.Area dataKey="mobile" variant="solid" />
    <AreaChart.Area dataKey="tablet" variant="lines" />
  </AreaChart>
</div>
```

## Example — annotations

```tsx
import { AreaChart, type ChartConfig } from '@misoto22/folio/charts'

<AreaChart title="Visitors per month" config={config} data={data} xDataKey="month">
  <AreaChart.Grid />
  <AreaChart.XAxis dataKey="month" />
  <AreaChart.YAxis label="Visitors" />
  <AreaChart.Tooltip />

  <AreaChart.ReferenceBand x={['Mar', 'Apr']} label="Migration" />
  <AreaChart.ReferenceLine y={250} label="Target" weight="firm" />
  <AreaChart.Annotation x="Mar" y={148} text="Deploy freeze" showAnchor />

  <AreaChart.Area dataKey="desktop" variant="solid" />
</AreaChart>
```

## Example — empty

```tsx
import { AreaChart, type ChartConfig } from '@misoto22/folio/charts'

<AreaChart
  title="Visitors per month"
  config={config}
  data={[]}
  empty={{
    title: 'No visits in this range',
    description: 'This project had no traffic before March. Try a wider range.',
  }}
>
  <AreaChart.Grid />
  <AreaChart.Area dataKey="desktop" />
</AreaChart>
```

## Example — sonify

```tsx
import { AreaChart, type ChartConfig } from '@misoto22/folio/charts'

<AreaChart title="Visitors per month" config={config} data={data} xDataKey="month">
  <AreaChart.Sonify />
  <AreaChart.Grid />
  <AreaChart.XAxis dataKey="month" />
  <AreaChart.YAxis label="Visitors" />
  <AreaChart.Tooltip />
  <AreaChart.Area dataKey="desktop" variant="gradient" />
</AreaChart>
```
