1. Documentation
  2. Navigation
  3. Tree
ReadmenpmGitHub
  • Introduction
  • Installation
  • Theming
  • Icons
  • Accordion
  • Card
  • Scroll Area
  • Separator
  • Sidebar
  • Field
  • Label
  • Input
  • Textarea
  • Number Field
  • OTP Field
  • Select
  • Combobox
  • Checkbox
  • Radio
  • Switch
  • Slider
  • Toggle
  • Calendar
  • Date Picker
  • File Upload
  • Button
  • Copy Button
  • Dropdown
  • Command
  • Tabs
  • Breadcrumb
  • Pagination
  • Tree
  • Table
  • Data Table
  • Stat
  • Timeline
  • Avatar
  • Status Bar
  • Badge
  • Meter
  • Empty
  • Skeleton
  • Spinner
  • Toast
  • Dialog
  • Sheet
  • Popover
  • Tooltip
  • Text
  • Kbd
  • Code Block
  • Utilities
  • Design rules

Tree

A collapsible hierarchy with a guide line per level — file trees, resource explorers, nested config.

Loading documentation…

Pagination< PreviousTableNext >

Powered by heyo

On this page

UsageBranches and leavesControlled expansionPropertiesTreeNode
<TreedefaultExpanded={["src"]}selected={selected}onSelect={(node) => setSelected(node.id)}nodes={[  {    id: "src",    label: "src",    icon: IconFolder,    children: [      { id: "index", label: "index.ts", icon: IconCode, meta: "2.1 kB" },      { id: "worker", label: "worker.ts", icon: IconCode, meta: "8.4 kB" },    ],  },  { id: "readme", label: "README.md", icon: IconCode },]}/>

Tree renders a hierarchy from data. Indentation is drawn as a guide line per level rather than as padding, so at depth five you can still see which branch a row belongs to.

Rows are real buttons inside a tree role, so arrow keys and screen readers both work without anything extra from you.

Usage

tsx
import { Tree } from "@heyo-sh/heyo-ui";<Tree  nodes={nodes}  defaultExpanded={["src"]}  onSelect={(node) => open(node.id)}/>;

Branches and leaves

children decides what a node is. An array — even an empty one — makes a branch with a chevron, which is how an empty folder stays a folder. Leave it undefined for a leaf.

<TreedefaultExpanded={["bindings"]}nodes={[  {    id: "bindings",    label: "Bindings",    children: [      { id: "kv", label: "KV", meta: <Badge variant="count">2</Badge> },      { id: "r2", label: "R2", children: [] },    ],  },]}/>

Controlled expansion

expanded with onExpandedChange hands the open branches to you — the way to persist them, or to expand a path when a route changes.

tsx
const [expanded, setExpanded] = useState<string[]>(["src"]);<Tree nodes={nodes} expanded={expanded} onExpandedChange={setExpanded} />;

openIcon swaps the glyph for an open branch, which is how a closed folder and an open one end up looking different.

Properties

nodesTreeNode[]required

The hierarchy.

defaultExpandedstring[]optional

Ids of the branches open on first render.

expandedstring[]optional

Controlled open branches. Pair it with onExpandedChange.

onExpandedChange(expanded: string[]) => voidoptional

Fires when a branch opens or closes.

selectedstring | nulloptional

The selected node's id. Selection is always controlled.

onSelect(node: TreeNode) => voidoptional

Fires with the whole node, not just its id.

openIconIconLikeoptional

The icon for an open branch, when it differs from icon.

classNamestringoptional

Merged into the root.

TreeNode

idstringrequired

Stable id, used for expansion, selection and React keys.

labelReactNoderequired

The row's text.

iconIconLikeoptional

The leading glyph.

metaReactNodeoptional

A right-aligned hint — a count, a status dot, a size.

childrenTreeNode[]optional

Nested nodes. An empty array still renders a chevron; undefined makes a leaf.

disabledbooleanoptional

Dims the row and ignores interaction.