LineChart
Multi-series line chart for continuous-y trends over time — season stories, rolling averages, form curves. Built-in linear-regression trendlines, event-annotation guides, and an optional mirrored y-axis. Hero fixture: a synthetic two-series xG / xGA season trend.
Canonical behaviors.
No series supplied — the chart stays explicit.
Minimal valid chart: one series, a handful of points.
Linear-regression overlay per series. Extends across the full axis range, not just the data x-min/x-max.
`showMarkers={false}` plus trendlines for a noise-free form read.
Mirrored ticks on the right keep the y-read legible at wider widths.
Vertical guides mark managerial changes, season cuts, or other narrative beats.
Emphasize a subset and let the rest drop into the background.
Set `markerKind` on individual points to switch their default shape. Consumers can still override via the `points.shape` style callback.
ThemeProvider restyles the chart without touching the series shape.
Suppresses hover and HTML label overlay for export / SSR contexts.
`series-pair` envelope between actual cumulative points and a 68-pt top-4 pace threshold. Green when the team is ahead of the pace, red when behind. The reference line opts out of markers and uses per-series `strokeDasharray` to read as a threshold, not a trajectory. Synthetic slow-start / late-surge season crosses pace around MW22.
`envelopeCenterOffset()` helper builds a ±σ ribbon around the position-group mean. Player trajectory overlaid for contrast.
Single-series confidence band via `envelopeCenterOffset()`. Rolling xG/90 with ±σ.
`bands` for title-race, mid-table, and relegation zones; `eventRef()` marks a point-in-time beat (here, a managerial change).
Diagonal reference + `series-to-reference` envelope between the Lorenz curve and the equality diagonal. The reference line's geometry is the single source of truth — no hidden-series duplication. Canonical z-order acceptance test: dashed diagonal above the red fill, Lorenz curve above everything.
Best-practice examples.
Minimal usage
Pass one or more series, each with an array of { x, y } points.
import { LineChart } from "@withqwerty/campos-react";
export function SeasonTrend({ xg, xga }) {
return (
<LineChart
series={[
{ id: "xg", label: "xG", points: xg },
{ id: "xga", label: "xGA", points: xga },
]}
xAxisLabel="Matchweek"
/>
);
}
With trendlines and reference annotations
Linear-regression trendlines per series plus declarative reference lines for narrative events.
import { LineChart, eventRef, EVENT_REF_SUBTLE } from "@withqwerty/campos-react";
<LineChart
series={series}
trendlines
dualYAxis
references={[
eventRef(12, { label: "Change of Manager" }),
eventRef(20, EVENT_REF_SUBTLE),
]}
xAxisLabel="Matchweek"
/>
Public surface.
| Prop | Type | Default | Description |
|---|---|---|---|
series | readonly LineChartSeriesInput[] | required | Array of { id, label?, color?, points, trendline? } — one entry per line. |
xDomain / yDomain | readonly [number, number] | auto from data | Explicit axis range. Omit to let nice-ticks pick round boundaries. |
xTicks / yTicks | readonly number[] | number | auto | Explicit tick values or tick count. Number = count, array = positions. |
xTickFormat / yTickFormat | (value: number) => string | locale number | Tick formatter — use to render dates, percentages, etc. |
xAxisLabel / yAxisLabel | string | "" | Axis caption below / left of the plot area. |
trendlines | boolean | false | Draw a linear-regression trendline for every series. Opt out per series via `series[].trendline: false`. |
dualYAxis | boolean | false | Mirror y-axis ticks on the right side for wide charts. |
references | readonly PlotAreaReferenceLine[] | [] | Declarative horizontal/vertical/diagonal reference lines. Use `eventRef(x, opts?)` for any point-in-time marker (manager change, ownership, injury, external event) — pass `EVENT_REF_SUBTLE` or `EVENT_REF_ACCENT` to restyle. Use `diagonalFromLinear` for regression / equality lines. |
bands | readonly PlotAreaBand[] | [] | Axis-aligned shaded rectangles over data space. Handy for zone ribbons (title race, relegation, good/bad bands). |
envelopes | readonly LineChartEnvelope[] | [] | Signed-area fills between two bounds. Three kinds: `series-pair`, `center-offset` (CI-around-centre via `envelopeCenterOffset`), `series-to-reference` (Lorenz / regression-band). Each envelope clips to the plot area by default — set `clip: false` when overflow is intentional. |
highlightSeries | readonly string[] | — | Series ids to emphasize; all others fade to backgroundOpacity. |
showMarkers | boolean | true | Show dot markers at each data point. |
showGridLines | boolean | true | Show horizontal grid lines at each y-tick. |
showEndLabels / endLabelsForAllSeries | boolean | true / false | Anchored labels at the last point of each series. Default: only highlighted series. |
lineTooltip | { renderContent: (series) => ReactNode } | — | Cursor-following tooltip rendered while hovering along any line. Receives the full series model for derived stats. |
tooltipPriority | "marker" | "line" | "both" | "marker" | Resolves overlap between the marker tooltip and the cursor-following lineTooltip. Default: marker wins. |
formatAccessibleX | (x: number) => string | String(x) | Formats the x value inside marker aria-labels and the tooltip's x-row. Use when x is an epoch-ms timestamp or other non-human-readable number. |
staticMode | boolean | false | Suppress hover interactions and end-label HTML overlay for export/SSR contexts. |
yScale | "linear" | "log" | "linear" | Currently linear only; log is reserved for the FT covid chart battle-test and falls back with a warning. |
Create a React component using Campos LineChart. Import LineChart from @withqwerty/campos-react, pass series as { id, label, points: { x, y }[] }, and opt in to trendlines / events when the story calls for them. Prefer xAxisLabel for the time axis and leave yAxisLabel empty when the unit is implied by the series labels.