Treemap Chart
- Stable
- WCAG 2.2 evidence
- RTL
A treemap: the area of every tile is its share of the whole, laid out with the squarified
algorithm from hierarchical data. Data driven: data in, SVG out; the same props render the static SVG on the server and the plot is
laid out for the width of its container. Accessibility: the figure is named by title and described by summary; the data table lists every node with its group, its full
value and its share, in the order of the tree, so the values are text and not only an area (WCAG 1.1.1, 1.3.1). A tile shows its
name, value and share where they fit and fewer where they do not; a tile too small for a label is still named by the tooltip, the
point label and the table, so the colour is never the only carrier of which category a tile is (1.4.1). The plot is ONE tab stop: the
arrow keys move to the next or previous tile in reading order (the order of the tree, largest first, which is the order of the
table), Home and End jump to the ends, Page Up and Page Down skip a tenth. The tooltip shows on hover and focus, stays while hovered
and closes with Escape (1.4.13, 2.1.1). The draw-in is behind motion-safe:; the plot stays left-to-right in right-to-left pages.
There is no drill-down: a group is shown with its parts inside it. Consumer duties: a title that asks the question, a summary with the main message, the unit in formatValue, saying that area is
proportional to the value (a description like "Area is proportional to headcount").
import { TreemapChart } from "@nexera-ui/react";- 10
- examples
- 20
- props
- 2
- live controls
- 1
- platform
- 9
- WCAG criteria
- 1
- block uses it
Try every prop. Copy the code.
Change the props and the code updates. Check light and dark, LTR and RTL, and phone width.
import { TreemapChart } from "@nexera-ui/react";
<TreemapChart />Examples 9
The same examples as Storybook, rendered live. Open Code to copy one.
Nested
Hierarchical data: a group is a frame with its name and its parts inside it, in the colour of the group. The table lists groups before their parts.
import { TreemapChart } from "@nexera-ui/react";
const people = (value: number): string => `${String(value)} people`;
<TreemapChart
title="Headcount by department and team"
description="Teams are grouped inside their department"
summary="Engineering has 42 people in three teams; Platform is the largest team with 18."
height={320}
data={[
{
name: "Engineering",
children: [
{ name: "Platform", value: 18 },
{ name: "Product", value: 14 },
{ name: "Data", value: 10 },
],
},
{
name: "Sales",
children: [
{ name: "Enterprise", value: 12 },
{ name: "Mid-market", value: 6 },
{ name: "SMB", value: 3 },
],
},
{
name: "Support",
children: [
{ name: "Tier 1", value: 12 },
{ name: "Tier 2", value: 8 },
],
},
{ name: "Ops", value: 17 },
{ name: "Finance", value: 11 },
]}
/>;
Other grouped
minShare groups tiles under 5 % of the whole into one "Other" tile; the table still lists each grouped item.
import { TreemapChart } from "@nexera-ui/react";
<TreemapChart
title="Spend by category"
description="Categories under 5 % are grouped"
summary="Software is 62 percent of spend; travel and training follow."
valueLabel="Spend"
formatValue={(value: number) => `$${value.toLocaleString("en-US")}`}
data={[
{ name: "Software", value: 62000 },
{ name: "Travel", value: 14000 },
{ name: "Training", value: 9000 },
{ name: "Office", value: 7000 },
{ name: "Snacks", value: 2500 },
{ name: "Books", value: 2000 },
{ name: "Plants", value: 1800 },
{ name: "Gifts", value: 1700 },
]}
minShare={0.05}
/>;
Loading
import { TreemapChart } from "@nexera-ui/react";
<TreemapChart state={{ status: "loading" }} />;
Empty
import { TreemapChart } from "@nexera-ui/react";
<TreemapChart
data={[]}
state={{
status: "empty",
title: "No departments to show",
description: "Try another site or clear the filter.",
}}
/>;
Error state
import { Button, TreemapChart } from "@nexera-ui/react";
<TreemapChart
state={{
status: "error",
title: "Couldn't load headcount",
description: "Check your connection and try again.",
action: (
<Button variant="secondary" size="sm">
Try again
</Button>
),
}}
/>;
Single point
One tile fills the plot.
import { TreemapChart } from "@nexera-ui/react";
const people = (value: number): string => `${String(value)} people`;
<TreemapChart
title="Headcount of the new site"
description="One department"
summary="The new site has one department, Engineering, with 12 people."
data={[{ name: "Engineering", value: 12 }]}
/>;
Many points
150 tiles: only the tiles that have room carry a label, every tile is still named by the tooltip, its point label and the table.
import { TreemapChart } from "@nexera-ui/react";
const people = (value: number): string => `${String(value)} people`;
const MANY: TreemapItem[] = Array.from({ length: 150 }, (_, i) => ({
name: `Team ${String(i + 1)}`,
value: 1 + ((i * 37) % 23),
}));
<TreemapChart
title="Headcount by team"
description="150 teams"
summary="Most teams have fewer than ten people."
height={320}
data={MANY}
/>;
Long labels
Long names are shortened on the tiles (the tooltip, the point label and the table keep them in full); the header wraps.
import { TreemapChart } from "@nexera-ui/react";
<TreemapChart
title="Headcount by department, team, location and employment type across the whole group of companies"
description="Area is proportional to headcount, including contractors and part-time employees"
summary="Customer success and onboarding is the largest department."
data={[
{ name: "Customer success and customer onboarding", value: 42 },
{ name: "Platform engineering and infrastructure", value: 31 },
{ name: "Sales development representatives", value: 21 },
{ name: "Finance, treasury and internal audit", value: 11 },
{ name: "People operations and workplace", value: 9 },
]}
/>;
Right to left
Right-to-left page: the card, header and table mirror, the plot keeps its left-to-right layout, digits follow the locale.
import { TreemapChart } from "@nexera-ui/react";
<TreemapChart
title="عدد الموظفين حسب القسم"
description="المساحة متناسبة مع عدد الموظفين"
summary="الهندسة هي أكبر قسم بـ ٤٢ موظفًا من ١٢٨."
data={[
{ name: "الهندسة", value: 42 },
{ name: "المبيعات", value: 21 },
{ name: "العمليات", value: 17 },
{ name: "المالية", value: 11 },
{ name: "الدعم", value: 20 },
{ name: "الموارد البشرية", value: 9 },
{ name: "التصميم", value: 8 },
]}
valueLabel="الموظفون"
labels={{ share: "النسبة", group: "المجموعة" }}
table={{ categoryLabel: "القسم", label: "عرض البيانات كجدول" }}
/>;
Props 20
Press "Try it" on a card to load that prop into the playground.
20 props shown
data*Nexerareadonly TreemapNodeInput[]The hierarchy: a leaf has a value (its area), a group has children; the groups nest as deep as you need. Siblings are laid out
from the largest to the smallest. Figma's headcount by department is flat: seven leaves.
valueLabelNexerastringName of the measure the area stands for ("People"): the tooltip row, the point label and the table column. Translate it.
minShareNexeranumberGroup siblings that are each smaller than this share (0 to 1) of their parent into one "Other" tile, when there are at least two. The tile is focusable and has a tooltip; the table lists every grouped item under "Other", so nothing is hidden. Use it for large data sets whose smallest tiles would be too small to read.
otherLabelNexerastringName of the grouped tile. Translate it.
labelsNexeraPartial<TreemapLabels>Texts the chart invents: the share, the group column and the item count. Translate them.
title*NexerastringChart title: the question the chart answers ("Headcount"). Required: it names the figure, the plot and the data table (WCAG 1.1.1).
descriptionNexeraReactNodeSecondary line under the title.
summary*NexerastringOne or two sentences with what the chart shows and its main message ("Headcount grew from 96 to 128 over twelve months"). Required: it describes the figure for assistive technology (WCAG 1.1.1); the data table has the details.
rangeNexeraChartRangePropsRange switch in the header: 3M, 6M, 12M. Pass the data of the chosen range back in.
actionsNexeraReactNodeExtra controls in the header, after the range switch.
kpiNexeraChartKpiPropsKPI row above the plot: the headline number with an optional label or change badge.
stateNexeraChartPlotStateThe state that replaces the plot: loading (skeleton), empty or error. A chart without a value to plot shows the empty state
by itself; pass { status: "empty", title, description, action } to give it your wording.
tableNexeraChartTableOptionsThe data table that is the text alternative: caption, first-column header and whether it is visible or only for assistive technology.
localeNexerastringLocale of digits and separators.
valueFormatNexeraNumberFormatOptionsIntl.NumberFormat options for values ({ style: "currency", currency: "PKR" }, { style: "percent" }). Serialisable, so it
works from a Server Component; formatValue needs a Client Component.
formatValueNexera(value: number) => stringFormats a value for tooltips, point labels and the table (full precision). Wins over valueFormat.
formatAxisValueNexera(value: number) => stringFormats an axis tick (short: "29M").
heightNexeranumberHeight of the plot in px. The card grows with the header, KPI and legend around it.
plotLabelNexerastringAccessible name of the plot group. Translate it.
noDataLabelNexerastringText for a missing value in the tooltip and the table. Translate it.
* Required. React Aria props shown are the ones most apps use; the component accepts the rest of its React Aria props too.
Accessible by default.
Built on React Aria, and covered by the WCAG 2.2 evidence generated on every build.
WCAG 2.2 evidence
8 direct · 1 supporting- 1.1.1Non-text ContentLevel A · tested directly
- 1.3.1Info and RelationshipsLevel A · tested directly
- 1.4.1Use of ColorLevel A · tested directly
- 1.4.10ReflowLevel AA · tested directly
- 1.4.13Content on Hover or FocusLevel AA · tested directly
- 2.1.1KeyboardLevel A · tested directly
- 2.3.3Animation from InteractionsLevel AAA · supporting test
- 4.1.2Name, Role, ValueLevel A · tested directly
- 4.1.3Status MessagesLevel AA · tested directly
Fits any width.
Nexera components respond to the space they are given. Drag the corner of the frame, or pick a width.
Styling hooks
Pass className to add Tailwind classes (merged last). State is exposed as data attributes, so you can style it with variants like data-pressed:.
<TreemapChart className="shadow-sm" />Used in blocks
Related components
- AccordionItemOne collapsible section of an FAQ or settings page.
- AreaChartA stacked area chart: layers piled up over time with the title, range switch, actions and legend of the card.
- AvailabilityRowOne person's availability across a window of the day: an avatar with initials and the name, and a timeline with the busy periods drawn as bars.
- AvatarA person or organisation shown as a photo, initials or an icon.
- AvatarGroupA row of overlapping avatars with a "+N" chip for the rest.
- AvatarLabelAn avatar with a name and an optional subtitle beside it, for a person in a list, a header or a mention.
- BadgeShort status or category label: `Tone` x `Variant` x `Size`, with an optional dot, leading icon and remove button.
- BadgeGroupA pill that pairs a small badge with a short message, for an announcement or a status line.