Exporting

The download menu a chart can offer — the picture as a PNG or a PDF, and the numbers behind it as a CSV.

The download menu

withExport puts a button in the chart's top corner. It opens a menu offering the chart as a picture and as the numbers behind it:

Loading editor

Reach for it wherever the chart is the answer to a question somebody asked — a report they will send on, a dashboard tile whose numbers belong in a spreadsheet next. Leave it off where the chart is a small part of the page's furniture: a sparkline in a table cell, or a trend behind a headline number, is smaller than the button would be.

The button sits over the top corner of the plot rather than in a band of its own, so turning it on doesn't shorten the chart. That corner is the emptiest part of a plot — a value axis rounds up to a tick above its largest value — but it is not guaranteed empty, so check a chart whose data reaches the top right.

What each file is

PNG and PDF are the chart as it is drawn, at the size it is being read at and at twice its pixel density. The PDF is one page, sized to the chart itself.

Both are rendered from a scene of their own rather than photographed off the page, which is what keeps them clean: no crosshair, no focus dot, no half-finished entrance animation, and the legend drawn into the picture rather than left behind as the buttons it is on screen.

CSV is the numbers, one row per category and one column per series:

"Month","Email","SMS"
"Jan",42,9
"Feb",58,12
"Mar",76,16

Values go out at full precision rather than as the axis writes them — a tick reads 50k to fit the chart, and a cell that arrives in a spreadsheet that way is a string nobody can sum. Dates are written YYYY-MM-DD HH:mm:ss, in the same frame the category axis reads them in: UTC unless the axis asked for scale: 'time'.

A pie or donut is written as its slices, and a sankey as its flows, since neither has a category axis to lay a table out along.

Narrowing the menu

exportFormats decides which files are offered, and in which order:

<Chart
	ariaLabel="Email opens per day"
	exportFormats={['png']}
	marks={marks}
	withExport={true}
/>

CSV drops out of the menu on its own for a chart with no rows to write: one whose only marks are annotations, which label a plot rather than adding to it, and one whose definition is a builder function, since a builder is free to answer with marks Pluma never saw. A definition object doesn't take it away — that is laid over the definition the marks produced, so the rows are still the chart's own.

A chart left with no formats at all draws no button, so exportFormats={['csv']} on a chart Pluma has no rows for is the same as leaving withExport off.

What the files are called

Files are named after the chart's ariaLabel, as a slug — a chart labelled "Messages delivered per month" downloads as messages-delivered-per-month.png. Set exportFileName to name them yourself, without an extension.

What a download costs

Nothing until it is used. The code that writes a file — the second renderer, the rasterizer, the PDF writer — is loaded when the reader picks a format, not when the chart renders, so a page full of downloadable charts carries none of it.

Known limits

A chart is rasterized through the browser's own image decoder, which loads the chart's SVG as a document of its own. Web fonts don't reach it, so text in a PNG or a PDF is drawn in the nearest font the system has rather than the product's. Everything else — colors, type sizes, guide weights, and any CSS variable a consumer overrode — is measured off the chart on screen and written into the picture.

A series the reader has hidden from the legend is left out of every format, including the CSV. An export is what they are looking at, whichever form they asked for it in.