Skip to content

Line Chart

ChartsSince 0.3.0
import { LineChart } from '@absoluteui/components/line-chart';
import '@absoluteui/components/line-chart/style.css';

Using Angular? See Line Chart for Angular.

An accessible SVG line chart (and area chart) for trends over a shared x axis. It provides:

  • one or more series over categories, numbers, or instants (time axis in the configured timezone);
  • gaps for missing values (null, NaN, infinities) and isolated points drawn as markers;
  • a legend of toggle buttons that show and hide series;
  • keyboard-reachable data points (one tab stop, arrow keys) with a tooltip on focus and hover;
  • a generated accessible summary (series, ranges, extremes, trend, gaps) and a data table fallback with the exact values;
  • series that differ by color, marker shape, and dash pattern, never by color alone (WCAG 1.4.1);
  • optional zoom and pan along x (zoom) with a Zoom toolbar, keys, Ctrl/Cmd + wheel, drag, and Shift + drag selection, and an optional crosshair (crosshair).
  • Trends over time or an ordered dimension.
  • Comparing a few series (up to about 8) over the same x values.
  • Area option: emphasizing magnitude relative to zero for one or two series.
  • Comparing discrete categories: use Bar Chart.
  • Part-to-whole: use Pie Chart or a stacked Bar Chart.
  • An inline trend without axes: use Sparkline.
  • Unordered x values or per-series x values: use Scatter Chart.
  • Bars and lines together or two value axes: use Combo Chart.

Monthly time series in a configured timezone

Section titled “Monthly time series in a configured timezone”
import { LineChart, type LineChartSeriesToggleDetail } from '@absoluteui/components/line-chart';
import { plainDate, plainDateTime, toInstant } from '@absoluteui/core';
const months = Array.from({ length: 6 }, (_, i) => toInstant(plainDateTime(plainDate(2026, i + 1, 1)), 'Europe/London'));
const host = document.createElement('div');
document.body.append(host);
const chart = LineChart.create(host, {
label: 'Monthly active users',
description: 'Thousands of users',
x: months,
series: [
{ id: 'web', label: 'Web', values: [42, 45, null, 51, 55, 61] },
{ id: 'mobile', label: 'Mobile', values: [30, 33, 38, 41, 47, 52] },
],
yAxis: { label: 'Users (thousands)' },
timezone: 'Europe/London',
});
host.addEventListener('aui-series-toggle', (event) => {
const { hidden } = (event as CustomEvent<LineChartSeriesToggleDetail>).detail;
host.dataset.hidden = hidden.join(',');
});
chart.update({ hiddenSeries: ['mobile'] });

Area chart with currency values and categories

Section titled “Area chart with currency values and categories”
import { LineChart } from '@absoluteui/components/line-chart';
const host = document.querySelector<HTMLElement>('#cash');
if (host) {
LineChart.create(host, {
label: 'Net cash flow',
x: ['Q1', 'Q2', 'Q3', 'Q4'],
series: [{ id: 'cash', label: 'Cash flow', values: [-120, 40, 180, 95] }],
area: true,
height: 220,
valueFormat: { style: 'currency', currency: 'USD', maximumFractionDigits: 0 },
dataTable: 'visible',
});
}

Zoom along x with a crosshair and the aui-zoom event

