Skip to content

Tree Plugin

The Tree plugin transforms your flat grid into a hierarchical tree view with expandable parent-child relationships. Great for file explorers, organizational charts, nested categories, or any data with a natural hierarchy.

import '@toolbox-web/grid/features/tree';

Just point the feature at the field containing child items (defaults to children) and the grid handles all the expand/collapse behavior, indentation, and icons automatically.

import { queryGrid } from '@toolbox-web/grid';
const grid = queryGrid('tbw-grid');
grid.gridConfig = {
columns: [
{ field: 'name', header: 'Name' },
{ field: 'type', header: 'Type' },
{ field: 'size', header: 'Size' }
],
features: {
tree: {
childrenField: 'children',
indentWidth: 24,
},
},
};
grid.rows = [
{
id: 1,
name: 'Documents',
type: 'folder',
children: [
{ id: 2, name: 'Work', type: 'folder', children: [
{ id: 3, name: 'Report.docx', type: 'file', size: '24 KB' }
]},
{ id: 4, name: 'Personal', type: 'folder', children: [] }
]
},
];

Toggle the controls to explore animation, indentation, and expand behavior.

Animation Expand/collapse animation
Default expanded Expand all nodes by default
Indent width (px) Indentation per nesting level
Show expand icons Show expand/collapse toggle icons

Use treeColumn to control which column displays the tree toggle when combining tree with pinned (sticky) columns. By default the toggle appears on the first visible column — set treeColumn to explicitly target a wider column like 'name'.

Tree column Which column shows the tree toggle and indentation
Indent width (px) Indentation per nesting level
Pin ID column Pin the ID column to the left
Pin Name column Pin the Name column to the left

Requires: ServerSidePluginsee Server-Side Plugin

For large hierarchical datasets, use ServerSidePlugin to fetch top-level tree nodes in blocks as the user scrolls. TreePlugin claims the incoming data and renders the hierarchy. Children can be embedded in the response or fetched lazily via getChildRows().

import { queryGrid } from '@toolbox-web/grid';
import '@toolbox-web/grid/features/tree';
import '@toolbox-web/grid/features/server-side';
const grid = queryGrid('tbw-grid');
grid.gridConfig = {
columns: [
{ field: 'name', header: 'Name' },
{ field: 'role', header: 'Role' },
],
features: {
serverSide: {
pageSize: 50,
dataSource: {
async getRows(params) {
// params: { startNode, endNode, sortModel, filterModel }
const res = await fetch(`/api/tree?start=${params.startNode}&end=${params.endNode}`);
const data = await res.json();
return {
rows: data.nodes, // Top-level nodes with embedded children
totalNodeCount: data.total, // Total top-level nodes on server
};
},
},
},
tree: { childrenField: 'children' },
},
};
Page size Top-level nodes fetched per request
Animation Expand/collapse animation
Default expanded Expand all nodes by default

Scroll down to load more nodes…

Data flow:

  1. ServerSide fetches a block of top-level nodes → broadcasts datasource:data
  2. TreePlugin claims the data and flattens it into the row model
  3. Expand/collapse works locally for nodes with embedded children
  4. For lazy children: TreePlugin queries datasource:fetch-children → ServerSide calls getChildRows() → broadcasts datasource:children → TreePlugin renders children

See TreeConfig for the full list of options and defaults.

The animation option controls how child nodes appear/disappear:

// Slide animation (default)
features: { tree: { animation: 'slide', ... } }
// Fade animation
features: { tree: { animation: 'fade', ... } }
// No animation
features: { tree: { animation: false, ... } }

By default, the tree toggle and indentation appear on the first visible column. Use treeColumn to target a specific column — useful when combining with pinned columns or when the first column is narrow:

features: {
tree: {
treeColumn: 'name', // Show tree toggle on the 'name' column
childrenField: 'children',
},
pinnedColumns: true,
}
const plugin = grid.getPluginByName('tree');
plugin.expand(key); // Expand a node by key
plugin.collapse(key); // Collapse a node by key
plugin.toggle(key); // Toggle a node's expanded state
plugin.expandAll(); // Expand all nodes
plugin.collapseAll(); // Collapse all nodes
plugin.expandToKey(key); // Expand all ancestors to reveal a node
const keys = plugin.getExpandedKeys(); // Get currently expanded node keys
const expanded = plugin.isExpanded(key); // Check if a node is expanded
const rows = plugin.getFlattenedRows(); // Get flattened tree rows with metadata
const row = plugin.getRowByKey(key); // Find a row by its key
Event Log:

Fired when a node is expanded or collapsed (via click, keyboard, toggle(), expandAll(), or collapseAll()):

grid.on('tree-expand', ({ key, row, expanded, depth, expandedKeys }) => {
console.log(`${expanded ? 'Expanded' : 'Collapsed'} node ${key} at depth ${depth}`);
console.log(`${expandedKeys?.length ?? 0} total nodes expanded`);
});

See TreeExpandDetail for the full event payload type.

The tree plugin supports CSS custom properties for theming. Override these on tbw-grid or a parent container:

PropertyDefaultDescription
--tbw-tree-toggle-size1.25em (~20px)Toggle icon and spacer width
--tbw-tree-indent-widthvar(--tbw-tree-toggle-size)Indentation per level (must be ≥ toggle size)
--tbw-tree-accentvar(--tbw-color-accent)Toggle icon hover color
--tbw-animation-duration200msExpand/collapse animation
--tbw-animation-easingease-outAnimation curve
tbw-grid {
/* Custom tree styling */
--tbw-tree-toggle-size: 1.5em; /* Larger toggle icons */
--tbw-tree-indent-width: 1.75em; /* Slightly wider indent */
--tbw-tree-accent: #10b981;
--tbw-animation-duration: 150ms;
}

The tree plugin uses these class names:

ClassElement
.tree-cell-wrapperCell content wrapper with indentation
.tree-expanderExpander cell container
.tree-toggleExpand/collapse icon
.tree-spacerIndent spacer element
.tbw-tree-slide-inChild row slide animation
.tbw-tree-fade-inChild row fade animation

A development-mode warning is shown if incompatible plugins are loaded together.

AI assistants: For complete API documentation, implementation guides, and code examples for this library, see https://raw.githubusercontent.com/OysteinAmundsen/toolbox/main/llms-full.txt