Tree

A hierarchy the reader can expand, select, check and drag, with a virtual list for the large ones.

Usage

A tree is a nested list whose rows people open, select, check and drag. Use one when the nesting has to be visible.

When to use

Use Tree when the nesting matters: people need to see where something sits, and opening a branch is quicker than opening a page.
  • A file and folder browser, which is what Tree.DirectoryTree is for.
  • A permission, category or tag picker where checking a parent means all its children.
  • An org chart, an account hierarchy or a list of locations that people browse by expanding.
  • A structure people rearrange by dragging, like a page outline or a menu builder.
What to use instead.
  • Menu for navigation. It marks the current page and has the roles a nav needs, and a tree of links has neither.
  • Table with expandable rows when the children are records with the same columns as their parents.
  • Cascader or TreeSelect when the hierarchy is the value of a form field. Both put the tree behind a trigger and return one path.
  • Collapse for one level of content blocks.

treeData, and renaming its fields

Pass nodes through treeData. Nesting Tree.TreeNode elements is deprecated, and the kit does not re-export Tree.TreeNode.
  • Give every node a stable key. expandedKeys, selectedKeys, checkedKeys and loadedKeys all use it, so a key that changes on reload collapses and deselects the tree.
  • fieldNames renames the key, title and children fields. Use it instead of copying your data into a new array on every render, which slows a large tree down.
  • titleRender renders every row's title, for anything richer than a string.
  • isLeaf marks a node with no children. Without it, a childless node still shows a switcher, which is how loadData gets a chance to fill it.
  • Other fields on a node are kept, and aria-* and data-* keys land on the row element.

Expansion

Expansion is uncontrolled until you pass expandedKeys. Then you own it, so pair it with onExpand or the switcher stops working.
  • defaultExpandedKeys opens a few branches on the first render and leaves the rest to the reader.
  • defaultExpandAll opens every branch, which gets slow past a few hundred nodes, most of all without height. Control expandedKeys and add an expand all button instead.
  • defaultExpandParent is on by default and opens the parents of the keys you expand, once.
  • autoExpandParent reopens the parents of the expanded keys on every change. Turn it on while a search box sets expandedKeys, then off again, or it reopens a branch the reader just closed.
  • On a plain Tree the switcher expands and the title selects. expandAction changes that on DirectoryTree only.

Checking, and checkStrictly

checkable adds checkboxes. Checking a parent checks everything under it, and a parent with some children checked shows as half checked.
  • checkStrictly makes parents and children independent. Use it when a parent is something you grant on its own, like a folder shared without its files.
  • It also changes the value: checkedKeys and onCheck use { checked, halfChecked } instead of an array of keys. Decide before you write the handler.
  • disableCheckbox on a node disables its checkbox and keeps the row selectable. disabled disables both.
  • A tree that is both checkable and selectable gives each row two states. Pick one, unless selection means something else, like which node the panel beside the tree shows.

Large trees: lazy children and windowing

A big tree has two costs: fetching the nodes and rendering them. loadData handles the first and virtual the second.
  • loadData receives a node and returns a promise. Resolve it after adding the children to your treeData. The tree tracks loadedKeys, so each branch loads once.
  • While it loads, the switcher shows a spinner, which switcherLoadingIcon replaces. Set isLeaf on real leaves, or every file offers an arrow that loads nothing.
  • virtual is on by default and does nothing without height. With a height, only the visible rows are in the DOM, so tests and find in page cannot see the rest.
  • itemHeight comes from the theme, so tell the tree if your CSS makes rows taller. scrollWidth adds horizontal scrolling for rows wider than the tree.

Dragging

draggable turns on dragging and draws a grip on each row. Pass a function (node) => boolean to make only some rows draggable, or an object with nodeDraggable and an icon, where false removes the grip.
  • allowDrop decides whether a drop position is allowed, which is where a rule like “a file cannot hold children” goes.
  • onDrop reports dropPosition and dropToGap. A drop in the gap goes between two siblings, and a drop on a node goes inside it.
  • The tree does not move anything. Build the new treeData yourself from what onDrop reports.
  • Dragging has no keyboard route, so also offer a move command in the row's menu.

Lines, icons and the switcher

  • showLine draws connector lines, and the switcher stays your icon pack's chevron. Lines help on a deep tree and add clutter to a shallow one. showLine={{ showLeafIcon: <Icon name="file" /> }} puts an icon at the end of each leaf's line.
  • showIcon is off on a plain Tree, and on its own it draws nothing. Pass icon per node or for the whole tree.
  • switcherIcon defaults to your icon pack's chevron, which rotates as a row opens. Pass a function of expanded to keep the rotation, a node to replace it without rotation, or null for no switcher.
  • Add icons when they tell kinds of node apart that the text does not, and keep the set small.

Tree.DirectoryTree

Tree.DirectoryTree is Tree set up as a file browser. It shows file, folder and open folder icons from your icon pack, makes the whole row clickable, and opens a folder when you click its name.
  • expandAction={false} separates opening from selecting, and doubleClick opens on a double click, as desktop file managers do. Use the same choice across your product.
  • multiple adds Ctrl or Cmd to add a row and Shift to select a range, as people expect in a file list.
  • The selected row uses the primary color rather than the light fill of a plain Tree, so it reads as where the reader is.