Dynamic Charts
The chart atom IS the chart state. Call set(…) with a new options object or update(…) with a mutator and the mounted chart patches itself via Highcharts' own chart.update — no imperative chart code, no re-render of the template.
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: "Requests / second"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
xAxis: {
categories: [
"-4s",
"-3s",
"-2s",
"-1s",
"now"
]
},
yAxis: {
title: {
text: "req/s"
},
min: 0
},
plotOptions: {
series: {
marker: {
enabled: false
},
lineWidth: 2
}
},
series: [
{
type: "line",
name: "req/s",
data: [
42,
51,
38,
63,
57
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
Live examples
Replace the series data on an interval with chart.set(…). Highcharts animates the transition; the rest of the page never re-renders.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "line"
},
title: {
text: "Requests / second"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
xAxis: {
categories: [
"-4s",
"-3s",
"-2s",
"-1s",
"now"
]
},
yAxis: {
title: {
text: "req/s"
},
min: 0
},
plotOptions: {
series: {
marker: {
enabled: false
},
lineWidth: 2
}
},
series: [
{
type: "line",
name: "req/s",
data: [
42,
51,
38,
63,
57
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
chart.events.click receives the chart instance as `this` — addPoint appends to the series and the axis scrolls via shift. The handler is part of the config, so the copy-paste snippet includes it.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "spline",
events: {}
},
title: {
text: "Click anywhere to add a point"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
xAxis: {
categories: [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7"
]
},
yAxis: {
title: {
text: "Value"
},
min: 0
},
plotOptions: {
series: {
marker: {
enabled: true,
radius: 3
}
}
},
series: [
{
type: "spline",
name: "Random walk",
data: [
31,
42,
38,
51,
44,
62,
57,
49
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
Charts read plain atoms — wire them to any other state with effect(). When the source atom changes, the chart updates in place.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "column"
},
title: {
text: "Sales by year — driven by an atom"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
xAxis: {
categories: [
"2023",
"2024",
"2025",
"2026"
]
},
yAxis: {
title: {
text: "$k"
}
},
series: [
{
type: "column",
name: "Sales",
data: [
410,
480,
520,
610
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
chart.update(fn) mutates the current config — change a title, restyle a series or swap the chart type without rebuilding options from scratch.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "column"
},
title: {
text: "Quarterly revenue"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: true
},
xAxis: {
categories: [
"Q1",
"Q2",
"Q3",
"Q4"
]
},
yAxis: {
title: {
text: "$k"
}
},
series: [
{
type: "column",
name: "Revenue",
data: [
120,
140,
135,
170
]
},
{
type: "line",
name: "Target",
data: [
130,
130,
130,
130
],
dashStyle: "Dash"
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
set() with a different series array swaps the whole chart content — toggle datasets, change granularity, or swap chart.type in one call.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "line"
},
title: {
text: "Toggle datasets"
},
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: "Online",
data: [
22,
31,
28,
41,
38,
49
]
},
{
type: "line",
name: "Retail",
data: [
40,
36,
44,
39,
47,
43
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
Update yAxis.min/max reactively to zoom into a range — pairs well with controls built from ordinary mates atoms.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "column"
},
title: {
text: "Latency p50–p99"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
xAxis: {
categories: [
"eu-1",
"eu-2",
"us-1",
"us-2",
"ap-1"
]
},
yAxis: {
title: {
text: "ms"
},
min: 0,
max: 400
},
series: [
{
type: "column",
name: "p99",
data: [
84,
96,
172,
210,
330
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
Keep the last N points: append the new value and drop the first — the classic rolling telemetry chart.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "areaspline"
},
title: {
text: "Memory usage (last 10 samples)"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
xAxis: {
categories: [
"-9s",
"-8s",
"-7s",
"-6s",
"-5s",
"-4s",
"-3s",
"-2s",
"-1s",
"0s"
],
labels: {
enabled: false
}
},
yAxis: {
title: {
text: "MB"
},
min: 0
},
plotOptions: {
areaspline: {
fillOpacity: 0.3,
marker: {
enabled: false
},
lineWidth: 1.5
}
},
series: [
{
type: "areaspline",
name: "Heap",
data: [
210,
224,
219,
241,
236,
252,
248,
263,
259,
271
]
}
]
});
// 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 dynamic charts charts. See the full Highcharts API for everything else.
| Option | Type | Default | Description |
|---|---|---|---|
chart.events.click |
Function | — | `this` is the chart — e.g. this.series[0].addPoint(…) on click. |
chart.events.load |
Function | — | Runs once on mount — start polling here if you prefer events to atoms. |
series[].addPoint(value, redraw, shift) |
Function | — | Append a point; shift drops the oldest for sliding windows. |
chart.update(options, redraw, oneToOne) |
Function | — | The imperative equivalent of atom.set — mates-charts calls it for you. |
chart.setType(type) |
Function | — | Swap the series type at runtime. |
yAxis.setExtremes(min, max) |
Function | — | Zoom the axis programmatically. |
series[].pointInterval / pointStart |
number | — | Generate datetime x positions without listing them. |
plotOptions.series.animation |
boolean | AnimationOptions | true | Transition between atom updates. |