Treemap of Disk Usage by Folder
If you are the storage admin, the question is not how full the volume is. It is which folders take the space, and how much of it nobody has touched in years, so you know what to archive before you buy more disk.
A treemap answers that. Each folder is a tile whose area is its size, and the tiles sit inside a branch for their age band. The chart above is bound to the grid beneath it, one row per folder, so filtering the rows redraws the chart. Filter the Age column to Over 2 years and only the stale folders are left on the canvas.
Why a treemap and not a pie
A pie cannot hold thirty folders and cannot nest them. A treemap spends its whole area on the sizes, so a few large folders dominate at once, and it nests, so each folder keeps its place inside its age band.
The chart over a grid
The chart reads the grid’s rows, and the tree it draws is the grid’s own grouping. Group the grid by the age band and then the folder, and the treemap has one branch per band with a tile per folder inside it. The measure, y, sizes the tiles. Each branch takes its own colour, and the legend names the age bands. Here is the example in plain JavaScript, with sample rows inline in place of your own.
import { createGrid } from '@toclocoinc/lattice-grid';
import '@toclocoinc/lattice-grid/css';
import { createChart } from '@toclocoinc/lattice-grid/modules/charts';
const rows = [
{ id: 1, path: '/shares/it/backups', gb: 910, modified: '2026-11-12', age: 'Under 1 year' },
{ id: 2, path: '/shares/design/renders', gb: 640, modified: '2026-11-04', age: 'Under 1 year' },
{ id: 3, path: '/shares/engineering/releases', gb: 345, modified: '2025-07-15', age: '1 to 2 years' },
{ id: 4, path: '/shares/support/call-recordings', gb: 690, modified: '2024-06-11', age: 'Over 2 years' },
{ id: 5, path: '/shares/finance/archive', gb: 412, modified: '2023-02-14', age: 'Over 2 years' },
];
const gridEl = document.createElement('div');
const chartEl = document.createElement('div');
gridEl.style.height = '240px';
chartEl.style.height = '360px';
document.body.append(gridEl, chartEl);
const grid = createGrid(gridEl, {
rowKey: 'id', rows, groupDefaultExpanded: false,
columns: [
{ field: 'age', title: 'Age', filter: { type: 'set' }, group: { enabled: true, index: 0 } },
{ field: 'path', title: 'Folder', group: { enabled: true, index: 1 } },
{ field: 'gb', title: 'Size (GB)', type: 'number', total: 'sum' },
{ field: 'modified', title: 'Last modified' },
],
});
createChart({ grid, container: chartEl, type: 'treemap', y: 'gb',
title: 'Disk usage by folder, grouped by age' });
The same thing in React
The React adapter is a factory, so you build the component once at module scope. The ref’s grid is the real grid, which is what the chart binds to.
import React, { useEffect, useRef } from 'react';
import { createGrid } from '@toclocoinc/lattice-grid';
import '@toclocoinc/lattice-grid/css';
import { createLatticeGrid } from '@toclocoinc/lattice-grid/modules/react';
import { createChart } from '@toclocoinc/lattice-grid/modules/charts';
const LatticeGrid = createLatticeGrid({ React, createGrid });
const rows = [
{ id: 1, path: '/shares/it/backups', gb: 910, modified: '2026-11-12', age: 'Under 1 year' },
{ id: 2, path: '/shares/design/renders', gb: 640, modified: '2026-11-04', age: 'Under 1 year' },
{ id: 3, path: '/shares/engineering/releases', gb: 345, modified: '2025-07-15', age: '1 to 2 years' },
{ id: 4, path: '/shares/support/call-recordings', gb: 690, modified: '2024-06-11', age: 'Over 2 years' },
];
const columns = [
{ field: 'age', title: 'Age', filter: { type: 'set' }, group: { enabled: true, index: 0 } },
{ field: 'path', title: 'Folder', group: { enabled: true, index: 1 } },
{ field: 'gb', title: 'Size (GB)', type: 'number', total: 'sum' },
];
export function DiskTreemap() {
const gridRef = useRef(null);
const chartRef = useRef(null);
useEffect(() => {
const chart = createChart({ grid: gridRef.current.grid, container: chartRef.current,
type: 'treemap', y: 'gb' });
return () => chart.destroy();
}, []);
return (<>
<LatticeGrid ref={gridRef} rowKey="id" columns={columns} rows={rows}
groupDefaultExpanded={false} style={{ height: 200 }} />
<div ref={chartRef} style={{ height: 320 }} />
</>);
}
The options used
These are the rows of the charts reference for the options in the listings above.
| Option | Type | What it does |
|---|---|---|
grid |
Grid | Required. The grid to read. |
container |
Element or string | Required. Where to draw. |
type |
string | 'treemap' here, nested tiles sized by the measure. |
y |
string | The measure column. Here it is the folder size, which sets each tile’s area. |
title |
string | Drawn above the plot. |
The tree itself comes from the grid’s grouping, one level per grouped column in order, so x is not used.
Reading the canvas
The bigger the tile, the more space the folder takes, and the branch it sits in is its age. In the example, the Over 2 years branch holds several large folders that nobody has opened in that long, which is the space to archive first. A big tile in the Under 1 year branch is large but in use, so it is a question for the next purchase and not for a clean-up.
Next
See the treemap beside the other part-to-whole charts in the bar, line and pie family demo, read the full list of chart types on the charts page, or follow the how-to for a chart that follows the grid.