Section titled “Zoom along x with a crosshair and the aui-zoom event”
import { LineChart, type LineChartZoomDetail } from '@absoluteui/components/line-chart';
const days = Array.from({ length: 60 }, (_, i) => i + 1);
const host = document.createElement('div');
document.body.append(host);
const chart = LineChart.create(host, {
label: 'Daily orders',
x: days,
series: [{ id: 'orders', label: 'Orders', values: days.map((d) => 100 + ((d * 17) % 40)) }],
xAxis: { label: 'Day' },
zoom: true,
zoomRange: { from: 1, to: 14 },
crosshair: true,
});
host.addEventListener('aui-zoom', (event) => {
const { x, reason } = (event as CustomEvent<LineChartZoomDetail>).detail;
host.dataset.window = x ? `${String(x.from)}-${String(x.to)} (${reason})` : 'all';
});
chart.update({ zoomRange: null });
import { LineChart } from '@absoluteui/components/line-chart';
import '@absoluteui/components/line-chart/style.css';
import { instant } from '@absoluteui/core';
const host = document.querySelector<HTMLElement>('#latency');
if (host) {
const x = [0, 1, 2, 3].map((h) => instant(Date.UTC(2026, 2, 1, h)));
LineChart.create(host, {
label: 'API latency',
x,
series: [{ id: 'p95', label: 'p95', values: [120, 180, null, 140] }],
valueFormat: { style: 'unit', unit: 'millisecond' },
timezone: 'Asia/Kolkata',
});
}
import { LineChart } from '@absoluteui/components/line-chart';
const host = document.createElement('div');
document.body.append(host);
LineChart.create(host, {
label: 'Revenue',
x: ['Jan', 'Feb', 'Mar'],
series: [{ id: 'rev', label: 'Revenue', values: [120, 135, 150] }],
});

Export: @absoluteui/components/chart-export (chartToSvg, chartToPng, downloadChart) exports any chart instance to SVG or PNG.

<div class="aui-chart aui-line-chart [aui-chart--patterns] [aui-chart--zoomable] [aui-chart--zoomed] [aui-line-chart--markers] [aui-line-chart--area]">
<div class="aui-chart__header">
<div class="aui-chart__title" id="T">title</div>
<p class="aui-chart__description" id="D">description</p>
<div class="aui-chart__toolbar"> (zoom: true; hidden otherwise)
<div class="aui-chart__zoom" role="group" aria-label="Zoom">
<button class="aui-chart__tool" aria-label="Zoom in"/> <button class="aui-chart__tool" aria-label="Zoom out" aria-disabled="true"/> <button class="aui-chart__tool" aria-label="Reset zoom" aria-disabled="true"/>
</div>
</div>
</div>
<ul class="aui-chart__legend" aria-label="Legend">
<li class="aui-chart__legend-entry"><button class="aui-chart__legend-item" aria-pressed="true"><svg class="aui-chart__swatch" aria-hidden="true"/>Web</button></li>
</ul>
<div class="aui-chart__body"> (height: --aui-chart-height)
<svg class="aui-chart__svg" role="group" aria-roledescription="line chart" aria-labelledby="T" aria-describedby="D S">
<g class="aui-chart__crosshair" aria-hidden="true"><line class="aui-chart__crosshair-line"/>...</g> (crosshair: true)
<g class="aui-chart__grid" aria-hidden="true"/> <g class="aui-chart__axis …" aria-hidden="true"/>
<g class="aui-line-chart__series aui-chart__series--c1" aria-hidden="true"><path class="aui-line-chart__area"/><path class="aui-line-chart__line aui-chart__dash--1"/></g>
<g class="aui-line-chart__points"><path class="aui-chart__mark aui-line-chart__point" role="img" aria-label="Jan 2026, Web: 42" tabindex="0"/>...</g>
</svg>
<div class="aui-chart__empty" hidden/> <div class="aui-chart__tooltip" aria-hidden="true" hidden/>
</div>
<p class="aui-chart__summary" id="S" hidden>generated summary</p>
<div class="aui-chart__data"><button class="aui-chart__table-toggle" aria-expanded="false" aria-controls="R">Show data table</button><div class="aui-chart__table-scroll" id="R" role="region"><table class="aui-chart__table">...</table></div></div>
</div>
LineChart.create(host: HTMLElement, options: LineChartOptions): LineChart

Global configuration key: lineChart (see Configuration).

