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.

QuestionAnswered by
Which chart, which comparison, which titleStyle guide: Plan and layout
What a status means, how colour behaves under filtersStyle guide: Numbers and colour
What an empty or partial tile says, what to testStyle guide: Data states and testing
Pages, pickers and filtersStyle guide: Navigation and interaction
Grid, tiles, header, filters, type sizes, status markersThis page
Building it in Power BIThis 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.

ColumnsWidthUse
3338KPI tile, four in a row beside the rail
4456Filter rail; KPI tile without a rail; narrow support visual
5 · 6574 · 692Support visual; half-width table
7 · 8810 · 928Main visual or table beside the rail
10 · 12 · 161164 · 1400 · 1872Wide line chart; everything beside the rail; full width

Two kinds of page

PageLayoutFilters
OverviewHeader · rail · KPI row (152) · main band (424) · support band (288) · footerThe rail filters a population: which programmes, which period
DetailHeader · subject bar (64) · KPI row (152) · main band (376) · support band · footer. Content starts at y 200No 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.

RoleWebPower BIWeight
KPI value48px36ptBold, tabular
Page title32px24ptBold
Subject title28px21ptBold
Visual title20px15ptSemibold (bold in Power BI)
Body, table cell, filter value15–16px12ptRegular
Label, subtitle, axis, legend, footer14px10.5ptRegular

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.

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.

PartSpec
Rail4 columns (456), full content height, one tile
HeadingMono caps, muted. A heading for the group, not a visual title
Dropdown1px --muted border (3:1 against white), 3px corners, label above in 600
Apply · ClearPrimary (coral) and outline buttons, 40px high, square corners. One primary per rail
NoteBottom 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.

Disbursed, 2026 to date€42.6m61% of budget · 74% at this point in 2025
Indicators on track64%Watch · target 70%
Budget used61%€42.6m of €69.8m
VariantSpec
PlainTeal top rule, 4px. Label 14px muted, value 48px bold, context 14px
StatusTop rule in the status colour, and a status marker in the context line. The rule never carries the status alone
Bar8px bar from 0 to the target, Teal on Platinum. Fixed ends: an automatic bar is always somewhere between empty and full and says nothing
Size3 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.

On trackWatchOff trackCompletedNo data
On trackWatchOff trackCompletedNo data
<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
StateTitleRest of the page
One itemThe name, 28px bold, and "4 of 12"Normal
Nothing picked"Pick a programme", mutedEmpty state, saying the same
More than one"Pick one programme · 3 selected"Empty state
ItemsPicker
Up to about 25Dropdown, everything visible
25 to 500Dropdown with search
More than 500No 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.

What changed in Q3Water moved from watch to on track after the Q2 supply delays cleared.
Partial periodQ4 has 30 of 92 days. Totals will rise.
Not refreshedThe finance data didn't load. Last good refresh 27 Oct, 06:00.

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.

StateMeansSays
No dataNothing was measured"No data", and why
No resultsThere is data, but the filters exclude it"No results for these filters", and how to get out
ErrorSomething brokeWhat failed, and the last good refresh. Cherry hatching
No accessThe reader may not see this dataEmpty 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.

ProgrammeStatusBudget, € mDisbursed
Cash for nutrition, SahelOff track6.438%
Mobile clinics, TigrayWatch4.855%
Legal aid for refugees, UgandaNo data2.2–
All 31 programmes69.861%
  • 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.

ui_kits/dashboard/index.htmlOpen the dashboard full screen
<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 setSo you
Positions and sizesType them in from the grid. Every row ends at 1896
Conditional formattingSet status colours per visual, from a measure that returns a hex code from the status table
Category colours by valueStore each category's colour in a column and apply it with conditional formatting, so filters don't reshuffle colours
Header, rail, notesBuild them from shapes and text boxes, group them, and copy the group to each page
Data bars, sparklines, target linesSet per visual. Data bars run from 0 to the target, never automatic
Alt textWrite one sentence per visual: what it shows and what it means

Building the parts

PartPower BI object
Page headerText boxes for title and period line (both from measures), page navigator for the tabs, a 1px line shape under them
Filter railRectangle 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 statusCard (new): callout value, label, reference label from a measure. Accent bar for the status colour
KPI tile with bar, sparkline or markerA 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 markerA measure that returns the sign (✓ ! ✕ – ◍), coloured with conditional formatting, and the word in the next column
Subject barShape, text boxes from measures, and one single-select slicer synced across all detail pages
Empty and error statesOne Card (new) on top of the visual with a text measure that is blank when there is data
FooterOne text box, filled from measures

Where Power BI differs

Decided once, for every report. Don't work around these per file.

In the systemIn Power BI
IBM Plex Sans and Plex MonoCalibri for everything, metadata included
Semibold (600)Bold. Power BI has regular and bold only
Square status marker with the sign insideThe 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 tileThe accent bar, wherever your release puts it
3px corners everywhere3px on visuals, shapes and slicers; table cells and data bars stay square
Legend in status orderLegend off, and a text box with the statuses in order
Coral focus ringPower BI's own ring. Don't rebuild it with a shape: it won't work with a keyboard
Dark modeLight 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.