TotalBase
Widgets

Comparison

Bar chart, Horizontal bar, Combo chart, Waterfall and Leaderboard.

In the admin: a Dashboard › a widget › Edit

Comparison widgets set values side by side: one bar or row per category. They never sort or cut rows themselves: the order and the LIMIT belong in the query.

Orders by branch as a bar chart, parts used by category as horizontal bars, and the top customers as a leaderboard.
Orders by branch as a bar chart, parts used by category as horizontal bars, and the top customers as a leaderboard.

Bar chart

Vertical bars: one group per category, one bar per series.

RoleTakesUnset
Categorythe axis labels; a date makes a time axisthe first column that isn't a number
Valuesone series per column, in orderevery number column
Serieslong format: one series per value of this column, with one value columnnone: choose it by hand

Open and overdue orders per branch, two series as columns (wide format):

SELECT b.name AS branch,
       count(wo.id) FILTER (WHERE wo.status NOT IN ('COMPLETED', 'CANCELLED')) AS open,
       count(wo.id) FILTER (WHERE wo.status NOT IN ('COMPLETED', 'CANCELLED')
                            AND wo.due_at < now()) AS overdue
FROM branches b
LEFT JOIN work_orders wo ON wo.branch = b.id
GROUP BY b.name
ORDER BY b.name

The same data can come as rows (long format): SELECT b.name AS branch, wo.type, count(*) AS orders ... GROUP BY 1, 2 with Series set to type draws a series per order type. A value missing for a category is left empty. Series names and colors come from the column's presentation, such as the labels and colors of type's CHECK list.

Setting
Stackedstacks the series instead of placing them side by side
Format, Compact number, Colorhow values read; the accent color of a single series
Color columna column whose palette name colors each bar; unset, _color. Only with a single value column
Show legendthe series' names. A single series hides it
Seriesper series: its name, color, type (bar, line or area), axis (left or right) and format. Types mix in one chart, and a series on the right axis reads on its own scale
Axeseach axis' title; the value axes' minimum, maximum, logarithmic scale and format. Unset minimum: 0
Reference lineslines at a number, a statistic of a series (average, minimum, maximum, median), a column or a variable, and bands between two values
On click, Zooma click on a bar; a zoom slider under the chart, the wheel or a pinch

BAR

Vertical bars - one group per category, one bar per series.

Size: 6 × 4 of the 12-column grid, at least 3 × 3 · Also: series, thresholds, events, zoom, export

DataCodeTakesRequiredUnset
Categorycategorycategory, timeyesfirstThe axis labels - a date makes a time axis. Defaults to the first column that isn't a number.
ValuesvaluesnumberyesallOne series per column, in this order. Defaults to every number column.
SeriesseriescategorynoneLong format: one series per value of this column (month, seller, total) - with one value column. Optional.
PropertyCodeSectionValues
Stackedstackedappearancedefault falseStacks the series instead of placing them side by side.
FormatdisplayFormatformatHow its numbers read - a displayFormat pattern: "$ #,##0", "#,##0.00", "0.0 %" (% never multiplies: 85 reads 85.0 %), "0.0 h", "CURRENCY:ARS". Unset: the value column's own (its presentation), else the locale's.
Compact numbercompactformatAbbreviates large numbers - 11.6M, 2.4K - keeping the format's text and decimals ("$ #,##0" + compact: $ 1.3M). Unset: on, unless a format applies (its own or its column's).
ColorcolorappearanceA palette hue for its marks - unset, the theme's primary.
Color columncolorColumnappearanceA column whose value - a palette name: red, emerald, amber... - colors its row's mark. Unset, a column named _color, if the query returns one.
Show legendshowLegendappearancedefault trueThe series' (or slices') names, beside the chart.
SeriesseriesseriesPer value column - or, in long format, per value of the Series column: {label, color (a palette hue), type: bar|line|area, axis: left|right, displayFormat}. Unset: the column's title and format; in long format, the Series column's value labels and colors (its presentation).
Axesaxesaxes{category: {title}, value: {title, min, max, log, displayFormat}, value2: {...}} - value2 is the right axis, used by series with axis: right. Unset min: 0 for bars and areas, fitted to the data for lines.
Reference linesreferencesthresholdsLines and bands on the value axis: {type: "line", value: a number | average | min | max | median | {column} | {variable}, label, color, series?} or {type: "band", from, to, label, color}. Labels read in the axis' format.
On clickclickeventsWhat a click on a mark does: {action: "FILTER", variable, value} sets a variable of this dashboard; {action: "DATAVIEW", dataview, filter} opens a DataView filtered (the where grammar); {action: "DASHBOARD", dashboard, variables, tab}; {action: "RECORD", dataview, pk}; {action: "URL", url, newTab, inEmbeds}. Values are formulas over (_ columns too) and ; targets by id. hint: the tooltip's last line.
ZoomzoomzoomExportdefault falseA bar under the chart, and the wheel or a pinch, to zoom into a range.
SELECT * FROM (VALUES ('North', 120, 80), ('South', 95, 110), ('East', 140, 60), ('West', 70, 90)) AS t(region, sales, returns)

