Line
Line charts connect data points in the order they appear — the default choice for trends over time. In mates-charts you select it with chart.type = "line" (or per-series type) and pass standard Highcharts options; the Chart component keeps the rendered chart in sync with the atom.
Usage
Create a chart atom with standard Highcharts options,
then render Chart(chart) anywhere in a
mates template. Every later chart.set(…) or
chart.update(…) re-renders the chart — no
imperative Highcharts code.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "line"
},
title: {
text: "Monthly Revenue"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
xAxis: {
categories: [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun"
]
},
yAxis: {
title: {
text: "Revenue ($k)"
}
},
series: [
{
type: "line",
name: "Revenue",
data: [
12,
19,
15,
25,
22,
30
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
Live examples
One series with categories on the x-axis. The wrapper div sets the height — the chart fills whatever box you give it.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "line"
},
title: {
text: "Monthly Revenue"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
xAxis: {
categories: [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun"
]
},
yAxis: {
title: {
text: "Revenue ($k)"
}
},
series: [
{
type: "line",
name: "Revenue",
data: [
12,
19,
15,
25,
22,
30
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
dataLabels print each point's value. The crop option stops labels at the edge from spilling out of the chart box.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "line"
},
title: {
text: "NordicAdventure sales"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: true
},
xAxis: {
categories: [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
]
},
yAxis: {
title: {
text: "Temperature (°C)"
},
labels: {
format: "{value}°"
}
},
plotOptions: {
line: {
dataLabels: {
enabled: true,
format: "{y}°"
},
enableMouseTracking: false
}
},
series: [
{
type: "line",
name: "Oslo",
data: [
-4,
-3,
1,
6,
12,
16,
18,
17,
12,
6,
1,
-2
]
},
{
type: "line",
name: "Munich",
data: [
1,
2,
6,
10,
15,
18,
20,
19,
15,
10,
4,
2
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
xAxis.type = "datetime" plus chart.zooming.type = "x" enables drag-to-zoom; double-click resets. Highcharts picks sensible tick positions automatically.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "line",
zooming: {
type: "x"
}
},
title: {
text: "USD to EUR exchange rate"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
xAxis: {
type: "datetime",
labels: {
format: "{value:%b %y}"
}
},
yAxis: {
title: {
text: "Exchange rate"
}
},
plotOptions: {
series: {
marker: {
enabled: false
},
lineWidth: 1.5
}
},
series: [
{
type: "line",
name: "USD → EUR",
pointStart: 1735689600000,
pointInterval: 1209600000,
data: [
0.92,
0.94,
0.91,
0.89,
0.93,
0.95,
0.92,
0.9,
0.88,
0.91,
0.94,
0.96,
0.93,
0.9,
0.89,
0.92,
0.95,
0.97,
0.94,
0.92
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
Color-coded zones (plotBands) and threshold markers (plotLines) on the y-axis turn a plain line into an annotated status chart.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "line"
},
title: {
text: "Server load"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
xAxis: {
categories: [
"00:00",
"04:00",
"08:00",
"12:00",
"16:00",
"20:00",
"24:00"
]
},
yAxis: {
title: {
text: "CPU %"
},
max: 100,
plotBands: [
{
from: 0,
to: 60,
color: "rgba(22, 163, 74, 0.08)",
label: {
text: "Healthy",
style: {
color: "#16a34a"
}
}
},
{
from: 60,
to: 85,
color: "rgba(217, 119, 6, 0.10)",
label: {
text: "Elevated",
style: {
color: "#d97706"
}
}
},
{
from: 85,
to: 100,
color: "rgba(220, 38, 38, 0.10)",
label: {
text: "Critical",
style: {
color: "#dc2626"
}
}
}
]
},
plotOptions: {
series: {
marker: {
enabled: false
},
lineWidth: 2
}
},
series: [
{
type: "line",
name: "CPU",
data: [
22,
18,
41,
74,
88,
63,
35
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
chart.inverted swaps the x and y axes — the line grows downward. A one-line variant of the standard time series.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "line",
inverted: true
},
title: {
text: "Rally stage times"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
xAxis: {
categories: [
"SS1",
"SS2",
"SS3",
"SS4",
"SS5",
"SS6"
]
},
yAxis: {
title: {
text: "Minutes behind leader"
}
},
series: [
{
type: "line",
name: "Gap",
data: [
0,
4.2,
7.8,
9.1,
14.6,
18.2
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
yAxis.type = "logarithmic" handles data spanning orders of magnitude — early startup growth, viral curves, exponential decays.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "line"
},
title: {
text: "Weekly active users"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
xAxis: {
categories: [
"W1",
"W2",
"W3",
"W4",
"W5",
"W6",
"W7",
"W8"
]
},
yAxis: {
type: "logarithmic",
title: {
text: "Users (log)"
},
minorTickInterval: 0.1
},
series: [
{
type: "line",
name: "WAU",
data: [
12,
48,
190,
810,
3400,
12500,
41000,
128000
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
series[].step = "left" | "center" | "right" draws right-angle steps instead of diagonals — ideal for state changes and rate changes over time.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "line"
},
title: {
text: "Plan tier over time"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
xAxis: {
categories: [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun"
]
},
yAxis: {
title: {
text: "Users"
}
},
plotOptions: {
line: {
step: "left",
marker: {
enabled: true,
radius: 3
}
}
},
series: [
{
type: "line",
name: "Users",
data: [
1,
1,
4,
4,
4,
12
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
Per-series dashStyle and marker.symbol distinguish overlapping series without relying on colour alone.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "line"
},
title: {
text: "Forecast vs actual"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: true
},
xAxis: {
categories: [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun"
]
},
yAxis: {
title: {
text: "$k"
}
},
series: [
{
type: "line",
name: "Actual",
data: [
15,
18,
14,
22,
26,
24
],
lineWidth: 2.5,
marker: {
symbol: "circle",
radius: 4
}
},
{
type: "line",
name: "Forecast",
data: [
15,
17,
16,
20,
25,
27
],
dashStyle: "Dash",
marker: {
symbol: "diamond",
radius: 4
}
},
{
type: "line",
name: "Target",
data: [
18,
18,
18,
18,
18,
18
],
dashStyle: "Dot",
marker: {
enabled: false
}
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
tooltip.shared groups all series into one hover tooltip — essential for comparing series.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "line"
},
title: {
text: "Revenue vs Costs"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: true
},
xAxis: {
categories: [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun"
]
},
yAxis: {
title: {
text: "$k"
}
},
tooltip: {
shared: true
},
series: [
{
type: "line",
name: "Revenue",
data: [
12,
19,
15,
25,
22,
30
]
},
{
type: "line",
name: "Costs",
data: [
8,
12,
14,
13,
18,
16
]
},
{
type: "line",
name: "Profit",
data: [
4,
7,
1,
12,
4,
14
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
The annotations module adds labels, shapes and arrows anchored to data points or pixels — callouts, targets and trend commentary.
import "highcharts/modules/annotations";
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "line"
},
title: {
text: "Launch metrics"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
xAxis: {
categories: [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun"
]
},
yAxis: {
title: {
text: "$k"
}
},
annotations: [
{
labels: [
{
point: {
xAxis: 0,
yAxis: 0,
x: 3,
y: 25
},
text: "Pricing change",
backgroundColor: "rgba(0, 150, 140, 0.9)",
style: {
color: "#ffffff"
}
},
{
point: {
xAxis: 0,
yAxis: 0,
x: 5,
y: 30
},
text: "All-time high",
backgroundColor: "rgba(217, 119, 6, 0.9)",
style: {
color: "#ffffff"
}
}
]
}
],
series: [
{
type: "line",
name: "MRR",
data: [
12,
15,
18,
25,
23,
30
],
lineWidth: 2.5
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
Highcharts' built-in accessibility layer announces the chart to screen readers — description, series descriptions and keyboard table navigation come free.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "line"
},
title: {
text: "Weekly active users"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
accessibility: {
description: "Line chart of weekly active users over the first half of 2026, rising from 12,000 to 30,000."
},
xAxis: {
categories: [
"W1",
"W2",
"W3",
"W4",
"W5",
"W6"
]
},
yAxis: {
title: {
text: "Users"
}
},
plotOptions: {
series: {
accessibility: {
point: {
valueDescriptionFormat: "{xDescription}: {value} users"
}
}
}
},
series: [
{
type: "line",
name: "WAU",
data: [
12,
15,
19,
22,
26,
30
],
lineWidth: 2.5
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
zones recolour a series above/below a value — profit above the zero line, loss below, in one series definition.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "line"
},
title: {
text: "Monthly profit"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
xAxis: {
categories: [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug"
]
},
yAxis: {
title: {
text: "$k"
},
plotLines: [
{
value: 0,
width: 1,
color: "#00968c"
}
]
},
series: [
{
type: "line",
name: "Profit",
data: [
-3,
2,
-5,
6,
8,
-2,
11,
14
],
lineWidth: 2.5,
zoneAxis: "y",
zones: [
{
value: 0,
color: "#dc2626"
},
{
color: "#00968c"
}
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
Options reference
mates-charts passes options straight through to Highcharts — these are the keys that matter for line charts. See the full Highcharts API for everything else.
| Option | Type | Default | Description |
|---|---|---|---|
chart.type |
"line" | "line" | Sets the default series type for the whole chart. |
series[].data |
number[] | [x, y][] | PointOptions[] | — | Values, [x, y] tuples, or point objects ({ x, y, name, color, events }). |
plotOptions.line.lineWidth |
number | 2 | Pixel width of the line. |
plotOptions.line.dashStyle |
"Solid" | "Dash" | "Dot" | "ShortDash" | "LongDash"… | "Solid" | Line dash pattern. |
plotOptions.series.step |
"left" | "center" | "right" | undefined | Draw right-angle steps between points. |
series[].zones / zoneAxis |
Zone[] / "x" | "y" | — | Recolour the line above/below a value threshold. |
plotOptions.series.marker.enabled |
boolean | auto | Show point markers; Highcharts auto-hides them on dense data. |
plotOptions.series.marker.symbol |
"circle" | "square" | "diamond" | "triangle" | "triangle-down" | "circle" | Marker shape. |
plotOptions.series.stacking |
undefined | "normal" | "percent" | undefined | Stack series values on top of each other, or normalise to 100%. |
xAxis.type |
"linear" | "datetime" | "logarithmic" | "category" | "linear" | Use "datetime" with millisecond timestamps, or "category" with ordinal data. |
xAxis.categories |
string[] | — | Category labels; index-matched to data points. |
xAxis.plotBands / plotLines |
Band[] / Line[] | — | Colour-coded y-zones and threshold markers. |
chart.inverted |
boolean | false | Swap the x and y axes. |
chart.zooming.type |
"x" | "y" | "xy" | undefined | Enable drag-to-zoom along an axis. |
tooltip.shared |
boolean | false | One tooltip showing every series at the hovered x position. |
legend.enabled |
boolean | true | Show the series legend. |