Tree

Pro

A nesting tree view for file explorers, category browsers and any hierarchy. Built on Radix Collapsible, with single selection, full keyboard navigation and CSS guide rails that trace every level.

  • src
    • components
      • button.tsx
      • card.tsx
      • tree.tsx
    • lib
      • utils.ts
    • globals.css
  • public
    • logo.svg
  • package.json
  • README.md

Installation#

# One-time setup (tokens + lib helpers)npx koalaui-cli@latest init# Activate your Pro license (once per machine)npx koalaui-cli@latest login <key># Add this component (its dependencies come along)npx koalaui-cli@latest add tree

Usage#

This example is part of Koala UI Pro

The preview is yours to explore. Its code comes with a Pro license, paid once and used in every project.

Have a license? Unlock it here

A TreeItem with children is a branch (it renders a caret and a collapsible panel); without children it's a leaf. The value is the node's stable identity for selection and expansion. Pass label and icon so every row stays visually consistent, and nest items as children for depth.

Anatomy#

import { Tree, TreeItem } from "@/components/ui/tree"<Tree>  <TreeItem value="branch" label="...">    <TreeItem value="leaf" label="..." />  </TreeItem></Tree>

Selection#

Tree holds a single selection. Control it with value / onValueChange, or let it manage its own with defaultValue. Mark any node disabled to take it out of selection, expansion, and the keyboard order.

  • Guides
    • Getting started
    • Installation
  • Components
    • Overview
    • Changelog

Selected: getting-started

Trailing actions & guides#

The tree isn't only for files. Drop a count, a badge, or a menu in the actions slot, and turn off the indent rails with guides={false} when the icons alone carry the hierarchy.

  • Electronics128
    • Phones54
    • Audio31
    • Laptops43

Drag to reorder#

Pass onMove and every row becomes draggable. Drop near the top or bottom of a row to place a node before or after it, or onto the middle of a folder to drop it inside. The tree doesn't own your data, so it reports the move and you apply it; dropping a node into its own subtree is blocked, and Alt + ↑ / ↓ reorders siblings from the keyboard.

  • app
    • layout.tsx
    • page.tsx
  • components
    • button.tsx
    • tree.tsx
  • tailwind.config.ts
  • README.md

Keyboard#

Focus the tree and navigate without the mouse: ↑ / ↓ move between visible rows, → expands a collapsed branch then steps into it, ← collapses an open branch then steps out to its parent, Home / End jump to the first and last rows, and Enter / Space select (and toggle a branch).

API reference#

Tree

The role="tree" root (a <ul>). Owns single selection, the expanded set and the roving keyboard model. Forwards all native <ul> props; every part accepts className, merged last.

PropTypeDefaultDescription
valuestring-The selected node's value (controlled).
defaultValuestring-The initially selected node (uncontrolled).
onValueChange(value: string) => void-Fires when a different node is selected.
expandedValuesstring[]-The expanded branch values (controlled).
defaultExpandedValuesstring[]-The initially expanded branches (uncontrolled).
onExpandedChange(values: string[]) => void-Fires with the full expanded set whenever a branch toggles.
guidesbooleantrueDraws the vertical rails that trace each nesting level.
onMove(move: TreeMoveEvent) => void-Enables drag to reorder and Alt + arrow sibling moves. Fires { value, target, position } with position one of "before" | "after" | "inside"; apply it to your own data.
CSS variableDescription
--tree-indentThe indent per level, set on the root (5.5 spacing steps). Override it to tighten or widen the ladder.

TreeItem

A node (an <li> holding a role="treeitem" row). With nested TreeItem children it is a branch on a Radix Collapsible; without, a leaf. Forwards all native <li> props.

PropTypeDefaultDescription
value*string-Stable identity for selection, expansion and moves.
labelReactNode-The row label, truncated to one line.
iconReactNode-Leading glyph, e.g. a folder or file icon. A bare icon is sized to 20px.
expandedIconReactNodeiconLeading glyph shown while the branch is open, e.g. FolderOpen.
actionsReactNode-Trailing content such as a count badge or a row menu.
disabledboolean-Removes the node from selection, expansion, focus and dragging.
childrenReactNode-Nested TreeItems. Their presence makes the node a branch.
Data attributeDescription
data-selected"true" on the row of the selected node, else "false".
data-expanded"true" on the row of an open branch, else "false".
data-branch"true" when the node has children.
data-levelThe row's depth, starting at 0.
data-valueThe node's value, on the row.
data-draggingPresent on the row being dragged.
data-dropbefore, after or inside on the row under a drag.
data-stateopen or closed on a branch's nested group (Radix Collapsible).
CSS variableDescription
--tree-levelThe depth, set inline on each row and group; drives the row inset and the guide rail position.

FAQ#

Children. A `TreeItem` with nested `TreeItem` children renders a caret and a collapsible panel (a branch); one without children is a leaf. There is no separate type prop, just the presence of `children`.