Horizontal bar

The same roles and settings, with bars across: for long labels. Categories read top to bottom in the query's order. Parts used on work orders by category:

SELECT p.category, sum(-m.quantity) AS used
FROM stock_movements m
JOIN parts p ON p.id = m.part
WHERE m.reason = 'WORK_ORDER'
  AND ($VAR.period.from IS NULL OR m.created_at >= $VAR.period.from)
  AND ($VAR.period.to IS NULL OR m.created_at < $VAR.period.to)
GROUP BY p.category
ORDER BY used DESC

BAR_HORIZONTAL

Horizontal bars - for long labels; order the query yourself.

Size: 6 × 4 of the 12-column grid, at least 3 × 3 · Also: series, thresholds, events, zoom, export

DataCodeTakesRequiredUnset
Categorycategorycategory, timeyesfirstThe axis labels - a date makes a time axis. Defaults to the first column that isn't a number.
ValuesvaluesnumberyesallOne series per column, in this order. Defaults to every number column.
SeriesseriescategorynoneLong format: one series per value of this column (month, seller, total) - with one value column. Optional.
PropertyCodeSectionValues
Stackedstackedappearancedefault falseStacks the series instead of placing them side by side.
FormatdisplayFormatformatHow its numbers read - a displayFormat pattern: "$ #,##0", "#,##0.00", "0.0 %" (% never multiplies: 85 reads 85.0 %), "0.0 h", "CURRENCY:ARS". Unset: the value column's own (its presentation), else the locale's.
Compact numbercompactformatAbbreviates large numbers - 11.6M, 2.4K - keeping the format's text and decimals ("$ #,##0" + compact: $ 1.3M). Unset: on, unless a format applies (its own or its column's).
ColorcolorappearanceA palette hue for its marks - unset, the theme's primary.
Color columncolorColumnappearanceA column whose value - a palette name: red, emerald, amber... - colors its row's mark. Unset, a column named _color, if the query returns one.
Show legendshowLegendappearancedefault trueThe series' (or slices') names, beside the chart.
SeriesseriesseriesPer value column - or, in long format, per value of the Series column: {label, color (a palette hue), type: bar|line|area, axis: left|right, displayFormat}. Unset: the column's title and format; in long format, the Series column's value labels and colors (its presentation).
Axesaxesaxes{category: {title}, value: {title, min, max, log, displayFormat}, value2: {...}} - value2 is the right axis, used by series with axis: right. Unset min: 0 for bars and areas, fitted to the data for lines.
Reference linesreferencesthresholdsLines and bands on the value axis: {type: "line", value: a number | average | min | max | median | {column} | {variable}, label, color, series?} or {type: "band", from, to, label, color}. Labels read in the axis' format.
On clickclickeventsWhat a click on a mark does: {action: "FILTER", variable, value} sets a variable of this dashboard; {action: "DATAVIEW", dataview, filter} opens a DataView filtered (the where grammar); {action: "DASHBOARD", dashboard, variables, tab}; {action: "RECORD", dataview, pk}; {action: "URL", url, newTab, inEmbeds}. Values are formulas over (_ columns too) and ; targets by id. hint: the tooltip's last line.
ZoomzoomzoomExportdefault falseA bar under the chart, and the wheel or a pinch, to zoom into a range.
SELECT * FROM (VALUES ('Laptops', 320), ('Phones', 280), ('Tablets', 150), ('Monitors', 90)) AS t(product, stock) ORDER BY stock DESC

Combo chart

Bars and lines on two axes: the first value column as bars on the left axis, the rest as lines on the right, each axis in its own format. It needs at least two value columns and no Series column; for a series per value of a column, use a Bar chart. Series changes which is which.

Orders per month as bars, hours per order as a line:

SELECT date_trunc('month', wo.reported_at)::date AS month,
       count(DISTINCT wo.id) AS orders,
       round(sum(te.minutes) / 60.0 / nullif(count(DISTINCT wo.id), 0), 1) AS hours_per_order
FROM work_orders wo
LEFT JOIN time_entries te ON te.work_order = wo.id
WHERE wo.reported_at >= date_trunc('month', current_date) - interval '11 months'
GROUP BY 1
ORDER BY 1

A Tooltip role adds more columns to each mark's tooltip.

COMBO

