Dashboards
Dashboards
The interface around the charts: canvas, grid, status colours and the parts every dashboard page is made of. The same rules ship as a stylesheet for the web and a theme for Power BI.
Where this fits
A dashboard needs two kinds of rules. The style guide decides how the data is shown: chart choice, titles on live data, colour that survives filtering, data states. This page decides everything around it, and how to build it. When the two disagree about a chart, the style guide wins.
| Question | Answered by |
|---|---|
| Which chart, which comparison, which title | Style guide: Plan and layout |
| What a status means, how colour behaves under filters | Style guide: Numbers and colour |
| What an empty or partial tile says, what to test | Style guide: Data states and testing |
| Pages, pickers and filters | Style guide: Navigation and interaction |
| Grid, tiles, header, filters, type sizes, status markers | This page |
| Building it in Power BI | This page, Power BI, and the theme file |
Building for a client? Use their brand for the interface and keep the style guide for the charts. The grid and the component list on this page still work; swap the colours and the typeface.
Canvas and grid
One canvas size, one grid. 1920 × 1080, sixteen columns of 102px, a 24px margin and a 16px gutter. Every visual starts on a column and spans whole columns. Type coordinates in; never drag.
| Columns | Width | Use |
|---|---|---|
| 3 | 338 | KPI tile, four in a row beside the rail |
| 4 | 456 | Filter rail; KPI tile without a rail; narrow support visual |
| 5 · 6 | 574 · 692 | Support visual; half-width table |
| 7 · 8 | 810 · 928 | Main visual or table beside the rail |
| 10 · 12 · 16 | 1164 · 1400 · 1872 | Wide line chart; everything beside the rail; full width |
Two kinds of page
| Page | Layout | Filters |
|---|---|---|
| Overview | Header · rail · KPI row (152) · main band (424) · support band (288) · footer | The rail filters a population: which programmes, which period |
| Detail | Header · subject bar (64) · KPI row (152) · main band (376) · support band · footer. Content starts at y 200 | No rail. The subject bar picks one item, and the pick stays when you change page |
Eight visuals per page is the maximum. More than eight means there is no main question.
Status colours
Five statuses, each with one colour, one sign and one word. A status is always a square marker with the sign inside and the word beside it, never a colour on its own.
- The sign is drawn in ink on the colour (white on Baltic and Cherry, black on Jasmine, Sky and Steel), so the light colours keep their contrast.
- Cell tints (
--status-*-bg) are for table cells and badges. Use the tint or the marker, not both. - The status colours are also data colours. A chart encodes status or categories, never both. On a page with status, draw category charts in colours that aren't status colours: Teal and its ramp, Coral, Violet or Blush, with Steel for context.
- Completed is Sky rather than a second blue: it stays distinct from On track for every common type of colour blindness (worst case ΔE 29).
Type
IBM Plex Sans on the web, Calibri in Power BI. Power BI only renders fonts installed on the viewer's machine, and Calibri has the lining, tabular figures the style guide asks for. No Newsreader on a dashboard: one typeface, hierarchy by size and weight.
| Role | Web | Power BI | Weight |
|---|---|---|---|
| KPI value | 48px | 36pt | Bold, tabular |
| Page title | 32px | 24pt | Bold |
| Subject title | 28px | 21pt | Bold |
| Visual title | 20px | 15pt | Semibold (bold in Power BI) |
| Body, table cell, filter value | 15–16px | 12pt | Regular |
| Label, subtitle, axis, legend, footer | 14px | 10.5pt | Regular |
Nothing smaller than 14px, or 10.5pt, including the source line. On the web, metadata (period, refresh time, source, filter heading) is Plex Mono, as everywhere else in the system.
Page header
Says where you are: the dashboard title, the pages, and the period and refresh time. It sits on the canvas, above a hairline. No coloured band.
Programme monitor
| Part | Spec |
|---|---|
| Band | y 0, height 96, full width; 1px --line under it |
| Title | 32px bold; the kicker above it is optional |
| Period line | Right-aligned. Period, selection and refresh time, all from the data |
| Page tabs | The Chip underline tab: active page in heading colour, 600, 3px coral underline |
Filter rail
All filters in one place, on the left of an overview page. At most three filters, Apply and Clear, and the note that says what changed.
| Part | Spec |
|---|---|
| Rail | 4 columns (456), full content height, one tile |
| Heading | Mono caps, muted. A heading for the group, not a visual title |
| Dropdown | 1px --muted border (3:1 against white), 3px corners, label above in 600 |
| Apply · Clear | Primary (coral) and outline buttons, 40px high, square corners. One primary per rail |
| Note | Bottom of the rail, above the buttons. See Note |
One or two filters and no note? Put them in the header instead, as dropdowns beside the period line.
KPI tile
The BigNumber card on a canvas: label, value and one line of context. Four in a row, all from the same variant, so their baselines line up.
| Variant | Spec |
|---|---|
| Plain | Teal top rule, 4px. Label 14px muted, value 48px bold, context 14px |
| Status | Top rule in the status colour, and a status marker in the context line. The rule never carries the status alone |
| Bar | 8px bar from 0 to the target, Teal on Platinum. Fixed ends: an automatic bar is always somewhere between empty and full and says nothing |
| Size | 3 columns × 152 beside the rail, 4 columns × 152 without |
Every value carries a comparison: a target, the previous period, the baseline or the rest of the portfolio. Coral stays the interface accent; it is never a status.
Status marker
A square with the sign, then the word. Inline in text and tiles, or as a cell with the tint behind it.
<span class="status status--watch">Watch</span> <span class="status status--cell status--off-track">Off track</span>
Subject bar
On every detail page, never on an overview: which item this page is about, its status, where it sits in the list, and the picker for another one.
Mobile clinics, Tigray
Watch4 of 12| State | Title | Rest of the page |
|---|---|---|
| One item | The name, 28px bold, and "4 of 12" | Normal |
| Nothing picked | "Pick a programme", muted | Empty state, saying the same |
| More than one | "Pick one programme · 3 selected" | Empty state |
| Items | Picker |
|---|---|
| Up to about 25 | Dropdown, everything visible |
| 25 to 500 | Dropdown with search |
| More than 500 | No dropdown. Name and position only; readers arrive by clicking through from a filtered table |
Note
"What changed", an explanation, or a warning. The Callout pattern: a rule above and a mono key with a coloured square. No left border, no box.
Notes that depend on the data come from the data: a table of notes by item and period, picked by the same filters as the page. A typed note is true until the next refresh.
Empty and error states
Three kinds of empty, three messages. The tile keeps its title; the message replaces the chart. Never the tool's default message.
Indicator results
No data
This programme reports twice a year. Next report due 15 Jan.
Indicator results
No results for these filters
Nothing in East Africa for Q3. Clear the region filter to see all regions.
Indicator results
The figures didn't refresh
Last good refresh 27 Oct 2026, 06:00.
| State | Means | Says |
|---|---|---|
| No data | Nothing was measured | "No data", and why |
| No results | There is data, but the filters exclude it | "No results for these filters", and how to get out |
| Error | Something broke | What failed, and the last good refresh. Cherry hatching |
| No access | The reader may not see this data | Empty with an explanation. Never an error, and never everything |
A refresh warning goes in one place: one tile, or one line under the header. The same message twice on a screen reads as two problems.
Table
Ruled, not filled. A bold header over a dark rule, hairlines between rows, a 2px rule over the total. A table is a full visualisation: use one whenever readers need to check, copy or forward the numbers.
| Programme | Status | Budget, € m | Disbursed |
|---|---|---|---|
| Cash for nutrition, Sahel | Off track | 6.4 | 38% |
| Mobile clinics, Tigray | Watch | 4.8 | 55% |
| Legal aid for refugees, Uganda | No data | 2.2 | – |
| All 31 programmes | 69.8 | 61% | |
- Numbers right-aligned, tabular figures; text left-aligned.
- Sort by value, not alphabet, unless the rows have their own order: periods, levels, statuses.
- Fixed column widths. Automatic widths jump on every filter change.
- A missing value is a dash, not a zero.
Example page
An overview page built only from the parts above: rail, KPI row, main and support bands, table, footer.
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="dashboards/dashboard.css">
<div class="dash">
<header class="dash-head">…</header>
<div class="dash-grid">
<aside class="tile rail span-4 rows-all">…</aside>
<section class="tile kpi span-3">…</section>
<section class="tile span-7">…</section>
</div>
<footer class="dash-foot">…</footer>
</div>
Power BI theme
ren-data.theme.json sets the data colours in order, Calibri at every text size, white tiles with a 1px hairline and no shadow, 3px corners, 16px padding, ruled tables, coral buttons, underline page tabs and the canvas colour. Apply it first, before any visual exists: a theme doesn't override formatting a visual already has.
| The theme can't set | So you |
|---|---|
| Positions and sizes | Type them in from the grid. Every row ends at 1896 |
| Conditional formatting | Set status colours per visual, from a measure that returns a hex code from the status table |
| Category colours by value | Store each category's colour in a column and apply it with conditional formatting, so filters don't reshuffle colours |
| Header, rail, notes | Build them from shapes and text boxes, group them, and copy the group to each page |
| Data bars, sparklines, target lines | Set per visual. Data bars run from 0 to the target, never automatic |
| Alt text | Write one sentence per visual: what it shows and what it means |
Building the parts
| Part | Power BI object |
|---|---|
| Page header | Text boxes for title and period line (both from measures), page navigator for the tabs, a 1px line shape under them |
| Filter rail | Rectangle shape as the tile, at most three slicers (dropdown or vertical list), an Apply all slicers button and a Clear button on a bookmark |
| KPI tile, plain or status | Card (new): callout value, label, reference label from a measure. Accent bar for the status colour |
| KPI tile with bar, sparkline or marker | A one-row table with every bit of chrome turned off. Card (new) can't draw these; don't mix the two in one row |
| Status marker | A measure that returns the sign (✓ ! ✕ – ◍), coloured with conditional formatting, and the word in the next column |
| Subject bar | Shape, text boxes from measures, and one single-select slicer synced across all detail pages |
| Empty and error states | One Card (new) on top of the visual with a text measure that is blank when there is data |
| Footer | One text box, filled from measures |
Where Power BI differs
Decided once, for every report. Don't work around these per file.
| In the system | In Power BI |
|---|---|
| IBM Plex Sans and Plex Mono | Calibri for everything, metadata included |
| Semibold (600) | Bold. Power BI has regular and bold only |
| Square status marker with the sign inside | The sign alone in the status colour. Watch, Completed and No data are too light for text, so they get an ink sign on the tinted cell |
| Teal top rule on a KPI tile | The accent bar, wherever your release puts it |
| 3px corners everywhere | 3px on visuals, shapes and slicers; table cells and data bars stay square |
| Legend in status order | Legend off, and a text box with the statuses in order |
| Coral focus ring | Power BI's own ring. Don't rebuild it with a shape: it won't work with a keyboard |
| Dark mode | Light only |
Before you publish
- Every visual starts on a column and every row ends at 1896.
- Four KPI tiles of one variant, each with a comparison.
- Every status has a colour, a sign and a word.
- Header period line, footer and notes come from the data. Nothing typed that will go out of date.
- Test the opening view, the deepest single selection, a selection with no results, the first and the latest (partial) period, a reader without access, and a screenshot without context.
- Alt text on every visual. Fixed column widths on every table.
- No colour typed in by hand that belongs in the theme. If you need one, the theme is missing a case.