Charts
The Chart block renders bar, horizontal bar, line, area, pie and donut charts from a list. Charts are generated as SVG by pure functions (d3-scale and d3-shape for the maths only), so the same geometry reaches the editor, the preview and the PDF. The shapes are identical; chart labels are real text, so they are set by whichever engine is drawing and can differ by a fraction of a point in width between the two PDF backends.
Binding
- Data from — the list (
portfolio.history). - Category label — an expression per item (
point.month,slice.assetClass). - Series — one or more
{ label, value, colour? }entries; values are expressions per item (point.value). Pie and donut charts use the first series and colour each category from the theme palette. - Value format — a formatter pipe applied to axis ticks and labels (
currency:"GBP":0,percent).
Colours come from theme.colors.chart in order, so switching brand recolours every chart. Individual series may override.
Options
Legend, value labels, grid lines, stacked (bar/line/area), smooth lines, percentage decimals, donut centre label (may contain tokens: {{ count(portfolio.allocation) }} classes).
Progress / gauge
The Progress / gauge block shows a single value against a maximum as a bar or a semicircular gauge, with colour thresholds (up to 3 → green, up to 7 → amber…) and value formatting as a percentage, a raw value or x / max.
Interactive on screen, unchanged in print
Charts respond to a pointer in preview mode: hovering a bar, slice or point dims the rest, raises a tooltip naming the category, the series and the formatted value, and reports the share for pie and donut charts. Marks are focusable, so the same information is reachable from the keyboard, and each carries an aria-label for a screen reader.
Nothing is drawn twice to achieve this. Adding a charting library on screen would give you two chart implementations that drift, and a screen that no longer matches the file — which is the one thing this product exists to prevent. The SVG the reader points at is the SVG the PDF contains; the block records what each mark stands for as it draws it, and the interaction layer reads the real element's own box. The PDF translator strips those attributes, so the printed bytes are identical whether interactions were on or not.
In the designer this is on in preview mode and off while you are editing, where a hover belongs to selecting and dragging. interactiveCharts changes that:
createReportDesigner(el, { interactiveCharts: "preview" }); // default
createReportDesigner(el, { interactiveCharts: "always" }); // design mode too
createReportDesigner(el, { interactiveCharts: "off" });Outside the designer — a report you have rendered into your own page with layoutDocument — call it yourself. It returns a teardown that puts the DOM back exactly as it found it.
import { enableChartInteractions } from "@broadpaper/renderer";
const stop = enableChartInteractions(container, {
tooltip: (hit) => `${hit.category}: ${hit.formatted}`,
onSelect: (hit) => drillInto(hit.categoryIndex)
});onChart(element, payload) is the escape hatch: return false for a chart you would rather handle yourself — mount your own library over the box, or leave it alone entirely. The SVG underneath is still what prints.
Page flow
Charts are atomic and keep-together by default; a chart that does not fit moves to the next page. Set an explicit height in the inspector to control density.