🧪 Experimental feature (preview). This feature is under active development and released early so you can try it and give feedback. Behaviour, options, and results can change without notice, and it isn’t covered by the usual support and stability guarantees. Avoid relying on it for production work.
Overview
A Report chart tile names a chartType and a handful of columns. Between your JSON and the chart primitive that draws it sits an adapter: a small piece of data shaping that groups, rolls up, buckets or pivots the page’s records into the shape that primitive wants. Which adapter runs — and therefore which fields the tile reads — is decided by the chart’s family.
This page is the reference for that layer. For the envelope around a tile (size, palette, theme, filter, the list and hosted tiles), see Writing Report Definitions. For which chart to choose given a set of columns, see Designing a Report from Data.
Two facts shape everything below:
- Every tile is 300 px tall. A chart has to read at that size. Fewer categories and shorter labels always win.
- Aggregation happens at render time from the records on the page. You choose columns and a method; you never write values. Text that looks like a number is treated as a number; a cell that’s empty groups under
(none).
How a chart gets its data
Ten adapters feed the 36 chart types. Knowing what they do explains most surprises.
Categorical roll-up
Feeds: bar, horizontalBar, lollipop, pareto, pie, donut, treemap, funnel, waterfall, line, area, sparkline, figure, gauge, bullet.
Groups the records by dimension and rolls up measure with aggregation:
count— rows per group.measureis ignored (write"").sum— the total ofmeasureper group. Non-numeric cells count as 0.avg— the mean ofmeasureper group.
Values are rounded to two decimals. Groups are sorted largest first and capped at 8: the top 7 keep their names and everything else is lumped into one Other bucket (for avg, Other is the mean of the lumped means). Empty cells group as (none).
Two consequences matter. A dimension with dozens of values still renders — as seven bars and a big Other — so pick dimensions with 2–12 distinct values. And the order is by value, never by your data’s order, which is why the line, area and funnel charts in this family don’t preserve a sequence (see each chart below).
Pivot
Feeds: groupedBar, stackedBar, radar, heatmap, sunburst.
A two-way table: dimension values become the categories (most frequent first, capped at 12), seriesField values become the series (most frequent first, capped at 8), and each cell is the roll-up of measure by aggregation for that pair. Both columns should be categoricals with a handful of values each; a 12 × 8 heatmap is the most a 300 px tile will show legibly.
Time buckets
Feeds: timeSeries, timeBar, cumulative, burndown, calendar.
Parses dimension as a date, buckets every row into the calendar period named by granularity (day, week, month, quarter, year), rolls up measure by aggregation per period, and returns the periods in chronological order. Rows whose date won’t parse are skipped.
- Empty periods between the first and last are filled with zero so gaps read as gaps (not for
avg, where a zero mean would be a lie). At most 400 periods are shown; a day-grained span of many years keeps only the latest 400. - Date parsing handles ISO (
2026-03-01), slash and dash dates, epoch numbers, and anything the browser parses. Day-first versus month-first is detected from the whole column (a component over 12 settles it), so1/6/2026is read consistently for the data rather than always as January 6th. - Labels follow the grain:
Aug 5,Aug 2026,2026-Q3,2026.
Weeks start on Monday. cumulative replaces each period’s value with the running total to that point.
Flow stages
Feeds: sankey, network, flow.
Reads stageFields, an ordered list of at least two columns. Each record threads through every stage in order, and links are aggregated between every consecutive pair (stage 0 → 1, 1 → 2, …), weighted by measure/aggregation. Nodes are scoped to their stage, so the value "Open" in stage 1 and "Open" in stage 3 are two different nodes and the graph stays a clean left-to-right flow. Zero-weight links are dropped; at most 120 links are kept. With stageFields absent, the adapter uses [dimension, seriesField] as a two-stage flow.
XY points
Feeds: scatter, bubble.
One point per record: xMeasure and yMeasure (and sizeMeasure for bubbles) read as numbers; rows where either won’t parse are skipped. No aggregation. An optional seriesField colours the points by group, up to 8 groups.
Box statistics
Feeds: boxplot.
Groups measure values by dimension and computes min, lower quartile, median, upper quartile and max per group, for up to 12 groups. No aggregation; needs several rows per group to mean anything.
Histogram values
Feeds: histogram.
Collects every numeric value of measure across all rows — no dimension, no aggregation — and the primitive bins them into equal-width bins spanning the observed range.
Daily OHLC
Feeds: candlestick.
Groups rows by the calendar day of dimension, and for each day takes measure’s first value as open, last as close (in the order the records arrive), and the day’s extremes as high and low. No aggregation. Days are ordered chronologically.
Spans
Feeds: gantt.
One bar per record from startField to endField (both parsed as days; rows missing either are skipped; an end before its start is swapped). labelField names the row, falling back to #1, #2, …; seriesField colours bars by group. At most 60 spans, sorted by start.
Families at a glance
| Family | Chart types | Fields read | Adapter |
|---|---|---|---|
| categorical | bar, horizontalBar, lollipop, pareto, pie, donut, treemap, funnel, waterfall, line, area, sparkline, figure, gauge, bullet | dimension, measure, aggregation | Categorical roll-up |
| series | groupedBar, stackedBar, radar, sunburst | dimension, seriesField, measure, aggregation | Pivot |
| matrix | heatmap | dimension (X), seriesField (Y), measure, aggregation | Pivot |
| flow | sankey, network, flow | stageFields, measure, aggregation | Flow stages |
| xy | scatter, bubble | xMeasure, yMeasure, sizeMeasure (bubble), seriesField | XY points |
| distribution | boxplot | dimension, measure | Box statistics |
| histogram | histogram | measure | Histogram values |
| ohlc | candlestick | dimension (date), measure | Daily OHLC |
| time | timeSeries, timeBar, cumulative, burndown | dimension (date), granularity, measure, aggregation | Time buckets |
| calendar | calendar | dimension (date), measure, aggregation | Time buckets (always daily) |
| gantt | gantt | startField, endField, labelField, seriesField | Spans |
Fields a family doesn’t read are ignored, not rejected. Setting only what’s needed keeps a definition honest about what drives each chart.
Chart by chart
Grouped the way the picker groups them. “Best with” describes the data shape that makes the chart worth looking at. Palette group: categorical means distinct hues for unordered categories (ember, tableau, slate, earthen); sequential means a continuous ramp for magnitude or order (viridis, inferno, magma, plasma, cividis, turbo, warm, cool, spectral). See Palettes.
Compare
chartType | Draws | Best with | Notes |
|---|---|---|---|
bar | Vertical bars, one per category | text/boolean dimension with 2–12 values | The safe default. Legend on either side, or off (labels move to the axis). Categorical palette. |
horizontalBar | Bars running left to right | 6–12 categories or long labels | Labels read sideways without truncation. No legend control. Categorical. |
lollipop | A dot on a stem per category | Sparse comparisons where bars feel heavy | Same data as a bar with less ink. No legend control. Categorical. |
pareto | Bars largest-first plus a cumulative-percent line | “Which few categories make up most of the total?” | The roll-up is already largest-first, so the pareto line is meaningful. No legend control. Categorical. |
groupedBar | Clustered bars: a bar per series within each category | Two categoricals, ≤ 8 × 8 | dimension = clusters, seriesField = bars within a cluster. Legend side/off. Categorical. |
stackedBar | One bar per category, split by series | Same shape, when the per-category total matters | Legend side/off. Categorical. |
radar | A polygon per series over shared axes | 3–8 categories, 2–4 series | dimension = axes, seriesField = polygons. Gets noisy fast. Legend side/off. Categorical. |
Composition
chartType | Draws | Best with | Notes |
|---|---|---|---|
pie | Slices with a side legend | 2–6 categories | Past six slices the small ones vanish. Legend on/off. Categorical. |
donut | Pie with an open centre | 2–6 categories | Legend on/off. Categorical. |
sunburst | Two concentric rings | dimension (inner ring) × seriesField (outer ring) | Without seriesField it degrades to a single-ring donut of the roll-up. No legend control. Categorical. |
treemap | Nested rectangles sized by value | Up to ~12 categories with one measure | In-cell labels appear only on big cells; the side legend carries the rest. Legend on/off. Categorical by count; sequential when sized by a measure. |
funnel | Narrowing stages | Real stage-like drop-off | Stages are ordered by value, largest first, not by any order in your data — so the funnel shows relative size of stages, and only reads as a true funnel when the stages really do shrink in sequence. Legend on/off. Categorical. |
waterfall | Running total across steps | Contributions that add up to a total | Every category is a positive step in largest-first order, so it reads as “how the total accumulates”. Legend side/off. Sequential. |
Trend
chartType | Draws | Best with | Notes |
|---|---|---|---|
timeSeries | A line over calendar periods | Any date column | Use this for dates. Chronological, gap-filled, bucketed by granularity. No legend control. Sequential. |
timeBar | Columns over calendar periods | Dated counts where volume per period matters | Same buckets as timeSeries. Legend side/off (axis labels when off). Sequential. |
cumulative | Filled running total over periods | Growth-to-date, backlog accumulated | Same buckets, running sum. No legend control. Sequential. |
burndown | Remaining work over periods | Genuine remaining-work data only | Plots each period’s value as “remaining”, with the largest bucket as the total and first/last periods as start and deadline. Meaningless on ordinary event counts. No legend control. Sequential. |
line | A line over the categorical roll-up | Rarely the right choice in a report | Points are sorted by value, not by order — a line over a date column will not be chronological. Reach for timeSeries instead. No legend control. |
area | Filled version of line | Rarely | Same caveat. Prefer cumulative. No legend control. |
sparkline | A tiny trend line with the latest value and its delta | Rarely, as wired today | Fed the value-sorted roll-up, so the line always slopes down and the delta is the gap between the two smallest groups. For a compact trend, use a timeSeries at size S. Legend side. |
Time
chartType | Draws | Best with | Notes |
|---|---|---|---|
calendar | A weekday × week grid, one cell per day, coloured by value | A date column spanning weeks to months, many rows | Always daily; granularity is ignored. Pointless for a handful of rows. Sequential palette, always. |
gantt | One bar per record on a shared date axis | Two date columns (start and end) plus a naming column | startField, endField, labelField; seriesField colours by group. Up to 60 bars sorted by start. Categorical when grouped. |
candlestick | Open/high/low/close per day | A dated numeric that changes within a day | dimension = date column, measure = the value. Needs several rows per day; one row per day gives a flat candle. No legend control. |
Distribution
chartType | Draws | Best with | Notes |
|---|---|---|---|
histogram | Equal-width bins of one numeric column | A genuine measure with spread (amounts, durations, ages) | measure only — no dimension, no aggregation. Never bin an id. No legend control. |
boxplot | Min/quartiles/median/max per group | A measure with several rows per category | dimension + measure; up to 12 groups. Legend side/off. Categorical. |
heatmap | A colour matrix | Two categoricals and a measure (or counts) | dimension = columns (X, ≤ 12), seriesField = rows (Y, ≤ 8). orientation moves the colour scale. Sequential palette, always. |
Relationship
chartType | Draws | Best with | Notes |
|---|---|---|---|
scatter | One dot per record | Two numeric columns that both vary | xMeasure, yMeasure; optional seriesField for colour (≤ 8 groups). Ids are never valid axes. Legend side/off. Categorical. |
bubble | Scatter with dot area from a third numeric | Three varying numerics | Adds sizeMeasure. Legend side/off. Categorical. |
sankey | Weighted ribbons between ordered stages | 2–4 categorical columns that form a real progression | stageFields in order; measure/aggregation sets ribbon weight. Legend side/off. Categorical. |
network | A force-laid node-link graph | The same staged columns, when the connections matter more than the weights | Nodes are coloured by stage; links are unweighted. Legend side/off. Categorical. |
flow | Boxes and arrows in left-to-right columns | The same staged columns, when it should read like a flowchart | Legend side/off. Categorical. |
Single value
chartType | Draws | Best with | Notes |
|---|---|---|---|
figure | KPI cards: the largest group as a hero number, the rest listed beside it | A low-cardinality dimension where the top value is the headline | It is one number per category, not one total. For a single headline figure use the hosted numberLabel tile, or a figure whose dimension has one value. orientation picks the list’s side. Sequential. |
gauge | A 270° dial | A total that should read against a round ceiling | Value = the sum across all groups (total records, or total of measure); the maximum is the next “nice” number (1, 2, 5 × 10ⁿ) above it. There is no real target — it’s a total with a ceiling. Legend side/off. Sequential. |
bullet | A bar per category against a target tick | Categories to compare against their own average | The target is the mean across categories; the range is a nice ceiling. Skip unless “above or below average” is the point. Legend side/off. Categorical. |
Legends and orientation
orientation (left / right) and showLegend: false don’t apply to every chart. What they do depends on the primitive:
| Charts | orientation | showLegend: false |
|---|---|---|
| bar, timeBar, groupedBar, stackedBar, boxplot, waterfall | Moves the legend to that side | Hides the legend and labels the axis instead |
| figure, gauge, bullet, sparkline, radar, heatmap, sankey, network, flow, scatter, bubble | Moves the legend or list to that side | Hides the legend (radar, gauge, sankey, network, flow, scatter, bubble); no effect on figure, bullet, sparkline, heatmap |
| pie, donut, treemap, funnel | No effect | Hides the side legend |
| calendar, gantt | Moves the legend / colour scale to that side | No effect |
| horizontalBar, lollipop, pareto, sunburst, line, area, timeSeries, cumulative, burndown, histogram, candlestick | No effect | No effect |
Omit showLegend for the default (shown). A legend hidden on a bar chart is often the better small-tile choice: the axis labels are right under the bars.
Palettes
Thirteen palettes in two groups. Match the group to what the colour encodes.
Categorical — distinct hues for unordered categories. Eight swatches each, cycling when a chart needs more.
palette | Swatches |
|---|---|
ember | #d6480a #e8843c #caa036 #7d8b5a #4f8a86 #9c5f74 #a23b2e #6b4f3a |
tableau | #4e79a7 #f28e2b #e15759 #76b7b2 #59a14f #edc948 #b07aa1 #ff9da7 |
slate | #3d5a80 #5e81ac #6c8a9c #5b8a72 #4f7d9c #7a6fa8 #9aa5b1 #566573 |
earthen | #a8553f #c9a05e #7f9070 #6b8a99 #9a6a7a #8c6b4f #b08968 #5c6b66 |
Sequential — a continuous ramp sampled evenly across however many values the chart has (a single value takes the midpoint). They encode magnitude or order.
palette | Character |
|---|---|
viridis | purple → teal → yellow; the all-rounder, reads on light and dark |
plasma | indigo → magenta → orange → yellow; high contrast |
inferno, magma | black → red/pink → pale yellow; dramatic, best on dark cards |
cividis | navy → grey → yellow; colour-blind safe |
turbo | rainbow with a dark floor; very high contrast |
warm, cool | purple → orange / purple → green; softer ramps |
spectral | red → yellow → blue; a diverging feel |
Which group for which chart. Sequential for heatmap, calendar, gauge, figure, waterfall, burndown, the time family, and a treemap sized by a measure. Categorical for everything that names discrete groups: bar, horizontalBar, lollipop, pareto, pie, donut, sunburst, funnel, groupedBar, stackedBar, radar, sankey, network, flow, scatter, bubble, boxplot, bullet, gantt, and the list tile. Any palette renders on any chart — the group is about whether the colours say something true.
Keep a report to one categorical palette and one sequential palette. A different palette per tile reads as noise. On the dark canvas themes, the brighter categorical sets (tableau, ember) and the high-contrast ramps (viridis, plasma, turbo) hold up best; earthen and slate suit the light themes.
The tile’s accent bar (the coloured strip along the top of the card) is the palette’s first colour, so palette choice also colours the chrome.
Defaults and self-healing
When data arrives, each tile checks that the columns it needs exist and quietly fills any that don’t:
| Chart needs | If missing, it picks |
|---|---|
dimension (most families) | the first text/boolean column with 2–20 distinct values, else the first non-empty column |
dimension (time, calendar, candlestick) | the first date column, else as above |
xMeasure, yMeasure, sizeMeasure | the first, second and third numeric non-key columns that vary |
stageFields (fewer than 2) | the first two columns |
startField, endField, labelField (gantt) | the first two date columns (or the same one twice) and a low-cardinality text column |
measure (boxplot, histogram, candlestick) | the first numeric non-key column |
A column whose name is id, key, guid, or ends in .id / .guid is treated as a surrogate key and never auto-picked as a measure or axis. You can still name one explicitly; you shouldn’t.
Self-healing exists so a freshly added tile shows something. It’s not a substitute for naming the columns you mean — an auto-picked dimension may be the least interesting column in the data.