Kanzo UI
Data display

Tree View

A keyboard-navigable hierarchy of branches and leaves.

Ark UI
Warm-blooded
Flying
Harpy

Usage

import {
  TreeView,
  TreeViewBranch,
  TreeViewBranchContent,
  TreeViewBranchItem,
  TreeViewContent,
  TreeViewItem,
  TreeViewNode,
  TreeViewTree,
  createTreeCollection,
} from "@kanzo-tech/ui";
const collection = createTreeCollection({ rootNode: tree });

<TreeView collection={collection} defaultExpandedValue={["warm"]}>
  <TreeViewTree>{/* recursive nodes */}</TreeViewTree>
</TreeView>;

createTreeCollection wraps Ark's with nodeToValue: node => node.id and nodeToString: node => node.name already filled in, so a tree of { id, name, children } needs no adapter.

Anatomy

TreeViewBranchIndicator is the chevron that turns as a branch opens — 90 degrees on data-[state=open], and nothing at all under prefers-reduced-motion. TreeViewBranchItem renders one for you ahead of the title, so reach for it directly only when the row is arranged differently and the indicator belongs somewhere other than first.

<TreeView collection>
  <TreeViewLabel />
  <TreeViewTree>
    <TreeViewNode node indexPath>       ← recursive
      branch:  <TreeViewBranch>
                 <TreeViewBranchItem />  ← indicator + folder icon + text
                 <TreeViewBranchContent> ← children, plus the indent guide
      leaf:    <TreeViewContent>
                 <TreeViewItem />

The node renderer is recursive and you write it: a node with children becomes a TreeViewBranch, everything else a TreeViewContent. indexPath is how Ark locates the node in the collection, so it must be threaded through each level.

File icons

Leaf icons resolve from the file extension, so a node never carries its own icon. Pass a map built with createFileIcons; anything unmatched falls back to TreeViewItem's icon.

archive
charter.md
standing-orders.rules
board.csv
heraldry.json

Keyboard

KeyDoes
↓ / ↑Moves focus to the next / previous visible node, stepping into and out of expanded branches.
→Expands the focused branch, or moves to its first child when it is already open; nothing on a leaf.
←Collapses the focused branch, or moves to the parent when it is already closed.
Home / EndMoves focus to the first / last visible node.
Enter / SpaceSelects the focused node, and toggles a branch open or closed.
*Expands every branch that is a sibling of the focused node.
A–ZTypeahead: moves focus to the next visible node whose label starts with what you have typed.
Shift+↓ / ↑ / Home / EndExtends the selection as it moves, under selectionMode="multiple".
⌘+ASelects every node, under selectionMode="multiple".
F2Starts renaming the focused node, when the root is given a canRename predicate that returns true for it. The rename input is rendered by the node itself.

Select-all is bound to the Meta key alone, so Ctrl+A does not reach it on Windows or Linux — while the click path in the same machine treats Ctrl and Meta alike, so pointer and keyboard disagree about the same modifier.

Focus is painted for the keyboard only. Ark marks its roving tab stop data-focus, and with nothing focused that is the first node — so a row painted on it looks chosen the moment the tree mounts, before anyone has touched it. The row paints its focus on :focus-visible instead: arrowing through the tree shows where you are, and a tree nobody has touched shows nothing but its selection.

What would reverse it: Ark exposing whether its focus is the keyboard's. Then the row reads that attribute rather than the pseudo-class, and nothing a reader sees changes.

Held by packages/ui/src/simples/tree-view.test.tsx, "paints a row's focus for the keyboard only, not the tab stop Ark marks at rest".

API Reference

TreeView

PropTypeDefault
fileIconsRecord<string, ElementType | null>—
lazyMountbooleantrue
unmountOnExitbooleantrue

TreeViewBranchItem

PropTypeDefault
iconElementType | nullFolderIcon
expandedIconElementType | nullFolderOpenIcon

TreeViewItem

PropTypeDefault
iconElementTypeFileIcon

Passing null for an icon removes it entirely rather than falling back to the default. collection, selectionMode, expandedValue and the rest come from Ark's TreeView.Root; TreeViewCheckbox is available for selectionMode="multiple", and useTreeView re-exports Ark's context hook.

TreeNodeType is one node — id, name, optional children and its two icons — and TreeCollection is Ark's collection over them, re-exported so a host builds one without importing Ark directly. NodeProviderProps is the provider a custom node renderer sits inside.

On this page