Skip to content
  • System
  • Light
  • Dark
  • High contrast

LineChart

Assessment progress over time

Line chart, 6 points. Week 1 to Week 6. Values from 10 to 86.

020406080Week 1Week 2Week 3Week 4Week 5Week 6
import { LineChart } from '@eekodigital/raster';

<LineChart
  series={[{ name: 'Assessed', data: [10, 25, 40, 60, 72, 86] }]}
  categories={['Week 1', 'Week 2', 'Week 3', 'Week 4', 'Week 5', 'Week 6']}
  title="Assessment progress over time"
/>

Pass multiple series to compare trends. A legend renders automatically.

Results trend by status

Line chart, 3 series, 18 points. Jan to Jun. Values from 0 to 42.

010203040JanFebMarAprMayJun
PassFailN/A
<LineChart
  series={[
    { name: 'Pass', data: [0, 5, 12, 20, 30, 42], color: 'var(--demo-good)' },
    { name: 'Fail', data: [0, 1, 3, 5, 6, 8], color: 'var(--demo-bad)' },
    { name: 'N/A', data: [0, 2, 4, 7, 10, 12], color: 'var(--demo-neutral)' },
  ]}
  categories={['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']}
  title="Results trend by status"
/>

Set area to fill below the line.

Assessment progress (area)

Line chart, 6 points. Week 1 to Week 6. Values from 10 to 86.

020406080Week 1Week 2Week 3Week 4Week 5Week 6
<LineChart
  series={[{ name: 'Assessed', data: [10, 25, 40, 60, 72, 86] }]}
  categories={['Week 1', 'Week 2', 'Week 3', 'Week 4', 'Week 5', 'Week 6']}
  area
  title="Assessment progress (area)"
/>

Pass onSelect (and optionally selectedIndex) to make points toggle buttons. Enter or Space toggles the focused point; Escape clears the selection.

Results trend (select a point)

Line chart, 2 series, 12 points. Jan to Jun. Values from 0 to 42.

010203040JanFebMarAprMayJun
PassFail

Nothing selected

const [selected, setSelected] = useState<LinePointIndex | null>(null);

<LineChart
  series={series}
  categories={months}
  title="Results trend (select a point)"
  aspectRatio={3}
  selectedIndex={selected}
  onSelect={setSelected}
/>

Keep categories complete: they name each point and label the table rows. To thin or shorten the x-axis, use xTickFilter and formatXTick, which only affect the ticks:

<LineChart
series={[{ name: "Visitors", data: visits }]}
categories={days} // "2026-09-01" … "2026-09-30"
xTickFilter={(i) => i % 7 === 0}
formatXTick={(day) => day.slice(5)} // "09-01"
title="Visitors in September"
/>

Only the first and last categories anchor to the plot edges; every other tick centres on its point.

  • A role="figure" named by the visible title and described by a generated summary (chart type, series and point counts, range).
  • The SVG is a role="group" with aria-roledescription="chart"; no graphics-* roles.
  • Each series is a role="group" named {series}, {n} points.
  • Each point is labelled {series}, {x}: {y}, 3 of 12. With onSelect, selectedIndex or a click handler, marks are role="button" with aria-pressed; otherwise they’re static role="img".
  • Points use a different marker shape per series (circle, square, triangle…) as well as colour.
  • A visible Show data table button (aria-expanded) reveals a real table captioned Data for {title}, with th scope headers and values run through formatValue.
  • Escape (inside the chart only) clears the selection and announces it in a polite live region; it doesn’t close a surrounding dialog.
  • Animations stop under prefers-reduced-motion. In forced-colours mode marks use system colours, told apart by dash pattern and marker shape.
Key Action
← / → Previous / next mark
Home / End First / last mark
PageUp / PageDown Back / forward 10 marks
↑ / ↓ Previous / next series
Tab Leave the chart (one tab stop)
Enter / Space Toggle selection (interactive marks)
Escape Hide the tooltip and clear selection

See the Accessibility guide for the shared structure, the labels prop and screen-reader testing.

PropTypeDefaultDescription
seriesLineSeries[]—

Required. { name, data: number[], color? }.

categoriesstring[]—

Required. X-axis categories, one per point. They name each point and label the table rows, so keep them complete and thin the axis with xTickFilter or formatXTick. (A “” category still hides its tick, but also leaves that point without an x value in its name.)

areabooleanfalseFill below the line.
stackedbooleanfalseStack series.
curve“linear” | “smooth”“linear”Line interpolation.
xLabelstring—X-axis title.
yLabelstring—Y-axis title.
grid“horizontal” | “vertical” | “both” | “none”“horizontal”Grid lines.
formatValue(value: number) => stringIntl.NumberFormat

Formats values in ticks, marks and the table. Defaults to Intl.NumberFormat(labels.locale).

xLabelMinSpacingnumber30

Minimum px between x labels before they thin out. Thinning keeps the first and last categories.

xTickFilter(index: number, category: string) => boolean—

Which x ticks to label. Replaces the automatic thinning. Points and the table keep every category.

formatXTick(category: string, index: number) => string—

Text for an x tick, e.g. a short date. Return “” to hide it.

heightnumber200Plot height in px.
aspectRationumber—

Width ÷ height, instead of height. The plot box is sized in CSS either way, so server-rendered and hydrated layouts match.

onPointClick(series, point, value) => void—Makes points buttons.
selectedIndex{ series, point } | null—Controlled selection.
onSelect(index | null) => void—Makes points buttons; called on toggle and Escape.
titlestring—Required. Visible title: names the figure and captions the data table.
hideTitlebooleanfalseHide the title visually. It still names the chart for assistive technology.
labelsPartial<ChartLabels>English

Generated strings and the number locale. See Accessibility.

dataTable“disclosure” | “visually-hidden”“disclosure”How the data table is offered.
exportRefRef<ChartExportHandle>—

SVG/PNG export. See Exporting charts.

classNamestring—Class on the figure.