Selected work — 02 / Custom visuals
Charts I had to write.
Power BI ships with a fixed set of charts. When the one I needed wasn't among them, I wrote it — six so far: a body-map heatmap, a bar visual, a gauge, a stacked-change column and KPI cards, all hand-written in TypeScript. Rebuilt below, live, so you can play with them.
Every figure inside these widgets is sample data — invented to show how each visual behaves, not real numbers.
LIVEthe same heatmap that's further down — warmer means more injuries.
In short
A custom visual is a small program Power BI runs inside the report: it hands your code the data and the size of the box, and your code draws the pixels.
It's code, not a template
A TypeScript class that implements one interface. No drag-and-drop — every pixel is drawn on purpose.
01 · IVisual · TypeScriptPower BI hands it data
You declare the fields you accept; the host shapes the data to match and passes it in on every change.
02 · capabilities · dataViewYou draw the pixels
Given the data and the viewport, the code lays out SVG — bars, paths, labels, a whole stats panel.
03 · SVG · your layoutIt ships as one file
Packaged into a single .pbiviz — code, styles and icon zipped together — and imported into any report.
How it works
Power BI talks. Your code draws.
Its whole life is one loop: built once, then update() fires on every data, size or setting change — read, redraw. Run the loop
constructor
Host builds the visual, hands over the DOM element. You set up your <svg>.
data / size / setting changes
Someone filters, resizes, or tweaks a format control.
update(options)
The host calls your update() with fresh options.
options.dataViews[0]
You pull the reshaped data and the current settings out.
render() → SVG
Clear the canvas, lay out the picture at the new size.
Visual one — the injury body map
Injuries, mapped onto a body.
Two fields in — a body region and an injury count — and each region colours on a five-band scale while the panel rolls them into groups and spotlights the worst. Click a region, or drag the caseload
Injuries by Body Group
Bands: 1–5 · 6–15 · 16–40 · 41+ — all format-pane colours. This is the prototype; its shipped twin bodyInjuryHeatmap swaps the five bands for a smooth min→max gradient, tells left from right, and wires up Power BI selection, cross-highlight and tooltips.
The data behind it
Two fields in. A picture out.
It declares what it accepts — one grouping, one measure — and Power BI reshapes the report into the categorical dataView it receives. Toggle rows — watch the dataView
dataViewwhat update() receives — categorical
Visual two — the bar visual
A bar chart that does what the built-in one won't.
For the details the built-in bar chart skips — a real grand-total header, its own fonts, alignment and a border you can shape. Each is a control in the format pane. Change the pane — the chart follows
Where the pane comes from
Declare a control. Power BI draws the pane.
You never build the pane by hand — you declare each property's type, and the host renders the control. Pick a type
A boolean becomes a switch in the pane, and arrives in your settings model as true / false.
Visual three — the semi-circle gauge
On target, at a glance.
One value fills toward a max, past two targets, into one of three zones — behind, on track, ahead — and the arc takes that zone's colour. Drag the value
Targets at 40 and 75 · min/max, zones and markers are all format-pane controls.
Also on the shelf
Same instinct, a few more times.
Two more that earn their place — a stacked column that annotates its change between periods, and a strip of KPI cards. Both live. Poke them
Stacked column + change
v3.5.8 · legend · drilldown · change deltasMultiCard
v1.3.2 · KPI cards · row or columnIteration
One good version is really six.
Each release added exactly one thing a report asked for — and the old package was never overwritten, only superseded. Walk the versions
Set the Values role to accept a measure or a grouping, so a report author can pick “Don't summarize” and show raw category values instead of a forced sum.
By the numbers
The family, counted.
Both drawn in raw SVG on the powerbi-visuals API — no D3 chart helpers, no third-party charting. Every colour, font and border is a format-pane control.