Skip to content
skrewww

Content & Data

Line Chart

Line Chart shows a trend across ordered categories — a single series by default, or several series as separate lines. Static and non-tabbable, with an optional sparkline mode and the data also exposed as a hidden table.

Part of the chart components — see the Charts overview for how the families and dashboard compositions fit together.

Single component — no variants

betaReact AvailableFigma PartialDocs Partial
React last updated
2026-09-22
Documentation last updated
2026-09-26
Accessibility target
WCAG 2.2 AA (target)
Version
0.1.0-beta

Known open questions

  • Figma covers only the single-series Line Chart (example) static visual reference (a single stroke with hollow-ring markers and no axes); it is not a reusable Figma component. Multiple series, the value axis, grid, legend and tooltip have no Figma reference — they use current Skrewww tokens conservatively and need a design decision before parity can be claimed.
  • Point markers, axes and the sparkline treatment beyond the example are this implementation's own decisions; fixed chart height (width is fluid) is likewise not something Figma specified.
  • The categorical series palette (four slots: brand action, primary text, amber, green) is a CH-2 implementation choice checked for >= 3:1 contrast on the default white surface, not a Figma-verified palette. Slots carry no status meaning; positive/negative colors are a separate, unresolved design decision.
  • An interactive legend (series toggling) is deferred: it needs a hidden-series state plus keyboard and announcement design. The legend is a non-interactive key.
  • The tooltip is pointer/touch-only supplementary information; every value is also in the hidden table. A keyboard-operable chart (focusable points, arrow-key navigation) is deferred.
  • Dense data and long category labels have no policy yet: category labels always render (no tick skipping, rotation, truncation, scrolling or aggregation), so many points or long labels can collide or clip. A density and label-length policy is an open decision.

Purpose

Visualize a trend across ordered points: a single series by default, or several series as separate lines. Includes a compact sparkline mode.

Anatomy

A recharts LineChart inside ResponsiveContainer (fluid width, fixed height — genuinely fills its parent). Each series is one Line stroked in its series color at 2px, with a 3px-radius hollow-ring dot per point (semantic/surface/default fill, series-colored stroke); slot 1 is semantic/action/primary, matching the Figma example. Curve type is "linear" (straight segments) — confirmed by reading the actual vector path data for node 2058:2560 via the Figma Plugin API: every segment is a straight "L" (lineto) command. With no extra props no axes, grid, legend or tooltip render, matching the Figma reference; category/value axes, grid, legend and tooltip are opt-in. A missing value (null) leaves a gap. An optional `sparkline` mode (used by Banking Account Card) suppresses markers and thins the stroke to 1.5px and hides all chrome for inline/card use. A visually-hidden (`sr-only`) data table — one column per series — is rendered alongside, and the visual is aria-hidden inside a role="img" wrapper with aria-label + aria-describedby pointing at the table.

Variants and states

default

When to use

One or more trend lines across ordered categories (for example months) where the shape of change matters, including comparing several series.

When not to use

Categorical comparisons without an inherent order — use Bar Chart. Magnitude or accumulation where the filled area matters — use Area Chart. More than about four series (only four color slots exist).

Accessibility

role="img" with an accessible name, described by a visually-hidden (sr-only) data table with one column per series (missing values read "No data"), so series are identified by name, never by color alone. The plot, legend and tooltip are aria-hidden; the chart is a static visualization with no keyboard tab stop, and the tooltip is pointer/touch-only supplementary information.

Common mistakes

Adding axes, grid, legend or tooltip to the default chart when the Figma reference shows none (they are opt-in), or switching to an area chart with a `type` prop — Area Chart is its own component. Inventing props: chart families are separate components (do not add a `type`, `variant` or `stacked` prop), `series` keys must be unique and never "label", and raw Recharts props are not accepted. Pie, Donut, Scatter, Heatmap, Waterfall, Funnel and other chart families do not exist yet — do not import or claim them. Treating "static" as "no accessibility work needed": the hidden data table is required, not optional polish.

Properties

