Treemap
import { Treemap } from '@absoluteui/components/treemap';import '@absoluteui/components/treemap/style.css';Using Angular? See Treemap for Angular.
What it does
Section titled “What it does”An accessible SVG treemap for hierarchical part-to-whole data: rectangles laid out with the squarified algorithm (area proportional to value). It provides:
- one level at a time, tiles sorted by value (largest first); groups default to the sum of their children;
- drill-down: a group tile opens with a click or Enter/Space; Backspace and a breadcrumb (
nav“Treemap path”) in the chart toolbar go back up; each change emitsaui-drilland is announced (“Showing All / Engineering”); - keyboard-reachable tiles in size order (one tab stop, arrow keys) with a tooltip on focus and hover;
- printed label and value in tiles large enough to hold them (
tileLabels); - textures (with
patterns) and labels as non-color cues (WCAG 1.4.1); - a generated summary and a data table of the whole hierarchy.
The layout function is exported too: squarify(values, box). Nothing animates.
When to use
Section titled “When to use”- Part-to-whole breakdowns with many items or a hierarchy (budgets, disk usage, portfolio composition).
- Showing which items dominate a total when a pie would have too many slices.
When not to use
Section titled “When not to use”- Precise comparison of values: use Bar Chart (areas compare poorly).
- Few parts of one total: use Pie Chart or Bar Chart.
- Data with negative values (not plotted).
Examples
Section titled “Examples”Hierarchical budget with drill-down and the aui-drill event
Section titled “Hierarchical budget with drill-down and the aui-drill event”import { Treemap, type TreemapDrillDetail, type TreemapNode } from '@absoluteui/components/treemap';
const data: TreemapNode[] = [ { id: 'eng', label: 'Engineering', children: [{ id: 'web', label: 'Web', value: 30 }, { id: 'api', label: 'API', value: 20 }] }, { id: 'ops', label: 'Operations', value: 25 }, { id: 'people', label: 'People', value: 25 },];const host = document.createElement('div');document.body.append(host);const chart = Treemap.create(host, { label: 'Budget', data, valueFormat: { style: 'currency', currency: 'EUR', notation: 'compact' } });host.addEventListener('aui-drill', (event) => { const { path } = (event as CustomEvent<TreemapDrillDetail>).detail; host.dataset.path = path.join('/');});chart.drillTo('eng');Flat treemap without drill-down, exported as PNG
Section titled “Flat treemap without drill-down, exported as PNG”import { Treemap } from '@absoluteui/components/treemap';import { downloadChart } from '@absoluteui/components/chart-export';
const host = document.querySelector<HTMLElement>('#disk');const button = document.querySelector<HTMLButtonElement>('#export');if (host && button) { const chart = Treemap.create(host, { label: 'Disk usage', data: [ { id: 'video', label: 'Video', value: 420 }, { id: 'photos', label: 'Photos', value: 180 }, { id: 'apps', label: 'Apps', value: 95 }, { id: 'docs', label: 'Documents', value: 30, color: 6 }, ], drillDown: false, valueFormat: { style: 'unit', unit: 'gigabyte' }, height: 240, }); button.addEventListener('click', () => { void downloadChart(chart, { format: 'png', fileName: 'disk-usage' }); });}import { Treemap, type TreemapDrillDetail } from '@absoluteui/components/treemap';import '@absoluteui/components/treemap/style.css';
const host = document.querySelector<HTMLElement>('#portfolio');if (host) { Treemap.create(host, { label: 'Portfolio', rootLabel: 'All assets', data: [ { id: 'equity', label: 'Equity', children: [{ id: 'us', label: 'US', value: 40 }, { id: 'intl', label: 'International', value: 20 }] }, { id: 'bonds', label: 'Bonds', value: 30 }, { id: 'cash', label: 'Cash', value: 10 }, ], formatValue: (v) => `${String(v)}%`, }); host.addEventListener('aui-drill', (event) => { host.dataset.level = (event as CustomEvent<TreemapDrillDetail>).detail.id ?? 'top'; });}More usage
Section titled “More usage”import { Treemap } from '@absoluteui/components/treemap';
const host = document.createElement('div');document.body.append(host);Treemap.create(host, { label: 'Budget', data: [ { id: 'eng', label: 'Engineering', children: [{ id: 'web', label: 'Web', value: 30 }, { id: 'api', label: 'API', value: 20 }] }, { id: 'ops', label: 'Operations', value: 25 }, { id: 'hr', label: 'People', value: 25 }, ],});Anatomy
Section titled “Anatomy”<div class="aui-chart aui-treemap [aui-chart--patterns]"> <div class="aui-chart__header"> title, description <div class="aui-chart__toolbar"> (below the top level) <nav class="aui-treemap__path" aria-label="Treemap path"> <ol class="aui-treemap__path-list"> <li class="aui-treemap__path-item"><button class="aui-treemap__path-button">All</button></li> <li class="aui-treemap__path-item"><span aria-current="location">Engineering</span></li> </ol> </nav> </div> </div> <div class="aui-chart__body"> <svg class="aui-chart__svg" role="group" aria-roledescription="treemap" aria-labelledby="T" aria-describedby="S"> <g class="aui-treemap__tiles"> <g class="aui-treemap__tile-group aui-chart__series--c1"> <rect class="aui-treemap__tile [aui-treemap__tile--group] aui-chart__mark" role="img" aria-label="Engineering: 50 (50%), 2 items" tabindex="0"/> <rect class="aui-chart__pattern" aria-hidden="true"/> </g> </g> <g class="aui-treemap__labels" aria-hidden="true">Engineering >, 50</g> </svg> <div class="aui-chart__tooltip" aria-hidden="true" hidden/> </div> <p class="aui-chart__summary" hidden/> <div class="aui-chart__data">Show data table, table</div></div>API reference
Section titled “API reference”Factory
Section titled “Factory”Treemap.create(host: HTMLElement, options: TreemapOptions): TreemapGlobal configuration key: treemap (see Configuration).
Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
label |
string |
Chart title: visible text and the accessible name of the plot (aria-labelledby); also the data table caption. Required. | |
hideLabel |
boolean |
false |
Visually hide the title; it stays the accessible name. |
description |
string |
Visible description below the title, also referenced by aria-describedby (text only). | |
summary |
string |
Replaces the generated accessible summary (shown path, item count, total, three largest items). | |
valueFormat |
Intl.NumberFormatOptions |
Number format for values in tile labels, tooltips, the data table, and the summary (percentages use a percent format). | |
formatValue |
(value: number) => string |
Custom value text; overrides valueFormat everywhere. | |
hiddenSeries |
readonly string[] |
Shared chart option; a treemap has no series, so it has no effect. | |
data |
readonly TreemapNode[] |
Top-level nodes: { id (unique across the tree), label, value?: number | null, children?: TreemapNode[], color?: 1-8 }. Groups default to the sum of their children (a positive own value takes precedence). Zero, negative, and missing values are not plotted. At most 32 levels of nesting. Required. | |
root |
string | null |
null |
Id of the group to show (drill-down state); null shows the top level. An unknown id or a leaf falls back to the top level. Setting it through update() emits no event. |
drillDown |
boolean |
true |
Allow opening groups by click and Enter/Space and going up with Backspace and the breadcrumb. false: groups are plain tiles and no breadcrumb is shown (drillTo() still works). |
rootLabel |
string |
"All" |
Name of the top level in the breadcrumb and the “Showing …” text (default: localized “All”). |
legend |
'auto' | 'show' | 'hide' |
"auto" |
Shared chart option; a treemap labels its tiles directly and never shows a legend, so it has no effect. Globally configurable. |
dataTable |
'toggle' | 'visible' | 'hidden' | 'none' |
"toggle" |
Data table of the whole hierarchy (name path, value, share of parent): behind a Show data table button (built on first open), always visible, visually hidden (screen readers only), or none. Globally configurable. |
tooltip |
boolean |
true |
Tooltip on pointer hover and keyboard focus (label, value, share). Globally configurable. |
patterns |
boolean |
false |
Texture fills on tiles (by position in the shown level) so neighbors never differ by color alone (always on in forced colors). Globally configurable. |
height |
number |
300 |
Plot height in CSS px (integer 120-2000); the width follows the container. Globally configurable. |
tileLabels |
boolean |
true |
Print the label (groups that open end with “>”) and the value inside tiles that are large enough. Globally configurable. |
locale |
string |
"en-US" |
Number and message locale. Globally configurable. Inherited from common configuration. |
direction |
'ltr' | 'rtl' |
"ltr" |
rtl mirrors the layout (largest tile at the top right), right-aligns tile labels, and swaps ArrowLeft/ArrowRight. Globally configurable. Inherited from common configuration. |
Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
host |
HTMLElement |
The host element. |
element |
SVGSVGElement |
The plot (svg role=“group”), named by the title and described by the summary. |
summary |
string |
The generated (or custom) accessible summary. |
root |
string | null |
Id of the shown group (null: top level). |
path |
string[] |
Ids from the top level to the shown group (empty at the top level). |
hiddenSeries |
string[] |
Shared chart property; always empty for a treemap. |
Methods
Section titled “Methods”| Method | Description |
|---|---|
drillTo(id: string | null): void |
Show the group id (null: top level). Ignored for leaves, unknown ids, and the current group. Emits aui-drill and announces “Showing {path}” politely; when focus was in the chart it moves to the largest tile (going down) or the group you came from (going up). |
update(options: Partial<TreemapOptions>): void |
Merge, validate, and re-render. Invalid options throw and keep the previous state. A root in the options replaces the shown group (no event). |
setSeriesVisible(id: string, visible: boolean): void |
Shared chart method; a treemap has no series, so it only re-renders. |
destroy(): void |
Remove rendering, host classes, listeners, the resize observer, and the configuration subscription. |
Events
Section titled “Events”| Event | Detail | Bubbles | Cancelable | Description |
|---|---|---|---|---|
aui-drill |
{ id: string | null; path: string[] } |
Yes | No | The shown group changed through a tile (click, Enter/Space), Backspace, the breadcrumb, or drillTo(). id: the shown group (null: top level); path: ids from the top level. Not emitted for update({ root }). |
CSS classes
Section titled “CSS classes”All rules live in the aui.components cascade layer, so application styles override them without specificity battles.
| Class | Purpose |
|---|---|
aui-chart |
Host (shared chart chrome). |
aui-treemap |
Host modifier for this chart type. |
aui-chart--patterns |
patterns option on: tile textures shown. |
aui-chart__header / __title / __title--hidden / __description / __toolbar |
Title, description, and the toolbar that holds the breadcrumb. |
aui-treemap__path / __path-list / __path-item / __path-button |
Breadcrumb (nav “Treemap path”): ancestor buttons and the current level (aria-current=“location”). |
aui-chart__body / __svg / __layer |
Plot container (height from –aui-chart-height), SVG, and drawing layer. |
aui-chart__series--c1 ... --c8 |
Palette slot classes; set –aui-chart-color from color-chart-<n>. |
aui-chart__pattern / aui-chart__pattern-tile |
Texture overlays. |
aui-treemap__tiles / __tile-group / __tile / __tile--group |
Tile layer, per-tile group, focusable tile (also aui-chart__mark), and tiles that open (pointer cursor). |
aui-treemap__labels / __label / __value |
aria-hidden printed labels and values (also aui-chart__value-label). |
aui-chart__mark / __mark--active / __mark--hover |
Focusable tile and its states (thicker color-text outline). |
aui-chart__tooltip / __tooltip-title / __tooltip-rows / __tooltip-row / __tooltip-label / __tooltip-value |
Tooltip (aria-hidden; the focused tile carries the same text). |
aui-chart__empty |
Empty state text (No data). |
aui-chart__summary |
Hidden summary referenced by aria-describedby. |
aui-chart__data / __data--hidden / __table-toggle / __table-scroll / __table / __cell--numeric |
Data table fallback. |
Design tokens
Section titled “Design tokens”Tokens this stylesheet reads (verified in CI). Override them in a theme or with the Theme Designer.
--aui-border-width | --aui-color-border | --aui-color-border-strong | --aui-color-chart-1 | --aui-color-chart-2 | --aui-color-chart-3 | --aui-color-chart-4 | --aui-color-chart-5 | --aui-color-chart-6 | --aui-color-chart-7 | --aui-color-chart-8 | --aui-color-chart-axis | --aui-color-chart-grid | --aui-color-focus-ring | --aui-color-hover | --aui-color-link | --aui-color-surface | --aui-color-surface-sunken | --aui-color-text | --aui-color-text-muted | --aui-duration-fast | --aui-easing-standard | --aui-focus-ring-offset | --aui-focus-ring-width | --aui-font-family-sans | --aui-font-size-md | --aui-font-size-sm | --aui-font-size-xs | --aui-font-weight-medium | --aui-font-weight-regular | --aui-font-weight-semibold | --aui-line-height-normal | --aui-line-height-tight | --aui-radius-md | --aui-radius-sm | --aui-shadow-md | --aui-space-1 | --aui-space-2 | --aui-space-3 | --aui-tooltip-max-width | --aui-touch-target-min
TypeScript definitions
Section titled “TypeScript definitions”interface TreemapConfig extends ChartBaseConfig { tileLabels: boolean }interface TreemapNode { id: string; label: string; value?: number | null; children?: readonly TreemapNode[]; color?: ChartColor;}interface TreemapOptions extends ChartCommonOptions, Partial<TreemapConfig> { data: readonly TreemapNode[]; root?: string | null; drillDown?: boolean; rootLabel?: string;}interface TreemapDrillDetail { id: string | null; path: string[] }function squarify(values: readonly number[], box: Readonly<{ x: number; y: number; w: number; h: number }>): { x: number; y: number; w: number; h: number }[];Accessibility
Section titled “Accessibility”Pattern: SVG treemap as a named, described group (role=“group” with aria-roledescription “treemap”) of role=“img” tiles in size order with roving focus; one level shown at a time with drill-down (Enter/Space, click), Backspace and a breadcrumb (nav “Treemap path”) to go up, a polite announcement of the shown level, and a data table of the whole hierarchy.
Keyboard
Section titled “Keyboard”| Key | Context | Action |
|---|---|---|
| ArrowRight / ArrowDown | Tile focused | Next tile in size order (largest first); ArrowLeft/ArrowRight are swapped in RTL. |
| ArrowLeft / ArrowUp | Tile focused | Previous tile. |
| Home / End | Tile focused | Largest / smallest tile. |
| PageUp / PageDown | Tile focused | Ten tiles back / forward. |
| Enter / Space | Group tile focused (drillDown on) | Opens the group; focus moves to its largest tile. Ignored on leaf tiles. |
| Backspace | Tile focused below the top level (drillDown on) | Goes up one level; focus moves to the group you came from. |
| Enter / Space | Breadcrumb button | Shows that level (native button); focus moves into the tiles. |
| Escape | Tooltip visible | Hides the tooltip without moving focus (WCAG 1.4.13); it returns on the next move. |
| Tab / Shift+Tab | Any | Breadcrumb buttons (below the top level), then one tab stop for the plot (the active tile), then the Show data table button and table region. |
| Element | Role |
|---|---|
| svg.aui-chart__svg | group with aria-roledescription “treemap” (localized), named by the title |
| tiles (rect.aui-treemap__tile) | img with an aria-label: label, value, share of the shown level, and the item count for groups |
| breadcrumb (nav.aui-treemap__path) | navigation named “Treemap path” with an ordered list: ancestor buttons, then the current level (aria-current=“location”); shown only below the top level |
| data table | table (native) with caption, column headers (Name, Value, Share of parent), and row headers (the name path); wide tables scroll in a focusable region |
| printed labels, textures, tooltip | aria-hidden (decorative duplicates of the accessible data) |
ARIA attributes
Section titled “ARIA attributes”| Attribute | Element | Value |
|---|---|---|
aria-labelledby |
svg | id of the visible (or visually hidden) title |
aria-describedby |
svg | description id (when provided) and the generated summary id |
aria-roledescription |
svg | Localized “treemap” |
aria-label |
each tile | Localized “{label}: {value} ({percent})”, groups “{label}: {value} ({percent}), {count} items”, for example “Engineering: 50 (50%), 2 items” |
tabindex |
active tile | 0 on exactly one tile (roving); other tiles have none |
aria-label |
breadcrumb nav | Localized “Treemap path” |
aria-current |
current breadcrumb item | location |
live region (polite) |
document | “Showing {path}” after each drill, for example “Showing All / Engineering” |
aria-expanded / aria-controls |
Show data table button | Table open state and the table region id |
Roving focus over the tiles of the shown level in size order. Drilling down moves focus to the largest tile; going up (Backspace, breadcrumb, drillTo) moves it to the group you came from, when focus was in the chart. Re-renders (resize, update) keep focus on the same tile.
WCAG 2.2 success criteria addressed
Section titled “WCAG 2.2 success criteria addressed”Automated test results: Accessibility and compliance.
Notes and known caveats
Section titled “Notes and known caveats”- The generated summary names the shown path (below the top level), the item count, the total, and the three largest items with their shares, for example “Showing All / Engineering. treemap, 2 items, total 50. Largest: Web (60%) and API (40%).”
- Tiles are keyboard-reachable in size order (largest first), matching the squarified layout, which places large tiles first.
- Tiles are separated by a surface-colored gap, so neighbors need no mutual contrast; textures (patterns) and printed labels are the non-color cues.
- The data table lists the whole hierarchy (not only the shown level), so every value is reachable without drilling.
- Forced colors: tiles use CanvasText with Canvas separators and textures; focus uses Highlight; breadcrumb buttons use LinkText.
- No animation.
- Manual screen-reader verification (NVDA, JAWS, VoiceOver, TalkBack) is pending.
- aria-roledescription support varies; screen readers without it announce “group”.
- Whether a tile opens is conveyed by its item count in the accessible name, not by a role; Backspace is not discoverable without documentation (the breadcrumb is the visible alternative).
Behavior
Section titled “Behavior”States
Section titled “States”top level, drilled into a group (breadcrumb shown), drill-down off, empty (“No data”: no positive values), tile focused (tooltip), tile hovered, table open.
State transitions
Section titled “State transitions”| From | Trigger | To |
|---|---|---|
| any level | click or Enter/Space on a group tile | that group; focus on its largest tile; aui-drill; “Showing …” announced |
| below the top level | Backspace on a tile | parent level; focus on the group you came from; aui-drill |
| below the top level | breadcrumb button | that level; aui-drill |
| any | drillTo(id) |
that level; aui-drill |
| any | update({ root }) |
that level; no event |
| tooltip visible | Escape | tooltip hidden |
Accessibility notes
Section titled “Accessibility notes”- Tiles are reachable in size order (largest first). Drilling down focuses the largest tile of the group; going up focuses the group you came from, so users never lose their place.
- The summary names the shown path, item count, total, and the three largest items: “Showing All / Engineering. treemap, 2 items, total 50. Largest: Web (60%) and API (40%).”
- The data table lists the whole hierarchy with name paths (“Engineering / Web”), so every value is reachable without drilling.
- Tiles are separated by a
color-surfacegap; textures and printed labels are the non-color cues. - Openable tiles are identified by their item count in the accessible name and “>” in the printed label; Backspace is not discoverable on its own, so the breadcrumb is the visible way back.
- Forced colors: tiles use
CanvasTextwithCanvasgaps and textures; focus usesHighlight; breadcrumb buttonsLinkText. - No animation. Manual screen-reader verification is pending.
Responsive behavior
Section titled “Responsive behavior”The width follows the container (ResizeObserver); the height is height; the layout is recomputed on resize. Labels appear in tiles at least 3em wide and 1.6em tall (values from 3em tall) and are truncated to fit. The breadcrumb wraps; its buttons meet the minimum touch target height. Reflows at 320 CSS px.
Right-to-left
Section titled “Right-to-left”direction: 'rtl' mirrors the layout horizontally (largest tile at the top right), anchors tile labels at the right, and swaps ArrowLeft/ArrowRight. The breadcrumb, tooltip, and table follow the document direction.
Theming
Section titled “Theming”Tiles use color-chart-1..8 by palette slot (position in the shown level, or color); each meets 3:1 against surfaces in all shipped themes. Printed labels use color-text with a color-surface halo.
Global configuration
Section titled “Global configuration”configureAbsoluteUI({ components: { treemap: { tileLabels: false, dataTable: 'visible' } } });Changes apply to existing instances immediately.
Component configuration
Section titled “Component configuration”Instance options override global and theme defaults. All options are dynamic.
None. The group marker “>” is text in the printed label.
Security
Section titled “Security”All text uses textContent; SVG uses createElementNS; colors are classes. No innerHTML or style attributes.
Data handling
Section titled “Data handling”No persistence, network access, or telemetry.
Performance
Section titled “Performance”Budget: Treemap.create with 500 leaves < 60 ms in headless Chromium (e2e performance test), including the first render. Only the shown level is drawn; the data table is built lazily.
Supported data scale
Section titled “Supported data scale”Hundreds of leaves in total; keep each level to a few dozen items so tiles stay large enough to label and target.
Edge cases
Section titled “Edge cases”- Zero, negative, and missing values are not plotted (and not listed in the table); groups whose children are all unplotted become leaves (or disappear).
- A group’s own positive
valuereplaces the sum of its children. - No positive values at all: “No data”.
rootthat no longer exists (or became a leaf) afterupdate(): the top level is shown.- Tiny tiles get no printed label; the tooltip, accessible name, and table still show their values.
Errors
Section titled “Errors”| Code | Category | Cause |
|---|---|---|
TREEMAP_OPTIONS |
configuration | Missing label; data not an array; node ids not unique or empty; non-string labels; non-numeric values; invalid color or children; more than 32 levels; invalid root, drillDown, rootLabel, or formatters. |
CFG_INVALID_VALUE / CFG_UNKNOWN_OPTION |
configuration | Invalid or unknown configuration. |
A failed construction leaves the host untouched.
Known limitations
Section titled “Known limitations”- One level is drawn at a time; grandchildren are not shown nested.
- Tiles are always sorted by value.
- Manual screen-reader verification is pending.
Unsupported scenarios
Section titled “Unsupported scenarios”- Nested multi-level rendering, sunburst and icicle layouts.
- Selection and zoom animation.