Skip to main content

TreeView

The TkTreeview component displays hierarchical data in a tree structure with expandable/collapsible nodes. Uses array-based data structure for better performance and easier data management.

import { TkTreeView } from '@takeoff-ui/react'

Playground

Preview

Generated Code

<TkTreeView
items={[{"key":"1","label":"Documents","children":[{"key":"1-1","label":"Report.pdf"},{"key":"1-2","label":"Summary.docx"}]},{"key":"2","label":"Images","children":[{"key":"2-1","label":"Photo.png"},{"key":"2-2","label":"Logo.svg"}]}]}
mode="basic"
type="basic"
size="base"
selectionStrategy="all"
toggleTrigger="item"
branchIcon="category"
leafIcon="label"
showBadge
showPointer
/>
<TkTreeView
:items="[{"key":"1","label":"Documents","children":[{"key":"1-1","label":"Report.pdf"},{"key":"1-2","label":"Summary.docx"}]},{"key":"2","label":"Images","children":[{"key":"2-1","label":"Photo.png"},{"key":"2-2","label":"Logo.svg"}]}]"
mode="basic"
type="basic"
size="base"
selectionStrategy="all"
toggleTrigger="item"
branchIcon="category"
leafIcon="label"
:showBadge.prop="true"
:showPointer.prop="true"
/>
<tk-tree-view
[items]="[{"key":"1","label":"Documents","children":[{"key":"1-1","label":"Report.pdf"},{"key":"1-2","label":"Summary.docx"}]},{"key":"2","label":"Images","children":[{"key":"2-1","label":"Photo.png"},{"key":"2-2","label":"Logo.svg"}]}]"
mode="basic"
type="basic"
size="base"
selectionStrategy="all"
toggleTrigger="item"
branchIcon="category"
leafIcon="label"
[showBadge]="true"
[showPointer]="true"
/>

Controls

Type

The type prop controls the style type of the tree view. It can be set to basic, divided, or light.

View Code

Mode

The mode prop controls the display mode of the tree view. It can be set to basic or stepper.

Basic Mode

Displays tree items in a traditional hierarchical structure with expandable/collapsible nodes.

Stepper Mode

Displays tree items in a step-by-step column layout, ideal for navigation and drill-down interfaces.

View Code

Size

The size prop controls the size of the tree view. It can be set to base, small, or large.

View Code

Selectable

Enable checkbox selection with the selectable prop for multi-selection functionality. Use the value prop to control selected items and listen to tk-change events for selection updates.

The selectAll prop displays a "Select All" checkbox above the tree with a badge counter showing the total number of selected items. The selection behavior respects the selectionStrategy prop:

  • all: Selects both branches and leaf nodes
  • leaf: Selects only leaf nodes (file nodes)

Selected items: 0

View Code

const [selectedItems, setSelectedItems] = useState([]);

const treeData = [
{
key: 'documents',
label: 'Documents',
children: [
{
key: 'work-files',
label: 'Work Files',
children: [
{
key: 'reports',
label: 'Reports',
children: [
{
key: 'q1-report',
label: 'Q1 Report.pdf'
},
{
key: 'q2-report',
label: 'Q2 Report.pdf'
}
]
}
]
},
{
key: 'personal',
label: 'Personal',
children: [
{
key: 'photos',
label: 'Photos',
children: [
{
key: 'vacation-jpg',
label: 'Vacation.jpg'
}
]
},
{
key: 'notes-txt',
label: 'Notes.txt'
}
]
}
]
}
];

<TkTreeView
type="light"
size="base"
items={treeData}
selectable={true}
selectAll={true}
selectAllLabel="Select All"
selectionStrategy="all"
value={selectedItems}
branchIcon="folder"
leafIcon="insert_drive_file"
onTkChange={(e) => setSelectedItems(e.detail)}
/>

<div>
<p>Selected items: {selectedItems.length}</p>
{selectedItems.length > 0 && (
<ul>
{selectedItems.map((key, index) => (
<li key={index}>{key}</li>
))}
</ul>
)}
</div>

Expand All

The expandAll prop controls the initial expansion state of tree nodes.

Basic Mode with expandAll

Expands all directory nodes throughout the tree, showing the complete hierarchical structure.

Stepper Mode with expandAll

Expands the first directory path all the way down to show the deepest level in a column layout.

View Code

Expanded Keys

The expandedKeys prop to control the expanded items.

Current Expanded Keys: ["third-directory","projects"]
View Code

Collapse Behavior

By default clicking anywhere on a branch item expands or collapses it, so a branch closes when it is clicked while one of its children is highlighted.

Set toggleTrigger="icon" to limit toggling to the arrow icon. Clicking the rest of the item then only highlights it and leaves the tree open.

The highlight always follows the last clicked item, so expanding and collapsing a branch both highlight that branch and the highlight never disappears while the user is only opening and closing branches.

Clicking the highlighted item again removes the highlight. A branch click with the item trigger expands or collapses instead, so it keeps the highlight rather than blinking it on and off on alternating clicks.

Only the arrow icon toggles the branch, clicking the rest of the item just selects it.

View Code

Lazy Loading

Set the lazy prop to fetch a branch's children only when it is expanded. Expanding a branch that has none emits tk-load with the item and its index path, and the fetch is yours to make — the same split as tk-request on the table.

Branches that are not loaded yet have to be marked hasChildren: true, otherwise they cannot be told apart from a leaf and cannot be expanded at all. Put the children you fetch onto that branch in items, and list the keys in flight in loadingKeys to give them a spinner. Clear that list in a finally, or a failed fetch leaves one spinning forever.

Loading Keys: []
Loaded Keys: []
View Code
const initialData = [
{ key: 'documents', label: 'Documents', hasChildren: true },
{ key: 'images', label: 'Images', hasChildren: true },
{ key: 'readme', label: 'readme.txt' },
];