Option Type Default Description
label string Chart title: visible text and the accessible name of the plot (aria-labelledby). Required.
hideLabel boolean false Visually hide the title; it stays the accessible name.
description string Visible description below the title, also referenced by aria-describedby (text only).
summary string Replaces the generated accessible summary (aria-describedby).
valueFormat Intl.NumberFormatOptions Number format for values in tooltips, labels, the data table, the summary, and axis ticks (ticks use fixed fraction digits).
formatValue (value: number) => string Custom value text; overrides valueFormat everywhere except axis ticks.
hiddenSeries readonly string[] Ids of series (or slices) hidden initially; update() replaces the hidden set.
x readonly (string | number | Instant | ZonedDateTime)[] Shared x values, one per point: strings (category axis), numbers (linear axis), or instants (time axis). Numbers and instants must be ascending. Required.
series readonly ChartSeries[] Series: { id, label, values: (number | null)[], color?: 1-8 }. values has exactly one entry per x value; null, NaN, and infinities are gaps. Required.
area boolean false Fill the area between each line and the zero baseline (includes zero in the domain).
xType 'category' | 'linear' | 'time' Axis type. Default: inferred from the first x value.
xAxis { label?: string; tickCount?: number } X axis title and approximate tick count (2-20).
yAxis { label?: string; tickCount?: number; min?: number; max?: number; includeZero?: boolean } Y axis title, tick count, fixed domain, and zero inclusion (default true with area).
formatX (value: LineChartXValue, index: number) => string Custom x text for tooltips, labels, the table, and the summary.
timeFormat Omit<Intl.DateTimeFormatOptions, 'timeZone'> Date format of time x values. Default: chosen from the data resolution (year, month, day, minute, second).
zoom boolean false Zoom and pan along x: a Zoom toolbar (Zoom in, Zoom out, Reset zoom), +/= and - and 0 keys on a focused point, arrow keys past the window edge pan, Ctrl/Cmd + wheel, drag to pan a zoomed chart, Shift + drag to select a range. Turning it off resets the window.
zoomRange ChartZoomRange | null Visible x window { from, to } in data units (category index, number, or epoch ms for time axes); null shows everything. Clamped to the data and to at least two points. Applied without an aui-zoom event; use with zoom: true (the toolbar and keys need it).
legend 'auto' | 'show' | 'hide' "auto" auto: legend when there is more than one series (pie charts: always). Globally configurable.
dataTable 'toggle' | 'visible' | 'hidden' | 'none' "toggle" Data table fallback with the exact data: behind a Show data table button (built on first open), always visible, visually hidden (screen readers only), or none. Globally configurable.
tooltip boolean true Tooltip on pointer hover and keyboard focus. Globally configurable.
patterns boolean false Dash patterns and texture fills so series never differ by color alone. Off by default (plain colors); always on in forced colors. Turn it on when series are told apart by color alone (grouped or stacked series, multi-slice pies) and no labels carry the distinction (WCAG 1.4.1). Globally configurable.
height number 300 Plot height in CSS px (integer 120-2000); the width follows the container. Globally configurable.
markers 'auto' | 'always' | 'focus' "auto" Point markers: auto when points are at least 12 px apart; focus shows only the hovered or focused point. Isolated points always show a marker. Globally configurable.
crosshair boolean false Vertical crosshair line (aria-hidden) at the hovered or focused x value. Globally configurable.
locale string "en-US" Number, date, and message locale. Globally configurable. Inherited from common configuration.
timezone string "UTC" IANA timezone for time axes, tooltips, labels, and the table. Globally configurable. Inherited from common configuration.
direction 'ltr' | 'rtl' "ltr" rtl mirrors the category/x axis, the value axis side, and Left/Right arrow keys. Globally configurable. Inherited from common configuration.
Property Type Description
host HTMLElement The host element.
element SVGSVGElement The plot (svg role=“group”), named by the title and described by the summary.
summary string The generated (or custom) accessible summary.
hiddenSeries string[] Ids of hidden series (slices for Pie Chart).
zoomRange ChartZoomRange | null Current visible x window in data units, or null when showing everything.
Method Description
update(options: Partial<LineChartOptions>): void Merge, validate, and re-render. Invalid options throw and keep the previous state. Keyboard focus stays on the same data point.
setSeriesVisible(id: string, visible: boolean): void Show or hide a series (slice) programmatically; emits no event.
destroy(): void Remove rendering, host classes, listeners, the resize observer, and the configuration subscription.
Event Detail Bubbles Cancelable Description
aui-series-toggle { id: string; visible: boolean; hidden: string[] } Yes No The user toggled a legend entry (pointer or keyboard). Not emitted for update() or setSeriesVisible().
aui-zoom LineChartZoomDetail = ChartZoomDetail: { x: ChartZoomRange | null; y: null; reason: 'button' | 'keyboard' | 'wheel' | 'pan' | 'select' | 'reset' } Yes No The user changed the visible window (toolbar, keys, Ctrl/Cmd + wheel, drag pan, Shift + drag selection). x is null when showing everything. Not emitted for the zoomRange option or when the window does not change.

