# Area Chart

> A composable area chart with gradient fills, tooltips, and hover interactions

Source: https://ui.cortexcn.dev/docs/charts/area-chart

## Installation

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

## Usage

The Area Chart uses the same composable API as the Line Chart. See the [charts gallery](https://ui.cortexcn.dev/charts/area-chart) for interactive examples.

```tsx
import { AreaChart, Area, Grid, XAxis, ChartTooltip } from "@/components/charts";

const data = [
  { date: new Date("2025-01-01"), revenue: 12000, costs: 8500 },
  { date: new Date("2025-01-02"), revenue: 13500, costs: 9200 },
  // ... more data
];

export default function RevenueChart() {
  return (
    <AreaChart data={data}>
      <Grid horizontal />
      <Area dataKey="revenue" fill="var(--chart-line-primary)" />
      <Area dataKey="costs" fill="var(--chart-line-secondary)" />
      <XAxis />
      <ChartTooltip />
    </AreaChart>
  );
}
```

## Components

### AreaChart

The root component that provides context to all children. It shares the same props as `LineChart`.

| Prop                          | Type                        | Default                                        | Description                                                     |
| ----------------------------- | --------------------------- | ---------------------------------------------- | --------------------------------------------------------------- |
| `data`                        | `Record<string, unknown>[]` | required                                       | Array of data points                                            |
| `xDataKey`                    | `string`                    | `"date"`                                       | Key in data for x-axis values                                   |
| `margin`                      | `Partial<Margin>`           | `{ top: 40, right: 40, bottom: 40, left: 40 }` | Chart margins                                                   |
| `animationDuration`           | `number`                    | `1100`                                         | Clip-reveal duration in ms (`cubic-bezier(0.85, 0, 0.15, 1)`)   |
| `status`                      | `"loading" \| "ready"`      | `"ready"`                                      | Loading ↔ ready choreography on one chart instance              |
| `loadingLabel`                | `string`                    | —                                              | Centered shimmer label while `status="loading"` (`""` hides it) |
| `yDomainTween`                | `boolean`                   | `true`                                         | Animate y-domain when status or target domain changes           |
| `yDomainTweenDuration`        | `number`                    | `500`                                          | Y-domain tween duration in ms                                   |
| `xDomain`                     | `[Date, Date]`              | —                                              | Visible x-range for brush zoom                                  |
| `xDomainSlotCount`            | `number`                    | —                                              | Full dataset length for x-scale padding when `xDomain` is set   |
| `tweenYDomainOnXDomainChange` | `boolean`                   | `false`                                        | Tween y-domain when the brush changes the visible x-range       |
| `aspectRatio`                 | `string`                    | `"2 / 1"`                                      | CSS aspect ratio                                                |
| `className`                   | `string`                    | `""`                                           | Additional CSS class                                            |
| `style`                       | `CSSProperties`             | —                                              | Inline container styles (e.g. fixed height for a brush strip)   |

### Area

Renders a filled area on the chart with a gradient fill.

| Prop                   | Type                     | Default                     | Description                                                                  |
| ---------------------- | ------------------------ | --------------------------- | ---------------------------------------------------------------------------- |
| `dataKey`              | `string`                 | required                    | Key in data for y values                                                     |
| `yAxisId`              | `string \| number`       | `"left"`                    | Y-scale group for biaxial charts (pair with `YAxis`)                         |
| `fill`                 | `string`                 | `var(--chart-line-primary)` | Gradient fill color                                                          |
| `fillOpacity`          | `number`                 | `0.4`                       | Fill opacity at the top                                                      |
| `stroke`               | `string`                 | Same as `fill`              | Line stroke color                                                            |
| `strokeWidth`          | `number`                 | `2`                         | Line stroke width                                                            |
| `curve`                | `CurveFactory`           | `curveMonotoneX`            | D3 curve function                                                            |
| `animate`              | `boolean`                | `true`                      | Enable grow animation                                                        |
| `showLine`             | `boolean`                | `true`                      | Show stroke line on top                                                      |
| `showHighlight`        | `boolean`                | `true`                      | Show highlight on hover                                                      |
| `gradientToOpacity`    | `number`                 | `0`                         | Opacity at bottom of gradient                                                |
| `fadeEdges`            | `boolean`                | `false`                     | Fade area fill at left/right edges                                           |
| `showMarkers`          | `boolean`                | `false`                     | Render scatter-style ring markers at each point                              |
| `loadingStroke`        | `string`                 | `var(--foreground)`         | Pulse stroke color while chart is loading                                    |
| `loadingStrokeOpacity` | `number`                 | `0.5`                       | Pulse stroke opacity while chart is loading                                  |
| `markers`              | `SeriesPointMarkerStyle` | —                           | Marker styling (same options as [`Scatter`](https://ui.cortexcn.dev/docs/charts/scatter-chart)) |

### PatternArea

Renders a filled area using an SVG pattern (`url(#id)`). Define the pattern (e.g. `PatternLines`) as a child of `AreaChart`, then pair `PatternArea` with an `Area` that has `fillOpacity={0}` for the stroke line.

| Prop      | Type           | Default          | Description                                         |
| --------- | -------------- | ---------------- | --------------------------------------------------- |
| `dataKey` | `string`       | required         | Key in data for y values                            |
| `fill`    | `string`       | required         | Fill color or pattern URL (e.g. `url(#pattern-id)`) |
| `curve`   | `CurveFactory` | `curveMonotoneX` | D3 curve function                                   |

### Grid

Renders grid lines.

| Prop              | Type      | Default                                 | Description                                                       |
| ----------------- | --------- | --------------------------------------- | ----------------------------------------------------------------- |
| `horizontal`      | `boolean` | `true`                                  | Show horizontal lines                                             |
| `vertical`        | `boolean` | `false`                                 | Show vertical lines                                               |
| `numTicksRows`    | `number`  | `5`                                     | Number of horizontal lines                                        |
| `numTicksColumns` | `number`  | `10`                                    | Number of vertical lines                                          |
| `stroke`          | `string`  | `var(--chart-grid)`                     | Line color while ready                                            |
| `loadingStroke`   | `string`  | —                                       | Grid stroke while loading chrome is active                        |
| `strokeDasharray` | `string`  | `"4,4"`                                 | Dash pattern                                                      |
| `shimmer`         | `boolean` | `false`                                 | Animate a shimmer band across horizontal grid lines               |
| `shimmerStroke`   | `string`  | `color-mix(…)` on `--foreground` at 68% | Shimmer band color and opacity                                    |
| `shimmerLength`   | `number`  | `140`                                   | Shimmer band width in pixels                                      |
| `shimmerSpeed`    | `number`  | `1`                                     | Shimmer speed multiplier when sync is off (higher = faster)       |
| `shimmerSync`     | `boolean` | `false`                                 | Match shimmer timing to the line pulse (2.2s cycle + 280ms pause) |

### Background

Pattern fill for the plot area when you omit `Grid`. See the [Background utility](https://ui.cortexcn.dev/docs/utility/background) and **Pattern Background** examples on the [area chart gallery](https://ui.cortexcn.dev/charts/area-chart).

### YAxis

Value labels on the left or right. See [Y Axis](https://ui.cortexcn.dev/docs/utility/axis/y-axis) for `yAxisId`, `orientation`, and biaxial usage.

### XAxis

Renders x-axis labels that fade when the crosshair passes.

| Prop              | Type                 | Default  | Description                                                                                  |
| ----------------- | -------------------- | -------- | -------------------------------------------------------------------------------------------- |
| `numTicks`        | `number`             | `5`      | Number of tick labels to show                                                                |
| `tickerHalfWidth` | `number`             | `50`     | Fade radius for labels                                                                       |
| `tickMode`        | `"data" \| "domain"` | `"data"` | `"data"` snaps labels to data rows (crosshair-aligned); `"domain"` for calendar-even spacing |

### ChartTooltip

Renders the tooltip with crosshair, dots, and content box.

| Prop                  | Type                                    | Default  | Description                                               |
| --------------------- | --------------------------------------- | -------- | --------------------------------------------------------- |
| `showDatePill`        | `boolean`                               | `true`   | Show animated date ticker                                 |
| `showCrosshair`       | `boolean`                               | `true`   | Show vertical crosshair                                   |
| `showDots`            | `boolean`                               | `true`   | Show dots on series                                       |
| `indicatorColor`      | `string \| (point) => string`           | —        | Crosshair and dot color                                   |
| `indicatorDasharray`  | `string`                                | —        | Dash pattern for the crosshair (e.g. `"4,4"`)             |
| `indicatorFadeEdges`  | `"both" \| "top" \| "bottom" \| "none"` | `"both"` | Vertical crosshair fade                                   |
| `indicatorFadeLength` | `number`                                | `10`     | Fade size (% of height)                                   |
| `matchCrosshair`      | `boolean`                               | `false`  | Panel uses crosshair spring when `true`                   |
| `damping`             | `number`                                | `20`     | Panel follow when `matchCrosshair={false}`; `0` = instant |
| `content`             | `(props) => ReactNode`                  | -        | Custom content renderer                                   |
| `rows`                | `(point) => TooltipRow[]`               | -        | Custom row generator                                      |

## Brush zoom

See the [Brush](https://ui.cortexcn.dev/docs/utility/brush) utility docs for `ChartBrushLayout` and `ChartBrush` props.

Wrap the main chart in `ChartBrushLayout`, render a simplified mini chart in `brushStrip`, and add `ChartBrush` as a child of that strip. Pass `xDomain`, `xDomainSlotCount`, and `tweenYDomainOnXDomainChange` to the main `AreaChart` so the y-scale adapts as users pan and resize the brush.

<div className="not-prose mb-3 flex items-center justify-between gap-4">
  <h3 className="m-0 font-semibold text-foreground text-base tracking-tight">
    Preview
  </h3>
</div>

## Loading state

Drive loading and ready from your data layer with a single `AreaChart` — one `Grid`, one `Area`, no component swap. Set `status="loading"` while fetching; switch to `"ready"` when data resolves.

**Loading → ready:** pulse loop on skeleton data → pulse finishes its grow, then flows out right → loading label drifts down 30px, blurs, and fades → grid y-domain tween (500ms) → clip-path reveal (`cubic-bezier(0.85, 0, 0.15, 1)`) → interaction enabled.

**Ready → loading:** ready area conceals to the right → grid y-domain tween → pulse loop and shimmer resume.

Pair `Grid` `stroke` / `loadingStroke` with shimmer props. Pair `Area` `loadingStroke` props. Use `loadingLabel` on `AreaChart` for centered shimmer text via `@cortexcn/shimmering-text`.

<div className="not-prose mb-3 flex items-center justify-between gap-4">
  <h3 className="m-0 font-semibold text-foreground text-base tracking-tight">
    Preview
  </h3>
</div>

Toggle **Loading** / **Ready** in the preview to replay the transition, and **Pulse** / **Sweep** to switch the loading animation style. When target data spans a different y-range than the skeleton, `yDomainTween` morphs the scale before the area reveals.

Installing `@cortexcn/area-chart` pulls in `@cortexcn/shimmering-text` automatically.

### Loading style: pulse or sweep

The loading state has two animation styles, set with `loadingStyle` on the `Area`: the default `"pulse"` (a segment travels along the skeleton stroke) or `"sweep"` (a soft diagonal shimmer sweeps across the whole area). Set it on the `Area` inside a `status="loading"` chart, or on the `AreaChartLoading` wrapper:

```tsx
<AreaChart data={data} status="loading">
  <Grid horizontal shimmer />
  <Area dataKey="revenue" loadingStyle="sweep" />
</AreaChart>

// or, with the turnkey wrapper:
<AreaChartLoading loadingStyle="sweep" />;
```

The sweep masks over the real skeleton stroke, so it follows whatever `curve` the `Area` uses and respects `prefers-reduced-motion`. The sweep is used only during steady loading; the pulse still drives the exit transition. See the **Loading (Sweep)** example on the [area chart gallery](https://ui.cortexcn.dev/charts/area-chart).

## Dashed tail

Set `dashFromIndex` on `Area` to draw a solid stroke through one data point, then a dashed segment through the end of the series. Useful when the final period is still in progress (e.g. yesterday → today).

`dashFromIndex` is **inclusive** — dashing starts at that row and continues through the last point. The dashed segment follows the same curved path as the solid stroke and respects the stroke gradient fade from `fadeEdges`.

| Prop            | Type     | Default | Description                                         |
| --------------- | -------- | ------- | --------------------------------------------------- |
| `dashFromIndex` | `number` | —       | Inclusive data index where the dashed tail begins   |
| `dashArray`     | `string` | `"6,4"` | SVG `stroke-dasharray` pattern for the tail segment |

```tsx
<Area
  dataKey="visitors"
  dashFromIndex={5}
  dashArray="6,4"
  fill="var(--chart-line-primary)"
  fillOpacity={0.35}
/>
```

## Markers

Add markers to annotate specific dates on the chart:

```tsx
import {
  AreaChart,
  Area,
  ChartTooltip,
  ChartMarkers,
  MarkerTooltipContent,
  useActiveMarkers,
  type ChartMarker,
} from "@/components/charts";

const markers: ChartMarker[] = [
  {
    date: new Date("2025-01-05"),
    icon: "🚀",
    title: "v1.2.0 Released",
    description: "New chart animations",
  },
];

function MyChart({ data }) {
  return (
    <AreaChart data={data}>
      <Area dataKey="revenue" fill="var(--chart-line-primary)" />
      <ChartMarkers items={markers} />
      <ChartTooltip>
        <MarkerContent markers={markers} />
      </ChartTooltip>
    </AreaChart>
  );
}

function MarkerContent({ markers }) {
  const activeMarkers = useActiveMarkers(markers);
  if (activeMarkers.length === 0) return null;
  return <MarkerTooltipContent markers={activeMarkers} />;
}
```

### ChartMarker Interface

```ts
interface ChartMarker {
  date: Date;
  icon: React.ReactNode;
  title: string;
  description?: string;
  content?: React.ReactNode;
  color?: string;
  onClick?: () => void;
  href?: string;
  target?: "_blank" | "_self";
}
```

### ChartMarkers Props

| Prop        | Type            | Default  | Description                 |
| ----------- | --------------- | -------- | --------------------------- |
| `items`     | `ChartMarker[]` | required | Array of markers            |
| `size`      | `number`        | `28`     | Marker circle size          |
| `showLines` | `boolean`       | `true`   | Show vertical guide lines   |
| `animate`   | `boolean`       | `true`   | Animate markers on entrance |

## Segment Selection

Add click-drag and touch segment selection with composable components. The area highlight automatically shows the selected path segment.

### Basic Usage

```tsx
import {
  AreaChart,
  Area,
  Grid,
  XAxis,
  ChartTooltip,
  SegmentBackground,
  SegmentLineFrom,
  SegmentLineTo,
} from "@/components/charts";

<AreaChart data={data}>
  <Grid horizontal />
  <Area dataKey="revenue" fill="var(--chart-line-primary)" />
  <SegmentBackground />
  <SegmentLineFrom />
  <SegmentLineTo />
  <XAxis />
  <ChartTooltip />
</AreaChart>;
```

Use `SegmentBackground`, `SegmentLineFrom`, and `SegmentLineTo` independently — you do not need all three. Boundary lines support `variant="dashed" | "solid" | "gradient"`.

### Reading Selection Data

Use the `useChart` hook inside a child component to read the active selection:

```tsx
import { useChart } from "@/components/charts";

function SelectionStats({ onSelectionChange }) {
  const { selection, data, xAccessor } = useChart();

  useEffect(() => {
    if (!selection?.active) {
      onSelectionChange(null);
      return;
    }

    const startPoint = data[selection.startIndex];
    const endPoint = data[selection.endIndex];
    onSelectionChange({ startPoint, endPoint });
  }, [selection, data, xAccessor, onSelectionChange]);

  return null;
}
```

### SegmentBackground

| Prop   | Type     | Default                           | Description                        |
| ------ | -------- | --------------------------------- | ---------------------------------- |
| `fill` | `string` | `var(--chart-segment-background)` | Fill color for the selected region |

### SegmentLineFrom / SegmentLineTo

| Prop          | Type                                | Default                     | Description |
| ------------- | ----------------------------------- | --------------------------- | ----------- |
| `stroke`      | `string`                            | `var(--chart-segment-line)` | Line color  |
| `strokeWidth` | `number`                            | `1`                         | Line width  |
| `variant`     | `"dashed" \| "solid" \| "gradient"` | `"dashed"`                  | Line style  |

## Theming

The Area Chart uses the same CSS variables as the Line Chart:

```css
:root {
  --chart-background: oklch(1 0 0);
  --chart-foreground: oklch(0.145 0.004 285);
  --chart-foreground-muted: oklch(0.55 0.014 260);
  --chart-line-primary: oklch(0.623 0.214 255);
  --chart-line-secondary: oklch(0.705 0.015 265);
  --chart-crosshair: oklch(0.4 0.1828 274.34);
  --chart-grid: oklch(0.9 0 0);
  --chart-tooltip-foreground: oklch(0.985 0 0);
  --chart-tooltip-muted: oklch(0.65 0.01 260);
  --chart-marker-background: oklch(0.97 0.005 260);
  --chart-marker-border: oklch(0.85 0.01 260);
  --chart-marker-foreground: oklch(0.3 0.01 260);
  --chart-marker-badge-background: oklch(0 0 0);
  --chart-marker-badge-foreground: oklch(1 0 0);
  --chart-segment-background: oklch(0.5 0 0 / 0.06);
  --chart-segment-line: oklch(0.5 0 0 / 0.25);
}

.dark {
  --chart-background: oklch(0.145 0 0);
  --chart-foreground: oklch(0.45 0 0);
  --chart-crosshair: oklch(0.45 0 0);
  --chart-grid: oklch(0.25 0 0);
  --chart-marker-background: oklch(0.25 0.01 260);
  --chart-marker-border: oklch(0.4 0.01 260);
  --chart-marker-foreground: oklch(0.9 0 0);
  --chart-marker-badge-background: oklch(1 0 0);
  --chart-marker-badge-foreground: oklch(0.15 0 0);
  --chart-segment-background: oklch(1 0 0 / 0.06);
  --chart-segment-line: oklch(1 0 0 / 0.25);
}
```

## Dependencies

This component requires the same packages as the Line Chart:

```bash
pnpm add @visx/shape @visx/curve @visx/scale @visx/gradient @visx/responsive @visx/event @visx/grid d3-array motion react-use-measure
```