pyreon

Every chart on this page is live: it runs on @pyreon/charts, Pyreon's own engine, in this page. Charts follow the page's scheme: the color-scheme the page declares on <html> (this site sets it with its theme toggle), else the OS preference. Each example's source is one click away.

@pyreon/chartsstable

A trend

An area under a smoothed line, its points and a dashed target. One currencyformatter feeds the axis, the tooltip and the accessible table at once.

Revenue against target

Stacked or grouped

The same three series, switched between a stack and side-by-side bars. The mark list is reactive, so the switch repaints the same canvas.

Orders by channel

A ranking

horizontal turns the category axis on its side; showValues labels each bar.

Horizontal bars

A donut

An <Arc> with an inner radius, and a legend whose entries toggle their slices.

Donut

A radar

Radar

Candlesticks

A 120-day price series with a navigator strip: drag the strip's band or a handle, or scroll and drag inside the plot. The day labels thin to what fits.

Candlesticks with a navigator

A heatmap

Activity by weekday and hour, one <Cell> per observation.

Heatmap

Direct labels

<Legend direct /> names each line at its last point, in the line's own colour, instead of in a legend box.

Direct labels

A keyed sliding window

"Vary" drops the oldest bar and appends a new one. by="t" gives each row an identity, so every bar tweens from its own previous value; without it, rows match by position and each bar animates toward its neighbour's value.

Sliding window

A time axis

xValue places each point at its epoch-ms timestamp, so uneven gaps between samples stay uneven on screen. <Axis x time> picks calendar ticks anddate('MMM YYYY') labels them.

Time axis

A funnel

One <Stage> per row, drawn largest first.

Funnel

A boxplot

BoxplotChart takes raw samples per category and computes the quartiles, whiskers and outliers itself. (Pass summary instead when you already have the five numbers.)

Boxplot

A calendar

One cell per day, keyed by ISO date, between start and end.

Calendar

A chord diagram

Flows between a set of nodes, each ribbon as wide as its value at both ends.

Chord

A Gantt chart

Tasks grouped into lanes, with progress, dependency elbows and a milestone.

Gantt

A network graph

Nodes on a circle, sized by value and coloured by category. layout also takes 'force', or 'none' for positions you supply.

Graph

Parallel coordinates

One polyline per row across several axes; an axis can be categorical.

Parallel coordinates

A polar chart

Bars and a line on polar axes, the categories around the angle.

Polar

A river

A streamgraph: layers stacked around a centre line.

River

A Sankey diagram

Flows from sources through intermediate nodes to outcomes, each link as wide as its value.

Sankey

A sunburst

A hierarchy as rings; a parent without a value is the sum of its children.

Sunburst

A tree

The same kind of hierarchy drawn as nodes and links, left to right.

Tree

A treemap

Each leaf a rectangle with area proportional to its value, nested inside its parent.

Treemap

A single axis

Points along one axis, sized by a second value.

Single axis

A gauge driven by a signal

gaugeDial() builds the full dial; writing the signal repaints it.

Gauge

100,000 points

Every point drawn, no decimation. "Regenerate" replaces all of them and reports how long the redraw took on your machine. (maxPoints decimates to the plot's pixel width when you want the same picture for a fraction of the work.)

100,000 points, redrawn

A live stream

A new sample every 250ms into a 60-point window. Each write repaints the canvas and nothing else: the chart is one effect over one signal.

Streaming

Against ECharts

The same charts, measured in examples/benchmark (bun run bench:charts for speed, bun run bench:charts-bundle for size). These suites landed after the 2026-09-23 full run recorded in BENCHMARKS.md, which lists the charts scenario as not yet measured; treat the figures below as single-machine, author-run numbers pending that record. Size, gzipped, beyond a bare Pyreon app's runtime:

Chart@pyreon/chartsECharts 6, tree-shakenECharts 6, whole package
Line40.9 KB155.9 KB361.1 KB
Bar + line, tooltip, legend40.9 KB176.8 KB—
Pie18.1 KB117.3 KB—

Speed, one line chart on an 800×400 canvas. The figures are medians in milliseconds from real Chromium with animation off on both sides; absolute numbers depend on the machine, so read them for their ratios:

OperationPlotChartECharts 6
First render, 100,000 points28.246.5
Update all 100,000 points20.232.8
Update one of 1,000 points1.62.1
First render, 1,000 points10.44.5

The last row is a loss, and it comes from one feature. Pyreon renders an offscreen data table (up to 1,000 rows) for screen readers by default; ECharts renders none. Without it (accessibleTable={false}) the same chart's first render is 1.5 ms. The rest is the style and layout of about 3,000 real table cells. Skipping that layout is possible, but in Chromium it also removes the rows from the accessibility tree, the one place the table is read. That cost is what makes the chart readable without sight, and Pyreon keeps it on by default.

Chart Gallery