Tree
A compound tree component with single-select and checkbox modes, search, keyboard navigation, cascade checking, and ARIA tree semantics.
Installation
npx vayu-ui-cli@latest add treeUsage
Tree
Anatomy
import { Tree } from 'vayu-ui';
import type { TreeNode } from 'vayu-ui';
const data: TreeNode[] = [
{ id: 'root', label: 'Root', children: [{ id: 'child', label: 'Child' }] },
];
<Tree data={data} aria-label="My tree">
<Tree.Search searchQuery={query} onSearchChange={setQuery} />
<Tree.Actions onExpandAll={handleExpandAll} onCollapseAll={handleCollapseAll} />
<Tree.Container>
<Tree.Nodes nodes={data} />
</Tree.Container>
</Tree>;- Tree — Root provider that manages expand, select, and check state. Wraps all sub-components.
- Tree.Search — Controlled search input for filtering nodes. Requires
searchQueryandonSearchChange. - Tree.Actions — Toolbar with Expand All and Collapse All buttons.
- Tree.Container — Bordered container with a built-in empty state fallback.
- Tree.Nodes — Renders an array of
TreeNodeobjects. Typically receives the filtereddataarray. - Tree.Node — Renders a single node with optional children. Used internally by
Tree.Nodesor manually for custom layouts.
Accessibility
- Keyboard Support:
ArrowDown— Move focus to the next visible node.ArrowUp— Move focus to the previous visible node.ArrowRight— Expand a collapsed node, or move focus to the first child of an expanded node.ArrowLeft— Collapse an expanded node, or move focus to the parent of a collapsed node.Home— Move focus to the first visible node.End— Move focus to the last visible node.Enter— Toggle expand/collapse on parent nodes, select in normal mode, or toggle checkbox in checkbox mode.Space— Select a node in normal mode, or toggle checkbox in checkbox mode.
- ARIA Attributes:
- Root has
role="tree"witharia-labeloraria-labelledby. aria-multiselectableis set totruewhenmode="checkbox".- Each node has
role="treeitem"witharia-expanded,aria-selected,aria-disabled, andaria-level. - Child groups use
role="group"witharia-labeldescribing the parent. - Checkboxes use
role="checkbox"witharia-checked(true,false, or"mixed"for indeterminate). - Search input uses
role="searchbox"witharia-label="Search tree". - Action buttons use
role="toolbar"witharia-label="Tree actions".
- Root has
- Focus Behavior:
- Only the focused node has
tabIndex={0}; all others havetabIndex={-1}. - Focus ring is shown via
ring-2 ring-inset ring-focus. - Arrow key navigation cycles through visible nodes only, skipping collapsed children.
- Only the focused node has
Screen reader behavior
When a user navigates to a tree node, the screen reader announces the node label, its nesting level (via aria-level), and its expanded or collapsed state (via aria-expanded). In checkbox mode, the checked state is announced as checked, unchecked, or indeterminate (via aria-checked). When a node is expanded or collapsed, the screen reader announces the state change. Parent nodes are announced with their child count via the role="group" container. Disabled nodes are announced as disabled (via aria-disabled). Users can navigate between nodes using arrow keys, and the screen reader announces each node as it receives focus. The search input is announced as a search box, and toolbar buttons are announced with their respective labels.
Component Folder Structure
Tree/
├── Tree.tsx # Root component with context provider and state management
├── TreeNode.tsx # Individual node rendering with expand, select, and checkbox
├── TreeContainer.tsx # Bordered container with empty state fallback
├── TreeActions.tsx # Expand All / Collapse All toolbar
├── TreeSearch.tsx # Controlled search input with clear button
├── hooks.ts # useTree hook for accessing tree context
├── utils.ts # Tree traversal utilities (flatten, find, filter)
├── types.ts # TypeScript type definitions
└── index.ts # Re-exports all components, hook, and typesProps
Tree (Root)
| Prop | Type | Default | Description |
|---|---|---|---|
data | TreeNode[] | — | Tree data structure. Required. |
mode | 'normal' | 'checkbox' | 'normal' | Selection mode. |
variant | 'default' | 'filled' | 'bordered' | 'minimal' | 'default' | Visual style variant. |
size | 'sm' | 'md' | 'lg' | 'md' | Component size. |
showLines | boolean | true | Show connecting lines between nodes. |
showIcons | boolean | true | Show file/folder icons on nodes. |
defaultExpandAll | boolean | false | Expand all nodes on mount. |
defaultExpandedKeys | (string | number)[] | [] | Initially expanded node keys. |
expandedKeys | (string | number)[] | — | Controlled expanded state. |
onExpandedChange | (keys: (string | number)[]) => void | — | Fired when expand state changes. |
selectedKey | string | number | null | — | Controlled selected node (normal mode). |
defaultSelectedKey | string | number | — | Initially selected node. |
onSelect | (key, node) => void | — | Fired when a node is selected. |
checkedKeys | (string | number)[] | — | Controlled checked nodes (checkbox mode). |
defaultCheckedKeys | (string | number)[] | [] | Initially checked node keys. |
onCheck | (keys, nodes) => void | — | Fired when checkboxes change. |
checkStrictly | boolean | false | Disable parent-child checkbox cascade. |
disabled | boolean | false | Disable the entire tree. |
onNodeClick | (node: TreeNode) => void | — | Fired on any node click. |
renderActions | (node: TreeNode) => ReactNode | — | Render action buttons per node. |
aria-label | string | 'Tree' | Accessible label for the tree. |
aria-labelledby | string | — | ID of the element labeling the tree. |
className | string | — | Additional CSS classes. |
Tree.Search
| Prop | Type | Default | Description |
|---|---|---|---|
searchQuery | string | — | Current search query. Required. |
onSearchChange | (query: string) => void | — | Callback when query changes. Required. |
placeholder | string | 'Search tree…' | Input placeholder text. |
className | string | — | Additional CSS classes. |
Tree.Actions
| Prop | Type | Default | Description |
|---|---|---|---|
onExpandAll | () => void | — | Expand all nodes callback. Required. |
onCollapseAll | () => void | — | Collapse all nodes callback. Required. |
className | string | — | Additional CSS classes. |
Tree.Container
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | Tree content. Required. |
empty | ReactNode | — | Custom empty state fallback. |
className | string | — | Additional CSS classes. |
Tree.Nodes
| Prop | Type | Default | Description |
|---|---|---|---|
nodes | TreeNode[] | — | Array of tree nodes to render. Required. |
Tree.Node
| Prop | Type | Default | Description |
|---|---|---|---|
node | TreeNode | — | Single tree node object. Required. |
level | number | 0 | Nesting depth (0-based). |
TreeNode (Data Type)
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | number | — | Unique identifier. Required. |
label | string | — | Display text. Required. |
icon | ReactNode | — | Custom icon override. |
children | TreeNode[] | — | Nested child nodes. |
disabled | boolean | false | Disable this node. |
selectable | boolean | true | Allow selection on this node. |
metadata | Record<string, unknown> | — | Arbitrary metadata. |