Tree
A data-driven hierarchical tree view of folders and leaves with selection, expand/collapse, per-node icons, an actions slot, and a custom renderItem. Self-managed expand state, animated open/close, ARIA roving-tabindex keyboard navigation, and native drag-and-drop to reorder or re-parent nodes via onDocumentDrag. Controlled or uncontrolled selection reported through onSelectChange.
A data-driven hierarchical tree view. Pass a data array of TreeDataItem
nodes — any node with children is a folder that expands and collapses, anything
else is a leaf. The tree manages its own expand state (auto-expanding the
ancestors of the selected node, or everything when expandAll is set) and its
selection — controlled with selectedId or uncontrolled from defaultSelectedId,
reporting changes through onSelectChange. Each node can carry
its own icons, an actions slot, and a disabled flag, or you can take over the
whole row with renderItem. Mark nodes draggable / droppable to reorder or
re-parent them with native drag-and-drop through onDocumentDrag.
Installation
One-time setup: add the @ikui registry to your components.json.
{
"registries": {
"@ikui": "https://ik-ui.pages.dev/r/{name}.json"
}
}Then install the component:
pnpm dlx shadcn@latest add @ikui/treeUsage
import { Tree, type TreeDataItem } from "@/components/tree";const data: TreeDataItem[] = [
{
id: "app",
name: "app",
children: [
{ id: "page", name: "page.tsx" },
{ id: "layout", name: "layout.tsx" },
],
},
{ id: "readme", name: "README.md" },
];
<Tree
data={data}
defaultSelectedId="page"
onSelectChange={(item) => console.log(item?.name)}
/>;Keyboard
The tree follows the ARIA tree pattern with a roving tabindex, so it takes a single stop in the tab order. Once focused, navigate entirely with the keyboard:
- ↑ / ↓ — move to the previous / next visible node (disabled nodes are skipped).
- → — expand a collapsed folder, or move to its first child when already expanded.
- ← — collapse an expanded folder, or move to its parent.
- Home / End — jump to the first / last visible node.
- Enter / Space — select the node (and toggle it when it is a folder).
Examples
Per-node icons
Set icon on a node, plus openIcon (shown while a folder is expanded) and
selectedIcon (shown while selected). defaultNodeIcon / defaultLeafIcon fill
in any node that doesn't specify its own.
Tracking selection
onSelectChange fires with the clicked TreeDataItem (folders included). The
selected row stays highlighted.
Row actions
Give a node an actions node to render trailing controls — revealed on hover or
when the row is selected. Clicks inside actions don't select or toggle the row.
Drag and drop
Set draggable on the nodes you can pick up and droppable (default true) on
the ones that can receive a drop. onDocumentDrag(source, target) fires on drop —
the tree only tracks the gesture and highlights the target; you own the data, so
reorder or re-parent it in the handler. Here, dropping a file onto a folder moves
it in.
Props
| Prop | Type | Default |
|---|---|---|
data | TreeDataItem[] | TreeDataItem | - |
selectedId | string | - |
defaultSelectedId | string | - |
initialSelectedItemId | string | - |
onSelectChange | (item: TreeDataItem) => void | - |
expandAll | boolean | false |
chevronPosition | "left" | "right" | "left" |
defaultNodeIcon | React.ComponentType<{ className?: string }> | - |
defaultLeafIcon | React.ComponentType<{ className?: string }> | - |
renderItem | (params: TreeRenderItemParams) => React.ReactNode | - |
onDocumentDrag | (source: TreeDataItem, target: TreeDataItem) => void | - |
className | string | - |
TreeDataItem
| Prop | Type | Default |
|---|---|---|
id | string | - |
name | string | - |
children | TreeDataItem[] | - |
icon | React.ComponentType<{ className?: string }> | - |
openIcon | React.ComponentType<{ className?: string }> | - |
selectedIcon | React.ComponentType<{ className?: string }> | - |
actions | React.ReactNode | - |
onClick | () => void | - |
disabled | boolean | - |
draggable | boolean | - |
droppable | boolean | true |
className | string | - |
TreeRenderItemParams
| Prop | Type | Default |
|---|---|---|
item | TreeDataItem | - |
level | number | - |
isLeaf | boolean | - |
isSelected | boolean | - |
isOpen | boolean | - |
hasChildren | boolean | - |