Acronis UIKit
Components

Treemap

A typed treemap — nested rectangles sized by value.

Usage

import { Treemap } from '@acronis-platform/ui-react';
import type { ChartConfig } from '@acronis-platform/ui-react';

Treemap is a typed composition over the shared Chart primitives. Give it data, a per-leaf config, the size field (dataKey), and the label field (nameKey) — it renders a themed recharts treemap (cells sized by value, colored and labelled per name, with a tooltip and an opt-in legend), so you don't hand-compose recharts children. There are no axes or grid.

Cell colors come from the palette prop, not from config — see Palettes. Each config entry, keyed by a nameKey value, maps that cell to a label and an optional tone that re-points it within the palette. Treemap resolves them into the --color-<name> custom properties its cells fill from.

On-cell labels adapt their text color to three fill tones: dark stops get white text, pale stops get theme-adaptive text, and inverting stops (sequential 7–8, whose fills mirror across themes) use --ui-text-on-status-strong-primary — near-white in light, near-black in dark.

Examples

Leaves sized by value, colored and labelled per name, with a tooltip:

const data = [
  { name: 'React', size: 2400 },
  { name: 'Vue', size: 1600 },
  { name: 'Angular', size: 1200 },
  { name: 'Svelte', size: 800 },
];

const config = {
  React: { label: 'React' },
  Vue: { label: 'Vue' },
  Angular: {
    label: 'Angular'
  },
  Svelte: {
    label: 'Svelte'
  },
} satisfies ChartConfig;

<Treemap
  config={config}
  data={data}
  dataKey="size"
  nameKey="name"
  className="h-[320px] w-[520px]"
/>;

Change the tiling with aspectRatio, and hide the on-cell labels or tooltip with showLabels / showTooltip:

<Treemap
  config={config}
  data={data}
  dataKey="size"
  nameKey="name"
  aspectRatio={2.5}
  showLabels={false}
/>

Cell labels

Each cell is labelled with its leaf's name, centered in the tile by default. The name shown is the leaf's config label, not its raw nameKey value — that value becomes part of a --color-<name> custom property, so it has to be CSS-safe, and a leaf whose display name contains a space is keyed by a slug with the real name in its config entry (the same one the legend and tooltip show).

secondaryKeys adds a second line built from any other fields on the row — a value, a count, or both — and secondaryFormatter formats each of them, receiving the field's index in secondaryKeys so one formatter can cover fields of different kinds:

<Treemap
  config={config}
  data={data} // [{ name: 'React', size: 2400, count: 24 }, …]
  dataKey="size"
  nameKey="name"
  secondaryKeys={['size', 'count']}
  secondaryFormatter={(value, index) =>
    index === 0 ? `${value} kB` : `${value} files`
  }
/>

Labels degrade with the tile: a cell too short for two lines keeps just its name, a line wider than its cell is truncated with an ellipsis, and a tile too small for a label at all is left blank — which is the case the legend covers. Use labelAlign to anchor the block at a corner instead of the default center — the corner values are named bottom-start / top-start (not physical corners) so they mirror under dir="rtl":

<Treemap
  config={config}
  data={data}
  dataKey="size"
  nameKey="name"
  labelAlign="bottom-start"
/>

Pass secondarySeparator to change what goes between the values — a space-padded middot by default — when that reads wrong for your locale.

Legend

showLegend renders one entry per leaf — the same markers, labels and config lookup as every other chart type — and legendPos picks its edge. It's off by default, since a treemap labels its cells; turn it on when the small tiles are too narrow to name themselves. The legend is laid out as a row of the chart rather than over the tiles, and wraps onto further rows when the entries outgrow the width:

<Treemap
  config={config}
  data={data}
  dataKey="size"
  nameKey="name"
  showLegend
  legendPos="top"
/>

Custom tooltip

Replace the tooltip with a configured ChartTooltipContent — imported from the same library, so you never compose recharts yourself. Its formatter renders each row and labelFormatter the header, giving you custom formatting, per-series content, and extra fields:

import { Treemap, ChartTooltipContent } from '@acronis-platform/ui-react';

<Treemap
  config={config}
  data={data}
  dataKey="size"
  nameKey="name"
  tooltipContent={
    <ChartTooltipContent
      nameKey="name"
      hideLabel
      formatter={(value, name) => `${name}: ${value.toLocaleString()}`}
    />
  }
/>;

Animation

Charts render statically by default. Opt in to an entrance animation with animate, and tune it with animationDuration / animationBegin / animationEasing:

<Treemap
  config={config}
  data={data}
  animate
  animationDuration={800}
  animationEasing="ease-out"
/>

animate honors prefers-reduced-motion: for a visitor who has asked their system to reduce motion, the series render at their final geometry with no animation (the same applies when rendering on the server).

Accessibility

Treemap sets no role and no aria-* of its own, and recharts draws a treemap into a bare <svg> — an empty <title> / <desc> pair, no role, no tabindex. So the plot has no accessible name and is not a tab stop, which also makes the tooltip pointer-only.

The root is a plain <div> that spreads the props you pass, so a role and a label land on it:

<Treemap
  role="img"
  aria-label="Bundle size by framework: React 2400 kB, Vue 1600 kB, Angular 1200 kB, Svelte 800 kB"
  config={config}
  data={data}
  dataKey="size"
  nameKey="name"
/>

aria-labelledby works the same way, as does wrapping the chart in a <figure> with a <figcaption>.

A name is not a text alternative, though. A treemap is a visual encoding of numbers, so the numbers themselves have to be reachable as text — a caption, a summary sentence, or a table beside the chart. The cell labels are real text and not glyphs painted into an image: the cell renderer lays them out as HTML inside a <foreignObject>, and a truncated line is a CSS ellipsis, so the full string stays in the DOM. They carry no structural role, though, and they are conditional — a tile too narrow or too short for one is left blank. That last case is what showLegend covers: it renders every leaf's name as ordinary HTML in a row of its own, outside the plot.

Direction (RTL)

Under dir="rtl" the chrome around the plot — the legend row, the tooltip, and any readouts you compose alongside them — mirrors on its own, because it is ordinary flow layout built from logical CSS utilities. The plot area deliberately stays left-to-right: recharts places every mark in physical SVG coordinates, so mirroring it would flip the reading order of the data without flipping the geometry that encodes it. ChartContainer holds that in place by pinning .recharts-surface to direction: ltr.

The cell labels are the one thing inside the surface that is not SVG: the cell renderer lays each one out as HTML in a <foreignObject>, aligned with logical text-start / justify-* utilities, which is why labelAlign's corner values are named bottom-start / top-start rather than for a physical corner. Those labels are the deliberate exception to the pin. A <foreignObject> is a child of the surface, so it would inherit direction: ltr along with everything else in the plot — which would defeat the logical utilities. So ChartContainer pairs the pin with a rule that hands the page's direction back to that subtree, and the labels mirror. Measured in Chromium: the label block computes direction: rtl under dir="rtl" and a bottom-start line sits against the tile's right edge, one cell-padding in, where under dir="ltr" it sits the same distance from the left — so the corner variants land in the tile's bottom-right in RTL. The legend row and the tooltip are outside the surface and mirror with the page as usual.

The two halves are worth keeping straight: the tiling does not mirror (it is geometry recharts computed in physical coordinates, like every other plot), while the labels on it do (they are HTML in flow layout). A label therefore reads from the same start edge the rest of the page reads from, on a tile that stayed put.

API Reference

Prop

Type

Edit on GitHub

On this page