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

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

> A monochrome-plus-signal line chart over the shared --pds-chart-N ramp, recharts-backed.

## Import path

`LineChart` ships from the **`@protocore/pds/charts`** subpath — not the main entry — so recharts stays out of the core bundle. `recharts` (>=3) is an **optional peer**; install it in apps that render charts.

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

## When to use it

Use **LineChart** for a continuous series over an ordered x-axis — time, block height, sequence — where the *rate and direction of change* is the story. For volume-under-a-curve emphasis, use [AreaChart](/charts/area-chart); for discrete category comparison, [BarChart](/charts/bar-chart); for an axis-free glanceable trend, [Sparkline](/charts/sparkline).

Rank your series and lean on the ramp: keep supporting lines greyscale and reserve the signal hues for the line that carries meaning (see the doctrine on [ChartContainer](/charts/chart-container)). Every prop beyond `data`/`series`/`xKey`/`height` is forwarded to the underlying recharts `<LineChart>`.

## 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` | `ChartSeries[]` | yes | — | Series to plot, in draw + legend order. `ChartSeries` = `{ key: string; label?: string; color?: string }` — color defaults to `--pds-chart-N` by position. |
| `xKey` | `string` | yes | — | Datum key for the x-axis category. |
| `height` | `number` | no | `240` | Chart height in px. |
| `...rest` | `Omit<RechartsLineChartProps, 'data' \| 'children' \| 'width' \| 'height' \| 'ref'>` | no | — | Remaining props spread onto the underlying recharts `<LineChart>` (e.g. `margin`, `syncId`, `layout`). |

## Examples

### Basics

Give it `data`, an `xKey`, and one or more `series`. The defaults are the house style: a hairline horizontal grid, mono muted ticks, no axis lines, 1.5px strokes, no per-point dots, and a square active dot on hover. Wrap it in a [ChartContainer](/charts/chart-container) for the frame and the ramp.

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

const data = [
  { block: 18_000, latency: 2.1 },
  { block: 18_100, latency: 2.4 },
  { block: 18_200, latency: 2.0 },
  { block: 18_300, latency: 2.8 },
  { block: 18_400, latency: 2.5 },
  { block: 18_500, latency: 3.1 },
];

export default function Demo() {
  return (
    <ChartContainer label="Finality latency / s" height={240}>
      <LineChart data={data} xKey="block" series={[{ key: "latency", label: "Latency" }]} />
    </ChartContainer>
  );
}
```

### Multiple series

List several `series` in draw order; each resolves to the next `--pds-chart-N` slot. Because the ramp is monochrome-plus-signal, the first (ink) series reads as the lead and the rest recede — pair with a legend so readers can map lines to labels.

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

const data = [
  { hour: "09", eu: 41, us: 62, ap: 28 },
  { hour: "11", eu: 48, us: 70, ap: 33 },
  { hour: "13", eu: 52, us: 66, ap: 39 },
  { hour: "15", eu: 60, us: 74, ap: 44 },
  { hour: "17", eu: 57, us: 81, ap: 49 },
  { hour: "19", eu: 63, us: 78, ap: 55 },
];

const series = [
  { key: "eu", label: "eu-central-1" },
  { key: "us", label: "us-east-1" },
  { key: "ap", label: "ap-south-1" },
];

export default function Demo() {
  return (
    <ChartContainer
      label="p99 gateway latency / ms"
      legend={<ChartLegend items={series.map((s) => ({ label: s.label }))} />}
      height={240}
    >
      <LineChart data={data} xKey="hour" series={series} />
    </ChartContainer>
  );
}
```

## Do & don't

**Do**

- Wrap it in a ChartContainer so it inherits the `--pds-chart-*` ramp.
- Give each series a human `label` for the tooltip and legend.
- Keep the ink series (chart-1) as the primary metric and let others recede.
- Use a categorical/time `xKey`; sort your data by it before passing.

**Don't**

- Don't render it outside a ramp source without pinning `--pds-chart-*` yourself.
- Don't give every line a bright color — the ramp is a rank, not a rainbow.
- Don't import it from `@protocore/pds`; it lives on the `/charts` subpath.
- Don't plot unordered categories on the x-axis — use BarChart instead.

## Accessibility

**Notes**

- recharts renders the plot as SVG; provide surrounding context (a ChartContainer `label`, a caption, or a data table) for assistive tech, as the marks themselves are not individually labelled.
- The default tooltip appears on keyboard focus and hover via recharts; series stay distinguishable by luminance, not hue alone, thanks to the monochrome ramp.
- Pair multi-series charts with a legend so line identity does not rely on color perception.

## Related

`chart-container`, `area-chart`, `bar-chart`, `sparkline`

---

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