All rules live in the aui.components cascade layer, so application styles override them without specificity battles.

Class Purpose
aui-chart Host (shared chart chrome).
aui-line-chart Host modifier for this chart type.
aui-chart--patterns patterns option on: dash patterns and textures shown.
aui-chart__header / __title / __title--hidden / __description Title and description.
aui-chart__legend / __legend-entry / __legend-item / __legend-item--hidden / __legend-label / __legend-detail Legend list and toggle buttons.
aui-chart__swatch aria-hidden legend and tooltip key (marker, dash, texture).
aui-chart__body / __svg / __layer Plot container (height from –aui-chart-height), SVG, and drawing layer.
aui-chart__grid / __gridline / __zero-line / __axis / __axis-line / __tick-label / __axis-title Axes (aria-hidden).
aui-chart__series--c1 ... --c8 Palette slot classes; set –aui-chart-color from color-chart-<n>.
aui-chart__dash--1 ... --4 / aui-chart__pattern / aui-chart__pattern-tile Dash patterns and texture overlays.
aui-chart__mark / __mark--active / __mark--hover Focusable data mark and its states.
aui-chart__value-label Printed values with a surface-colored halo.
aui-chart__tooltip / __tooltip-title / __tooltip-rows / __tooltip-row / __tooltip-label / __tooltip-value Tooltip (aria-hidden; the focused mark carries the same text).
aui-chart__empty Empty state text (No data, All series are hidden).
aui-chart__summary Hidden summary referenced by aria-describedby.
aui-chart__data / __data--hidden / __table-toggle / __table-scroll / __table / __cell--numeric Data table fallback.
aui-chart--zoomable / aui-chart--zoomed Host modifiers: zoom enabled (touch-action pan-y on the body); a window is applied (grab cursor).
aui-chart__toolbar / __zoom / __tool Header toolbar (hidden while empty), the Zoom button group, and its icon buttons (aria-disabled when unavailable).
aui-chart__crosshair / __crosshair-line aria-hidden crosshair line drawn under the marks (crosshair option).
aui-chart__brush Range-selection rectangle while Shift + dragging.
aui-line-chart--markers / --area Markers visible; area fill on.
aui-line-chart__series / __line / __area / __points / __point / __point--isolated / __markers / __cursor Series group, line, area, point marks, isolated point, dense-series marker path, and the proxy mark of dense series.

Tokens this stylesheet reads (verified in CI). Override them in a theme or with the Theme Designer.