Bars and lines on two axes - the first value column as bars on the left, the rest as lines on the right.

Size: 6 × 4 of the 12-column grid, at least 3 × 3 · Also: series, thresholds, events, zoom, export

DataCodeTakesRequiredUnset
Categorycategorycategory, timeyesfirstThe axis labels - a date makes a time axis. Defaults to the first column that isn't a number.
ValuesvaluesnumberyesallTwo or more columns: the first as bars (left axis), the rest as lines (right axis) - series changes that.
Tooltiptooltipcategory, number, timenoneMore columns shown in a mark's tooltip, with their titles and formats. Optional.
PropertyCodeSectionValues
Stackedstackedappearancedefault falseStacks the series instead of placing them side by side.
FormatdisplayFormatformatHow its numbers read - a displayFormat pattern: "$ #,##0", "#,##0.00", "0.0 %" (% never multiplies: 85 reads 85.0 %), "0.0 h", "CURRENCY:ARS". Unset: the value column's own (its presentation), else the locale's.
Compact numbercompactformatAbbreviates large numbers - 11.6M, 2.4K - keeping the format's text and decimals ("$ #,##0" + compact: $ 1.3M). Unset: on, unless a format applies (its own or its column's).
ColorcolorappearanceA palette hue for its marks - unset, the theme's primary.
Color columncolorColumnappearanceA column whose value - a palette name: red, emerald, amber... - colors its row's mark. Unset, a column named _color, if the query returns one.
Show legendshowLegendappearancedefault trueThe series' (or slices') names, beside the chart.
SeriesseriesseriesPer value column - or, in long format, per value of the Series column: {label, color (a palette hue), type: bar|line|area, axis: left|right, displayFormat}. Unset: the column's title and format; in long format, the Series column's value labels and colors (its presentation).
Axesaxesaxes{category: {title}, value: {title, min, max, log, displayFormat}, value2: {...}} - value2 is the right axis, used by series with axis: right. Unset min: 0 for bars and areas, fitted to the data for lines.
Reference linesreferencesthresholdsLines and bands on the value axis: {type: "line", value: a number | average | min | max | median | {column} | {variable}, label, color, series?} or {type: "band", from, to, label, color}. Labels read in the axis' format.
On clickclickeventsWhat a click on a mark does: {action: "FILTER", variable, value} sets a variable of this dashboard; {action: "DATAVIEW", dataview, filter} opens a DataView filtered (the where grammar); {action: "DASHBOARD", dashboard, variables, tab}; {action: "RECORD", dataview, pk}; {action: "URL", url, newTab, inEmbeds}. Values are formulas over (_ columns too) and ; targets by id. hint: the tooltip's last line.
ZoomzoomzoomExportdefault falseA bar under the chart, and the wheel or a pinch, to zoom into a range.
SELECT * FROM (VALUES ('Jan', 120, 3500.5), ('Feb', 140, 3720), ('Mar', 95, 4010.25)) AS t(month, visits, avg_ticket)

Waterfall

How a total is built: each row a change up or down, with its sign.

RoleTakesUnset
Categoryeach step's namethe first column that isn't a number
Valuethe change, with its signthe first number column
Totalchosen by hand: a true/false column. A true row draws the running total so far from 0none

The value of Acme's stock movements this month, by reason:

SELECT m.reason, sum(m.quantity * p.unit_cost) AS value
FROM stock_movements m
JOIN parts p ON p.id = m.part
WHERE m.created_at >= date_trunc('month', now())
GROUP BY m.reason
ORDER BY CASE m.reason WHEN 'PURCHASE' THEN 1 WHEN 'TRANSFER' THEN 2
                       WHEN 'ADJUSTMENT' THEN 3 ELSE 4 END
Setting
Final total, Final total's namea last bar with the running total, on by default; its name, unset Total
Increase color, Decrease color, Total colorpalette hues; green and red by default

WATERFALL

How a total is built - each row a change up or down; a total row the running sum so far.

Size: 6 × 4 of the 12-column grid, at least 3 × 3 · Also: thresholds, events, export

