Skip to content
WANCRAFT

G.149Data & Feedback

Treemap

A squarified treemap of nested data: colour by group, tooltips, and click-to-zoom drill-down with a breadcrumb back up.

NewReactMotionTailwindadvanced

Overview

Treemap lays out hierarchical data with the squarified algorithm (implemented inline, no dependencies), so tiles stay close to square and easy to compare. Two levels show at a time: each group is a tinted frame with its children inside, coloured by top-level group and stepped lighter by rank. Large tiles carry a label and value; hover, tap or focus any tile for a tooltip with its path, value and share of the total. Click or press Enter to zoom into a group — tiles that stay in view spring to their new boxes and new ones grow out of their parent's old box — and use the breadcrumb, Escape or Backspace to zoom back out. Arrow keys move focus to the nearest tile in that direction, and a visually hidden nested list carries the whole hierarchy for screen readers.

01Installation

Method 01 · Registry

CLI verified

Uses the shadcn CLI in a project initialised with shadcn init. Installs the file to components/ui/treemap.tsx and adds its dependencies.

npx shadcn@latest add https://wancraft.my/r/treemap.json

Method 02 · Copy and paste

  1. 1. Install the dependencies below.
  2. 2. Copy the source from the Code tab into components/ui/treemap.tsx.
  3. 3. Import it and adjust props.
npm install motion
Dependencies
motion
Peer
react ≥ 18, tailwindcss ≥ 4
Added
13 Oct 2026
Updated
—

02Usage

The default configuration. Change properties above to generate a tailored example in the Usage tab.

example.tsx
import { Treemap, type TreemapNode } from "@/components/ui/treemap";

export function TreemapExample() {
  const data: TreemapNode = {
    id: "revenue",
    label: "Revenue",
    children: [
      { id: "software", label: "Software", children: [
        { id: "editor", label: "Editor", value: 420 },
        { id: "plugins", label: "Plugins", value: 160 },
      ] },
      { id: "hardware", label: "Hardware", children: [
        { id: "tablets", label: "Tablets", value: 310 },
        { id: "pens", label: "Pens", value: 90 },
      ] },
      { id: "services", label: "Services", value: 240 },
    ],
  };

  return (
    <Treemap data={data} format={(v) => `$${v}k`} />
  );
}

03Props

PropTypeDefaultDescription
data{ id; label; value?; children? }—Root node (required). Leaves carry values; groups sum their children.
heightnumber380Map height in px; the width follows the container (ResizeObserver).
nestedbooleantrueDraw each group's children inside it (two levels at a time).
showValuesbooleantrueValue under the label on tiles large enough.
gapnumber2Gap between tiles in px.
radiusnumber4Tile corner radius in px.
spring{ stiffness, damping, mass }{ stiffness: 210, damping: 28, mass: 1 }Spring for the drill-down zoom (instant with reduced motion).
accentstring"#FF7448"Colour of the first top-level group; others use a categorical palette.
format(value: number) => string—Value formatter (compact en-US by default).
onDrill(id: string) => void—Called with the id of the node zoomed into.

04Features

  • 01Squarified layout (Bruls et al.) implemented inline
  • 02Two levels at a time: tinted group frames with their children inside
  • 03Colour by top-level group, lighter steps by rank; stable across drill-downs
  • 04Click / Enter zooms into a group with a spring layout transition; breadcrumb, Escape or Backspace zooms out
  • 05Tooltip with path, value and share of total on hover, tap or focus
  • 06Labels and values only where they fit; responsive via ResizeObserver
motion · springmotion · layoutinput · hoverinput · clickinput · keyboardinput · focus

05Accessibility

  • Tiles are buttons in a single tab stop (roving tabindex); arrow keys move to the nearest tile in that direction, Home and End to the first and last.
  • Each tile's accessible name includes its value, share of its group and share of the total.
  • The breadcrumb is a nav with aria-current on the level in view; drilling is announced in a polite live region and focus stays in the map.
  • A visually hidden nested list carries the full hierarchy with values and shares.
  • Visible focus outline on every tile; with prefers-reduced-motion the zoom is instant.

06Limitations

  • Shows two levels at a time; deeper levels appear as you drill in.
  • Very small tiles stay unlabelled — their data is in the tooltip, the accessible name and the hidden list.