--aui-border-width | --aui-color-border | --aui-color-border-strong | --aui-color-chart-1 | --aui-color-chart-2 | --aui-color-chart-3 | --aui-color-chart-4 | --aui-color-chart-5 | --aui-color-chart-6 | --aui-color-chart-7 | --aui-color-chart-8 | --aui-color-chart-axis | --aui-color-chart-grid | --aui-color-focus-ring | --aui-color-hover | --aui-color-link | --aui-color-surface | --aui-color-surface-sunken | --aui-color-text | --aui-color-text-muted | --aui-duration-fast | --aui-easing-standard | --aui-focus-ring-offset | --aui-focus-ring-width | --aui-font-family-sans | --aui-font-size-md | --aui-font-size-sm | --aui-font-size-xs | --aui-font-weight-medium | --aui-font-weight-regular | --aui-font-weight-semibold | --aui-line-height-normal | --aui-line-height-tight | --aui-radius-md | --aui-radius-sm | --aui-shadow-md | --aui-space-1 | --aui-space-2 | --aui-space-3 | --aui-tooltip-max-width | --aui-touch-target-min

type LineChartXValue = string | number | Instant | ZonedDateTime;
interface ChartSeries { id: string; label: string; values: readonly (number | null)[]; color?: ChartColor }
interface LineChartConfig { legend: ChartLegendMode; dataTable: ChartTableMode; tooltip: boolean; patterns: boolean; height: number; markers: 'auto' | 'always' | 'focus'; crosshair: boolean }
interface LineChartOptions extends ChartCommonOptions, Partial<LineChartConfig> {
x: readonly LineChartXValue[];
series: readonly ChartSeries[];
area?: boolean;
xType?: 'category' | 'linear' | 'time';
xAxis?: { label?: string; tickCount?: number };
yAxis?: { label?: string; tickCount?: number; min?: number; max?: number; includeZero?: boolean };
formatX?: (value: LineChartXValue, index: number) => string;
timeFormat?: Omit<Intl.DateTimeFormatOptions, 'timeZone'>;
timezone?: string;
zoom?: boolean;
zoomRange?: ChartZoomRange | null;
}
interface ChartZoomRange { readonly from: number; readonly to: number }
interface LineChartSeriesToggleDetail { id: string; visible: boolean; hidden: string[] }
// LineChartZoomDetail = ChartZoomDetail
interface ChartZoomDetail { x: ChartZoomRange | null; y: ChartZoomRange | null; reason: 'button' | 'keyboard' | 'wheel' | 'pan' | 'select' | 'reset' }

Pattern: SVG chart as a named, described group (role=“group” with aria-roledescription) of role=“img” data points with roving focus; data table fallback (native table). Follows the WAI Complex Images tutorial (short name plus long description) and the roving tabindex technique of WAI-ARIA APG.

Key Context Action
ArrowLeft / ArrowRight Mark focused Previous / next data point (category) in the same series; Left/Right are mirrored in RTL. Zoomed: moving past the window edge pans the window to the next point.
ArrowUp / ArrowDown Mark focused, more than one visible series Same category in the previous / next visible series (nearest point when missing).
Home / End Mark focused First / last point of the series.
PageUp / PageDown Mark focused Ten points back / forward.
+ / = Point focused, zoom: true Zoom in around the focused x value.
- Point focused, zoom: true Zoom out around the focused x value.
0 Point focused, zoom: true Reset zoom (show all data).
Escape Tooltip visible Hides the tooltip without moving focus (WCAG 1.4.13); it returns on the next move.
Tab / Shift+Tab Any Zoom buttons (zoom: true), legend buttons, then one tab stop for the plot (the active mark), then the Show data table button and table region.
Enter / Space Legend button Shows or hides the series (native button).
Enter / Space Zoom button Zoom in, zoom out, or reset (native button; ignored while aria-disabled).
Element Role
svg.aui-chart__svg group with aria-roledescription (localized chart type), named by the title
data marks (points, bars, slices) img with an aria-label: category/x, series, formatted value
legend list (ul) named “Legend”; entries are toggle buttons (aria-pressed)
zoom toolbar (zoom: true) group named “Zoom” of native buttons “Zoom in”, “Zoom out”, “Reset zoom”
data table table (native) with caption, column headers, and row headers; wide tables scroll in a focusable region
axes, lines, textures, value labels, tooltip, crosshair, selection brush aria-hidden (decorative duplicates of the accessible data)
Attribute Element Value
aria-labelledby svg id of the visible (or visually hidden) title
aria-describedby svg description id (when provided) and the generated summary id
aria-roledescription svg Localized chart type, for example “line chart”
aria-label each mark Localized “{x}, {series}: {value}” (pie: “{label}: {value} ({percent})”)
tabindex active mark 0 on exactly one mark (roving); other marks have none
aria-pressed legend button true while the series is visible
aria-expanded / aria-controls Show data table button Table open state and the table region id
aria-disabled zoom buttons true while the action is unavailable (Zoom in at the minimum span, Zoom out and Reset zoom when not zoomed); the button stays focusable