DataCodeTakesRequiredUnset
Categorycategorycategory, timeyesfirstThe axis labels - a date makes a time axis. Defaults to the first column that isn't a number.
ValuevaluenumberyesfirstEach row's change, with its sign. Defaults to the first number column.
TotaltotalnoneChosen by hand: a true/false column - a true row draws the running total so far from 0 (its value is ignored).
Tooltiptooltipcategory, number, timenoneMore columns shown in a mark's tooltip, with their titles and formats. Optional.
PropertyCodeSectionValues
FormatdisplayFormatformatHow its numbers read - a displayFormat pattern: "$ #,##0", "#,##0.00", "0.0 %" (% never multiplies: 85 reads 85.0 %), "0.0 h", "CURRENCY:ARS". Unset: the value column's own (its presentation), else the locale's.
Compact numbercompactformatAbbreviates large numbers - 11.6M, 2.4K - keeping the format's text and decimals ("$ #,##0" + compact: $ 1.3M). Unset: on, unless a format applies (its own or its column's).
Final totalfinalTotalappearancedefault trueA last bar with the running total.
Final total's namefinalTotalLabelappearanceUnset: "Total" in the viewer's language.
Increase colorincreaseColorappearancedefault greenA palette hue for a change up.
Decrease colordecreaseColorappearancedefault redA palette hue for a change down.
Total colortotalColorappearanceA palette hue for a total - unset, the theme's primary.
Axesaxesaxes{category: {title}, value: {title, min, max, log, displayFormat}, value2: {...}} - value2 is the right axis, used by series with axis: right. Unset min: 0 for bars and areas, fitted to the data for lines.
Reference linesreferencesthresholdsLines and bands on the value axis: {type: "line", value: a number | average | min | max | median | {column} | {variable}, label, color, series?} or {type: "band", from, to, label, color}. Labels read in the axis' format.
On clickclickeventsWhat a click on a mark does: {action: "FILTER", variable, value} sets a variable of this dashboard; {action: "DATAVIEW", dataview, filter} opens a DataView filtered (the where grammar); {action: "DASHBOARD", dashboard, variables, tab}; {action: "RECORD", dataview, pk}; {action: "URL", url, newTab, inEmbeds}. Values are formulas over (_ columns too) and ; targets by id. hint: the tooltip's last line.
SELECT * FROM (VALUES (1, 'Sales', 1000, false), (2, 'Discounts', -150, false), (3, 'Net', NULL, true), (4, 'Paid', -600, false)) AS t(n, step, amount, is_total) ORDER BY n

Leaderboard

A ranked list with a bar per row, sized against the largest value. Rows show in the query's order: order and LIMIT it yourself.

RoleTakesUnset
Categoryeach row's namethe first column that isn't a number
Valuethe ranked valuethe first number column
Imagea file column, shown as a thumbnail beside each rowthe first file column

The top ten customers by billing in the chosen period:

SELECT c.name AS customer, sum(ii.quantity * ii.unit_price) AS billed
FROM invoices i
JOIN customers c ON c.id = i.customer
JOIN invoice_items ii ON ii.invoice = i.id
WHERE i.status <> 'DRAFT'
  AND ($VAR.period.from IS NULL OR i.issued_on >= $VAR.period.from)
  AND ($VAR.period.to IS NULL OR i.issued_on < $VAR.period.to)
GROUP BY c.name
ORDER BY billed DESC
LIMIT 10

Its settings: Format, Compact number, Color, Color column and On click (a click on a row).

LEADERBOARD

A ranked list with bars - order and LIMIT the query yourself.

Size: 4 × 4 of the 12-column grid, at least 3 × 3 · Also: events, export

DataCodeTakesRequiredUnset
Categorycategorycategory, timeyesfirstEach row's name. Defaults to the first column that isn't a number.
ValuevaluenumberyesfirstThe ranked value. Defaults to the first number column.
ImageimagefilefirstA file column (an image) shown as a thumbnail beside each row. Defaults to the first file column.
PropertyCodeSectionValues
FormatdisplayFormatformatHow its numbers read - a displayFormat pattern: "$ #,##0", "#,##0.00", "0.0 %" (% never multiplies: 85 reads 85.0 %), "0.0 h", "CURRENCY:ARS". Unset: the value column's own (its presentation), else the locale's.
Compact numbercompactformatAbbreviates large numbers - 11.6M, 2.4K - keeping the format's text and decimals ("$ #,##0" + compact: $ 1.3M). Unset: on, unless a format applies (its own or its column's).
ColorcolorappearanceA palette hue for its marks - unset, the theme's primary.
Color columncolorColumnappearanceA column whose value - a palette name: red, emerald, amber... - colors its row's mark. Unset, a column named _color, if the query returns one.
On clickclickeventsWhat a click on a mark does: {action: "FILTER", variable, value} sets a variable of this dashboard; {action: "DATAVIEW", dataview, filter} opens a DataView filtered (the where grammar); {action: "DASHBOARD", dashboard, variables, tab}; {action: "RECORD", dataview, pk}; {action: "URL", url, newTab, inEmbeds}. Values are formulas over (_ columns too) and ; targets by id. hint: the tooltip's last line.
SELECT * FROM (VALUES ('Ana', 48), ('Luis', 41), ('Marta', 35), ('Pedro', 22)) AS t(agent, resolved) ORDER BY resolved DESC LIMIT 10

Next steps