KQ-1319 · TREE/MAP

Tree Map

A spending treemap you zoom into with a real relayout. Every node has a rectangle in every view — squarified fresh for the plot's shape inside the focus, and the root's layout seen through the camera outside it — so a zoom glides each tile on glide from where it was to where it goes: the chosen category opens out to fill the plot while its children re-squarify into the new shape, siblings fly off past the edges and fade on the exit ease, and grandchildren grow out of their parent's old box; breadcrumbs reverse it. Labels are decided from each tile's final size and fade as they come and go, and a readout names the tile under the pointer. The tiles are buttons with one roving tab stop: arrows move to the nearest tile in that direction, Enter zooms in or selects a leaf, Backspace and Escape zoom out, and focus lands on the tile you came out of.

KQ-1319 · TREE/MAP

Fernworks spend

$1,082,900 · Q3 2026

Fernworks spend · $1,082,900 · 100.0% of spend · 7 items

Install

One command — the source lands in your repo. Or copy it from the Code tab.

$ pnpm dlx shadcn@latest add @kinetiq/tree-map

Props

depth
number
default 2
How many levels the view draws below the node in focus, 1 to 3: 1 is flat tiles, 2 and 3 frame each tile with a header and nest its children inside.
labels
"full" | "name" | "off"
default "full"
Tile labels: name, amount and share where they fit (fewer lines where they do not, none on slivers); the name alone; or none.
palette
"category" | "size" | "change"
default "category"
How tiles are coloured: a hue per top-level category shaded by rank, one hue by share of the focus, or warm for spend that grew and green for spend that shrank.
data
TreeMapNode
default defaultTreeMapData
The tree: id, name, children, and on leaves a value and an optional previous value. A parent's amount is the sum of its children; color overrides the palette for a branch.
value / defaultValue
string
default the root's id
The id of the node the view is zoomed into. Controlled or uncontrolled; an id that is not a parent falls back to the root.
onValueChange
(id: string) => void
default —
Fires from the tile, crumb or key that zoomed, with the new focus id.
onSelect
(node: TreeMapNode, path: TreeMapNode[]) => void
default —
A leaf was pressed or chosen with Enter, with the path from the root down to it.
format
(value: number) => string
default —
How an amount reads in tiles, the readout, the table and spoken names. Defaults to whole currency in locale.
locale
string
default "en-US"
The locale for amounts and shares.
currency
string
default "USD"
The currency for amounts.
period
string
default "Q3 2026"
The period the amounts cover, shown beside the total.
compareLabel
string
default "last quarter"
What the change is measured against, in the readout and spoken names.
status
"ready" | "loading" | "error"
default "ready"
Whether the numbers have arrived: loading shows a skeleton of blocks, error a retry.
onRetry
() => void
default —
Try again was pressed after the numbers failed to load.
title
string
default "Spend"
The heading.
label
string
default —
The accessible name. Defaults to the title.
sound
boolean
default false
Play a swish on every zoom (higher in, lower out) and a click for a leaf, a crumb or a keyboard move.
disabled
boolean
default false
Shows the spend but refuses zooms and selections.
className
string
default —
Classes for the outer panel.