data (rows: { label, value } or { label, [series.key]: number | null }). label (accessible name / hidden table caption). height (fixed pixel height, default 240 — width is fluid, filling the parent). sparkline (boolean, default false — compact inline rendering: hides the markers, uses a 1.5px stroke and hides all axes, grid, legend and tooltip; data and accessibility are unchanged, e.g. the balance-history trend in Banking Account Card). markers (boolean, default true; always false in sparkline mode). series ({ key, label, color?, format? }[] — omit for a single series read from each row's `value`), legend (boolean, default: true for several series), tooltip (boolean, default false), showCategoryAxis, showValueAxis, showGrid (booleans), valueFormat (a function or { kind: "number" | "compact" | "percent" | "currency" }), labelFormat (a function or { kind: "date", granularity }).

Why is there no axis at all by default?

Figma's own "Line Chart (example)" frame has no axis labels, so the default output matches it exactly. showCategoryAxis, showValueAxis, showGrid, legend and tooltip are opt-in and have no Figma reference.

Why "linear" curve type, not a smoothed curve?

Verified, not guessed: the actual vector path data for the Figma "Line" node (2058:2560), read directly via the Figma Plugin API, contains only straight lineto ("L") commands. A smoothed curve would be a regression from the real design.

How is the underlying data exposed to screen readers?

A visually-hidden (sr-only) table with a column per series, linked to the chart via aria-describedby — the same mechanism every Cartesian chart uses.

What is sparkline mode for?

A compact inline trend (for example a balance-history line inside a card): no markers, a thinner stroke, and no axes, grid, legend or tooltip even if requested. Use `height` to size it.

How do I show several series?

Pass `series` and rows shaped { label, [series.key]: number | null }. Do not add a `type` or `variant` prop to switch to an area chart — Area Chart is its own component.

Tokens used

semantic/action/primarysemantic/text/primarysemantic/text/secondarysemantic/border/defaultsemantic/border/strongsemantic/surface/defaultsemantic/surface/subtlecolor/warning/700color/success/700

Component API

PropTypeDefaultDescription
data({ label: string } & { [seriesKey: string]: string | number | null })[]—One row per category: { label, value } for a single series, or { label, [series.key]: number | null } when `series` is given. null means no data (a gap or no bar). Duplicate labels are allowed.
labelstring—Accessible name for the chart — also used as the hidden data table's caption.
heightnumber240Fixed pixel height. Width is fluid (ResponsiveContainer), filling the parent.
series{ key: string; label: string; color?: "series-1" | "series-2" | "series-3" | "series-4"; format?: ChartValueFormat }[]—Series definitions: { key, label, color?, format? }. `key` is the row property holding the value (unique, never "label"); `color` is a slot "series-1"…"series-4" (default: by position, wrapping after four). Omit for a single series read from each row's `value`.
sparklinebooleanfalseCompact inline rendering: hides the point markers, uses a 1.5px stroke instead of 2px, and hides every axis, grid line, legend and tooltip. Data and accessibility (role="img" + hidden data table) are unchanged.
markersbooleantrueDraw a hollow-ring marker on each point. Always false in sparkline mode.
legendboolean—Show a legend. Defaults to true when there is more than one series. It is a non-interactive key (no series toggling).
tooltipboolean—Show a hover/touch tooltip listing the category and each series' value. Defaults to false. Supplementary only: every value is also in the hidden table.
showCategoryAxisboolean—Show the category axis labels. Defaults to false (the Figma reference has no axis).
showValueAxisboolean—Show the value-axis ticks. Defaults to false.
showGridboolean—Show grid lines. Defaults to false.
valueFormatChartValueFormat—How values are formatted on value-axis ticks, in the tooltip, and in the hidden table: a function (value: number) => string, or { kind: "number" | "compact" | "percent" | "currency", ... }. Default: the raw number. A series' own `format` overrides it.
labelFormatChartLabelFormat—How category labels are formatted on the axis, in the tooltip, and in the hidden table: a function (label: string) => string, or { kind: "date", granularity: "day" | "month" | "year" } for normalized ISO date labels (UTC). Default: the label as given.

React example

Copy React example
import { LineChart } from "@/components/ui";

const monthlySignups = [
  { label: "Jan", value: 58 },
  { label: "Feb", value: 95 },
  { label: "Mar", value: 76 },
  { label: "Apr", value: 128 },
  { label: "May", value: 108 },
  { label: "Jun", value: 140 },
];

const trend = [
  { label: "Jan", revenue: 120, orders: 80 },
  { label: "Feb", revenue: 150, orders: 95 },
  { label: "Mar", revenue: 135, orders: 110 },
  { label: "Apr", revenue: 170, orders: 120 },
];

export function Example() {
  return <LineChart data={monthlySignups} label="Monthly signups" />;
}

export function MultiSeriesExample() {
  return (
    <LineChart
      data={trend}
      label="Revenue and orders"
      series={[
        { key: "revenue", label: "Revenue", format: { kind: "currency", currency: "USD", maximumFractionDigits: 0 } },
        { key: "orders", label: "Orders" },
      ]}
      showCategoryAxis
      showValueAxis
      showGrid
      tooltip
    />
  );
}