# Area Chart

Lines over shaded areas, for totals that change over time.

Source: [area-chart.tsx](https://github.com/jakejarvis/jarvis-ui/blob/main/src/components/ui/area-chart.tsx)

```tsx
import { AreaChart, AreaChartSeries } from "@/components/ui/area-chart";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import {
  ChartGrid,
  ChartLegend,
  ChartTooltip,
  ChartXAxis,
  type ChartConfig,
} from "@/components/ui/chart";

const data = [
  { month: "January", desktop: 186, mobile: 80 },
  { month: "February", desktop: 305, mobile: 200 },
  { month: "March", desktop: 237, mobile: 120 },
  { month: "April", desktop: 273, mobile: 190 },
  { month: "May", desktop: 209, mobile: 130 },
  { month: "June", desktop: 314, mobile: 140 },
  { month: "July", desktop: 268, mobile: 175 },
  { month: "August", desktop: 342, mobile: 210 },
  { month: "September", desktop: 296, mobile: 184 },
  { month: "October", desktop: 358, mobile: 226 },
  { month: "November", desktop: 331, mobile: 203 },
  { month: "December", desktop: 389, mobile: 248 },
];

const config = {
  desktop: { label: "Desktop" },
  mobile: { label: "Mobile" },
} satisfies ChartConfig;

export default function AreaChartStacked() {
  return (
    <Card className="w-full">
      <CardHeader>
        <CardTitle>Visitors</CardTitle>
        <CardDescription>January to December 2025</CardDescription>
      </CardHeader>
      <CardContent>
        <AreaChart
          data={data}
          config={config}
          stack="stacked"
          className="aspect-[4/3] sm:aspect-[2/1]"
        >
          <ChartGrid />
          <ChartXAxis dataKey="month" tickFormatter={(month: string) => month.slice(0, 3)} />
          <ChartTooltip />
          <ChartLegend />
          <AreaChartSeries dataKey="mobile" />
          <AreaChartSeries dataKey="desktop" />
        </AreaChart>
      </CardContent>
    </Card>
  );
}
```

## Installation

Add the registry, once per project:

```bash
npx shadcn@latest registry add @jarvis=https://ui.jarv.is/r/{name}.json
```

Then add the component:

```bash
npx shadcn@latest add @jarvis/area-chart
```

## Usage

```tsx
import { AreaChart, AreaChartSeries } from "@/components/ui/area-chart";
import { ChartTooltip, ChartXAxis, type ChartConfig } from "@/components/ui/chart";

const data = [
  { month: "January", visitors: 186 },
  { month: "February", visitors: 305 },
  { month: "March", visitors: 237 },
];

const config = {
  visitors: { label: "Visitors" },
} satisfies ChartConfig;

export function VisitorsChart() {
  return (
    <AreaChart data={data} config={config}>
      <ChartXAxis dataKey="month" />
      <ChartTooltip />
      <AreaChartSeries dataKey="visitors" />
    </AreaChart>
  );
}
```

`AreaChartSeries` draws one series. The axes, tooltip, legend and config come from
[Chart](https://ui.jarv.is/components/chart.md). Stacked series stack in the order they're written, first at the bottom.

## Composition

- `AreaChart`
  - [`ChartGrid`](https://ui.jarv.is/components/chart.md)
  - [`ChartXAxis`](https://ui.jarv.is/components/chart.md)
  - [`ChartYAxis`](https://ui.jarv.is/components/chart.md)
  - [`ChartTooltip`](https://ui.jarv.is/components/chart.md)
  - [`ChartLegend`](https://ui.jarv.is/components/chart.md)
  - `AreaChartSeries`

## Examples

### Fills

`variant` fills the area with a gradient, a flat tint or hatching.

```tsx
import { AreaChart, AreaChartSeries } from "@/components/ui/area-chart";
import { ChartLegend, ChartTooltip, ChartXAxis, type ChartConfig } from "@/components/ui/chart";

const data = [
  { month: "January", desktop: 186, mobile: 80 },
  { month: "February", desktop: 305, mobile: 200 },
  { month: "March", desktop: 237, mobile: 120 },
  { month: "April", desktop: 273, mobile: 190 },
  { month: "May", desktop: 209, mobile: 130 },
  { month: "June", desktop: 314, mobile: 140 },
];

const config = {
  desktop: { label: "Desktop" },
  mobile: { label: "Mobile" },
} satisfies ChartConfig;

export default function AreaChartFills() {
  return (
    <AreaChart data={data} config={config} stack="stacked" className="max-w-lg">
      <ChartXAxis dataKey="month" tickFormatter={(month: string) => month.slice(0, 3)} />
      <ChartTooltip />
      <ChartLegend />
      <AreaChartSeries dataKey="mobile" variant="hatched" />
      <AreaChartSeries dataKey="desktop" variant="solid" />
    </AreaChart>
  );
}
```

### Expanded

`stack="expanded"` stretches each stack to full height to show shares.

```tsx
import { AreaChart, AreaChartSeries } from "@/components/ui/area-chart";
import {
  ChartGrid,
  ChartLegend,
  ChartTooltip,
  ChartXAxis,
  ChartYAxis,
  type ChartConfig,
} from "@/components/ui/chart";

const data = [
  { month: "January", desktop: 186, mobile: 80, tablet: 42 },
  { month: "February", desktop: 305, mobile: 200, tablet: 61 },
  { month: "March", desktop: 237, mobile: 120, tablet: 58 },
  { month: "April", desktop: 273, mobile: 190, tablet: 70 },
  { month: "May", desktop: 209, mobile: 130, tablet: 49 },
  { month: "June", desktop: 314, mobile: 140, tablet: 66 },
];

const config = {
  desktop: { label: "Desktop" },
  mobile: { label: "Mobile" },
  tablet: { label: "Tablet" },
} satisfies ChartConfig;

export default function AreaChartExpanded() {
  return (
    <AreaChart data={data} config={config} stack="expanded" className="max-w-lg">
      <ChartGrid />
      <ChartXAxis dataKey="month" tickFormatter={(month: string) => month.slice(0, 3)} />
      <ChartYAxis tickFormatter={(share: number) => `${Math.round(share * 100)}%`} />
      <ChartTooltip />
      <ChartLegend />
      <AreaChartSeries dataKey="tablet" />
      <AreaChartSeries dataKey="mobile" />
      <AreaChartSeries dataKey="desktop" />
    </AreaChart>
  );
}
```

### Forecast

A dashed, hatched series reads as an estimate. Leave a value out of a row to break the line.

```tsx
import { AreaChart, AreaChartSeries } from "@/components/ui/area-chart";
import {
  ChartGrid,
  ChartLegend,
  ChartTooltip,
  ChartXAxis,
  ChartYAxis,
  type ChartConfig,
} from "@/components/ui/chart";

const data = [
  { month: "January", actual: 1240 },
  { month: "February", actual: 1380 },
  { month: "March", actual: 1310 },
  { month: "April", actual: 1520 },
  { month: "May", actual: 1610 },
  { month: "June", actual: 1740, forecast: 1740 },
  { month: "July", forecast: 1830 },
  { month: "August", forecast: 1960 },
  { month: "September", forecast: 2080 },
];

const config = {
  actual: { label: "Actual" },
  forecast: { label: "Forecast", color: "var(--chart-5)" },
} satisfies ChartConfig;

export default function AreaChartForecast() {
  return (
    <AreaChart data={data} config={config} className="max-w-lg">
      <ChartGrid />
      <ChartXAxis dataKey="month" tickFormatter={(month: string) => month.slice(0, 3)} />
      <ChartYAxis tickFormatter={(signups: number) => signups.toLocaleString("en-US")} />
      <ChartTooltip />
      <ChartLegend />
      <AreaChartSeries dataKey="actual" dots />
      <AreaChartSeries dataKey="forecast" variant="hatched" dashed />
    </AreaChart>
  );
}
```

## Props

| Part | Extends |
| --- | --- |
| `AreaChart` | [`Chart`](https://ui.jarv.is/components/chart.md) |
| `AreaChartSeries` | `Area` |

### AreaChart

| Prop        | Type                                | Description                                                                                                                                  |
| ----------- | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `config`    | `ChartConfig`                       | Each series' label, icon and color, keyed by its data key.                                                                                   |
| `data`      | `Record<string, unknown>[]`         | The rows to plot, one object per point along the x-axis.                                                                                     |
| `stack?`    | `"expanded" \| "none" \| "stacked"` | How the series combine: drawn over each other, stacked, or stacked and scaled to fill the height, so each shows its share. Default: `"none"` |
| `curve?`    | `CurveType`                         | How lines between points are drawn. A series can set its own. Default: `"monotone"`                                                          |
| `children?` | `React.ReactNode`                   |                                                                                                                                              |

### AreaChartSeries

| Prop       | Type                                 | Description                                                                   |
| ---------- | ------------------------------------ | ----------------------------------------------------------------------------- |
| `dataKey`  | `string`                             | The key of the series' values in each row, which also names it in the config. |
| `variant?` | `"gradient" \| "hatched" \| "solid"` | How the area under the line is filled. Default: `"gradient"`                  |
| `curve?`   | `CurveType`                          | How lines between points are drawn. Defaults to the chart's `curve`.          |
| `dashed?`  | `boolean`                            | Draws the line dashed, as for a forecast. Default: `false`                    |
| `dots?`    | `boolean`                            | Marks every point, not just the hovered one. Default: `false`                 |

`AreaChartSeries` takes the props of Recharts'
[`Area`](https://recharts.github.io/en-US/api/Area/) too, such as `connectNulls`.