// Rebuilds the branch the children belong to, leaving every other node as it was.
const attachChildren = (nodes, key, children) =>
nodes.map((node) => {
if (node.key === key) {
return { ...node, children, hasChildren: children.length > 0 };
}
if (node.children) {
return { ...node, children: attachChildren(node.children, key, children) };
}
return node;
});

const LazyTree = () => {
const [items, setItems] = useState(initialData);
const [loadingKeys, setLoadingKeys] = useState([]);
const [loadedKeys, setLoadedKeys] = useState([]);
const inFlight = useRef(new Set());

const handleLoad = async (event) => {
const { key } = event.detail.item;
// Collapsing and reopening a branch faster than loadingKeys can round-trip
// through state emits tk-load twice, so keys in flight are tracked in a ref.
if (inFlight.current.has(key)) return;
inFlight.current.add(key);
setLoadingKeys((keys) => [...keys, key]);
try {
const children = await fetch(`/api/folders/${key}`).then((res) => res.json());
setItems((current) => attachChildren(current, key, children));
// Only a branch that actually arrived is marked as loaded; a failed one is
// left off the list so expanding it again retries the fetch.
setLoadedKeys((keys) => [...keys, key]);
} finally {
inFlight.current.delete(key);
setLoadingKeys((keys) => keys.filter((k) => k !== key));
}
};

return (
<TkTreeView
lazy
type="light"
items={items}
loadingKeys={loadingKeys}
loadedKeys={loadedKeys}
branchIcon="folder"
leafIcon="insert_drive_file"
onTkLoad={handleLoad}
/>
);
};

Reopening a branch asks again, which is how a failed fetch is retried. expandAll is ignored here, so expandedKeys is the way to expand a lazy branch programmatically, and a branch it opens is requested just like a clicked one. Selection only ever covers the branches that are loaded.

Custom Styles

The containerStyle and stepStyle props allow you to apply custom styles. The stepStyle prop only works in stepper mode.

In this demo, background color is red for the container and vertical scrolling is applied to the step using max height.

View Code
<TkTreeView
containerStyle={{
backgroundColor: '#f8d7da',
padding: '10px',
borderRadius: '8px',
}}
stepStyle={{ backgroundColor: 'rgb(241 241 241)', maxHeight: '200px', overflowY: 'auto', minWidth: '200px' }}
mode="stepper"
type="divided"
size="base"
items={sampleData}
branchIcon="folder"
/>

TreeView API

Props

NameTypeDefaultDescription
IBadgeOptionsnullBadge customization options for children count display.
string''Icon for branch items (items with children). When empty, no icon is shown.
CSSStylePropertiesnullThe style attribute of container element
booleanfalseIf true, disables all interaction with the tree view.
booleanfalseIf true, expands all nodes in basic mode.
Note: This prop is ignored when expandedKeys is provided.
string[]nullArray of keys that should be expanded.
Usage: Provide an array of item keys: ["atakan", "mehmet", "4"]
Each key must be unique in the tree structure
ITreeItem[][]Array of tree items data. This is the primary way to provide data to the tree view.
booleanfalseIf true, branches are loaded on demand rather than handed over up front. Expanding a branch whose children are missing emits tk-load instead of rendering nothing, and the fetch itself belongs to the consumer.
Note: Branches that are not loaded yet have to be marked with hasChildren: true, otherwise they cannot be told apart from a leaf and cannot be expanded at all. Items also need a key, since loadingKeys and loadedKeys address them by key.
expandAll is ignored while this is set, because the tree it would expand is not loaded yet.
string''Icon for leaf items (items without children). When empty, no icon is shown.
string[][]Keys of the branches whose children have already been fetched. A branch listed here never emits tk-load again, and leaving a failed branch off the list is what allows it to be retried.
Note: This is optional. A branch that came back with children is already recognised as loaded, so the only case that needs this list is a branch that came back empty and should still read as a branch. Marking such a branch hasChildren: false instead turns it into a leaf and takes its arrow away.
string[][]Keys of the branches whose children are being fetched right now. Each of them shows a spinner in place of its toggle icon until its key is taken off the list.
"basic", "stepper"'basic'Tree view mode: 'basic' or 'stepper'.
booleanfalseIf true, shows a "Select All" checkbox above the tree items. Only effective when selectable is true.
string'SelectAll'Label for the "Select All" checkbox row.
booleanfalseIf true, enables checkbox selection for tree items.
"all", "leaf"'all'Selection strategy for checkboxes:
all: selecting a node selects the node itself and all descendants
leaf: selecting a node selects only leaf descendants (and leaf itself if it is a leaf)
booleantrueShow/hide the badge for children count on directories.
booleantrueShow/hide the pointer icon for selected items.
booleantrueShow/hide badges with zero count. Default is true. When false, badges with 0 count will be hidden (works for both selected count and children count).
"base", "large", "small"'base'Tree view size: 'large', 'base' or 'small'.
CSSStylePropertiesnullThe style attribute of column element for stepper mode
"icon", "item"'item'Determines which part of a branch item toggles its expanded state
"basic", "divided", "light"'basic'Tree view type: 'basic', 'divided', or 'light'.
string[]nullThe value of the selected tree item.

Events

NameDescription
tk-changeEvent emitted when the selected value changes.
tk-expand-changeEvent emitted when the expanded paths change in controlled mode. Emits an array of keys (e.g., ["4", "13"]) representing the expanded items. Only the keys of expanded items are emitted, not full paths.
tk-item-clickEvent emitted when a tree item is clicked.
tk-loadEvent emitted when an expanded branch needs its children. Only fires while lazy is set, and only for a branch that has no children and is listed in neither loadingKeys nor loadedKeys.