Treemap
treemapTiles a flat dataset into a rectangle with area proportional to value, so the biggest contributors read at a glance.
Usage
Basic usage
A flat dataset is tiled by value so the biggest items read at a glance. Cell colors default to one chart token per index.
<Treemap
data={[
{ name: "Hangzhou Hubin", value: 3820 },
{ name: "Shanghai West Nanjing Rd", value: 3140 },
]}
/>Display value
showValue adds a value line under the name; a cell that cannot fit both keeps only the name, and one that fits neither draws no text at all.
<Treemap data={data} showValue />Click to drill down
onItemClick reports the clicked cell; the drill-down itself (navigating to a list, opening a drawer) stays in application code.
<Treemap
data={data}
onItemClick={({ datum }) => router.push(`/members?store=${datum.name}`)}
/>Custom value format
valueFormat applies to both the in-cell text and the tooltip, so the two cannot drift apart.
<Treemap data={data} showValue valueFormat={thousands} />When to use
Use a treemap when a set of comparable items should be read as a distribution: 50 stores by member count, channels by revenue, error types by occurrence. The reader wants to see who dominates, not to read exact numbers.
When adjacent items must be compared precisely, or the list is meant to be read in order, use BarChart with horizontal, because area differences between neighboring cells cannot be judged accurately. For three to five items where "these add up to 100%" is the message, use PieChart.
Import
import { Treemap } from "@hulianui/ui"Props
| Name | Type | Default | Description |
|---|---|---|---|
| data* | TreemapDatum[] | - | Flat, single-level data { name, value, color? }; area is allocated by each value as a share of the total. |
| height | number | 280 | Total component height (SSR-safe: width comes from ResponsiveContainer, height must be explicit). |
| showValue | boolean | false | Whether to add a value line under the name inside each cell. |
| valueFormat | (value: number) => string | String | Value formatting, applied to both the in-cell text and the tooltip so the two cannot drift apart. |
| onItemClick | (info: { datum, index }) => void | - | Fires when a cell is clicked (drill-down: click a store to open its member list). Only cells fire; clicks on empty space do not. |
| className | string | - | Custom class name, commonly used for width. |
TreemapDatum
| Name | Type | Default | Description |
|---|---|---|---|
| name* | string | - | Label drawn in the cell and used as the tooltip title. |
| value* | number | - | The value that determines the area. |
| color | string | chart-N by index | Cell color; accepts a semantic tone name ("success") or any CSS color. |
Example
<Treemap
data={[
{ name: "Hangzhou Hubin", value: 3820 },
{ name: "Shanghai West Nanjing Rd", value: 3140 },
{ name: "Suzhou Guanqian", value: 2470 },
]}
showValue
valueFormat={(v) => `${(v / 1000).toFixed(1)}k`}
onItemClick={({ datum }) => router.push(`/members?store=${datum.name}`)}
/>Pitfalls
- Labels disappear on long-tail cells by design, not by accident. Cell size follows the data, so the small share of items is inevitably too small to fit any text. Drawing it anyway produces a mat of overlapping fragments: SVG
textis not clipped by itsrect, so overflow paints straight over neighboring cells. The rule lives in the pure functiontreemapLabelFitand asks whether width and height still fit after padding. To let readers identify long-tail items, rely on the tooltip or pair the chart with a list; do not count on in-cell text. - No nested drill-down. A single level is the whole feature:
datadoes not acceptchildren. Multi-level treemap interaction (descend, breadcrumb back) is a different component's worth of behavior, and in practice "drill down" means "navigate to another page", whichonItemClickhands to application code. - In-cell text is fixed white rather than
foreground: cells are filled withchart-Nat varying lightness, so following the theme foreground would render light gray on a light cell. This matches how pie slice labels are handled. - Beyond roughly 60 items a treemap degrades into confetti. That is the point to change the aggregation (top 20 plus "Other"), not to keep adding cells.
Related
Playground
<Treemap data={data} height={280} />