Roving focus: one mark is in the tab sequence and remembers the last visited data point, also across re-renders (resize, update). Toggling a legend entry keeps focus on its button; toggling the table keeps focus on the table button.

Criterion Level Note
1.1.1 Non-text Content A
1.3.1 Info and Relationships A
1.4.1 Use of Color A
1.4.3 Contrast (Minimum) AA
1.4.10 Reflow AA
1.4.11 Non-text Contrast AA
1.4.13 Content on Hover or Focus AA
2.1.1 Keyboard A
2.4.3 Focus Order A
2.4.7 Focus Visible AA
4.1.2 Name, Role, Value A

Automated test results: Accessibility and compliance.

  • The generated summary lists the chart type, series and point counts, axis ranges, per-series minimum and maximum with their positions, the overall trend, missing values, and hidden series.
  • Meaning never depends on color alone: marker shapes, dash patterns, and textures (patterns option), plus legend keys that repeat them.
  • Forced colors: series use CanvasText and keep shapes, dashes, and textures; focus uses Highlight.
  • No animation: nothing moves on render; hover and focus emphasis transitions are removed under prefers-reduced-motion and animation: none.
  • Series with more than 600 visible points in total use two proxy marks instead of one node per point; focus alternates between them so every move is announced. Browse-mode users read the exact values from the data table.
  • Zoom changes are announced politely (“Showing {from} to {to}.” or “Showing all data.”) and emitted as aui-zoom. Pointer-only gestures (Ctrl/Cmd + wheel, drag pan, Shift + drag selection) all have keyboard and toolbar equivalents.
  • The crosshair (crosshair option) is aria-hidden and follows both hover and keyboard focus; it hides when focus and the pointer leave.
  • Manual screen-reader verification (NVDA, JAWS, VoiceOver, TalkBack) is pending.
  • aria-roledescription support varies; screen readers without it announce “group”.

default, empty (“No data”), all series hidden (“All series are hidden”), series hidden, point focused (tooltip), hovered (shared tooltip), table open, dense (virtual points above 600 visible points), zoomed (window applied), panning or selecting (pointer drag), crosshair shown.

From Trigger To
any legend button (click, Enter, Space) series hidden or shown; aui-series-toggle emitted; domain rescales to visible series
plot not focused Tab active point focused, tooltip shown
point focused arrow keys, Home, End, PageUp, PageDown another point focused (tooltip follows)
tooltip visible Escape tooltip hidden, focus unchanged
table closed Show data table table built and shown; button reads “Hide data table”
any container resize re-render at the new width; focus kept on the same point
not zoomed Zoom in, +/=, Ctrl/Cmd + wheel up, Shift + drag zoomed; change announced; aui-zoom emitted
zoomed Zoom out, -, drag, arrow key past the window edge window widened or moved; announced; aui-zoom emitted
zoomed Reset zoom, 0, or zooming out to the full extent all data shown (“Showing all data.”); aui-zoom with x: null
  • The summary names the type, counts, x and y ranges, each series’ minimum and maximum with their x, the overall trend (first to last value), missing values, and hidden series.
  • With more than 600 visible points, points are virtual: two proxy marks alternate focus so each move is announced; browse-mode users read values from the data table.
  • Forced colors: series use CanvasText and are told apart by marker shape and dash pattern; focus uses Highlight.
  • Nothing animates; hover and focus emphasis transitions are removed under reduced motion.
  • The tooltip meets WCAG 1.4.13: shown on focus and hover, dismissible with Escape, hoverable, persistent.
  • Zoom changes are announced politely (“Showing {from} to {to}.”, “Showing all data.”). Every pointer gesture has a keyboard and toolbar equivalent (WCAG 2.1.1, 2.5.1).
  • The crosshair follows hover and keyboard focus and is aria-hidden.
  • Manual screen-reader verification is pending.

The width follows the container (ResizeObserver); the height is height. Tick counts, label thinning and truncation, and marker visibility adapt to the width. Reflows at 320 CSS px; wide data tables scroll in a focusable region.

direction: 'rtl' mirrors the x axis (first value at the right), puts the y axis on the right, and swaps ArrowLeft/ArrowRight. The legend, tooltip, and table follow the document direction.

Series colors come from color-chart-1..8 by palette slot (series position, or color). Each palette color meets 3:1 against surface, background, and sunken surfaces in all shipped themes (contrast gate). Gridlines use color-chart-grid (decorative), axes color-chart-axis (3:1).

configureAbsoluteUI({ components: { lineChart: { dataTable: 'hidden', markers: 'always', height: 240, crosshair: true } } });

Changes apply to existing instances immediately.

Instance options override global and theme defaults. All options are dynamic. zoom and zoomRange are instance-only (not globally configurable).

Time axes (Instant or ZonedDateTime x values) place ticks at wall-clock boundaries (midnight, first of month, January) in the configured timezone (instance, component, or common; UTC by default) and format all labels there. Across DST changes ticks follow local time, so their spacing is uneven. The host machine’s zone is never used.

No icons option. Legend keys and markers are drawn shapes. The zoom buttons render the icons plus, minus, and refresh through @absoluteui/icons; a global icon provider or registry entry for those names replaces them in every component that uses them.

All text uses textContent; SVG is built with createElementNS. Colors are classes; the plot height and tooltip position are written through the CSSOM. No innerHTML, style attributes, or inline handlers: compatible with style-src 'self' and require-trusted-types-for 'script'.

Renders the given data only; no persistence, network access, or telemetry. Validation errors name the option, never its value.

Budget: create with 5 series x 1,000 points (time axis) under 50 ms including the first render, re-render under 50 ms (e2e performance test, median of 5). Dense series use virtual points; the data table is built only when opened in toggle mode.

Tested with 5 series x 1,000 points. DOM size is independent of the point count above 600 visible points (except the line paths).

  • Empty x or series, or only missing values: “No data”.
  • Every series hidden: “All series are hidden”.
  • A single point is centered and drawn as a marker; the summary reads “{series}: {value} at {x}.”
  • A zero-width domain (all values equal) is widened so the line sits mid-plot.
  • Negative values: the domain crosses zero and a zero line is drawn.
  • Very long category labels are truncated (with an ellipsis) or thinned on the axis; the full text stays in the point labels, tooltip, and table.
Code Category Cause
LINE_CHART_OPTIONS configuration Missing label; x not an array of one kind; unsorted numeric/time x; series ids not unique; values length differs from x; invalid axis options.
CFG_INVALID_VALUE / CFG_UNKNOWN_OPTION configuration Invalid or unknown configuration (for example height outside 120-2000).

A failed construction leaves the host untouched; a failed update() keeps the previous state.

  • x values are shared; each series needs one value per x value.
  • Straight segments only.
  • Axis label widths are estimated (about 0.6 em per character).
  • The zoom window keeps at least two points visible; zoom is along x only.
  • Manual screen-reader verification is pending.
  • Zoom on the y axis; linked zoom across charts.
  • Secondary or logarithmic axes (use Combo Chart for a secondary axis); stacked areas.
  • Scatter data (per-series or unordered x): use Scatter Chart.
  • HTML in labels or tooltips.