Tree
Generic hierarchical list with roving-tabindex keyboard navigation. Distinct from FileTree (which adds folder/file icon-by-extension logic) — Tree is content-agnostic for org charts, taxonomy pickers, navigation trees.
Org chart — controlled selection
- Avery Chen — CEO
- Jordan Lee — CTO
- Sam Patel — Platform Lead
- Morgan Diaz — Product Lead
- Skyler Brooks — CFO
- Reese Walker — CMO
Selected: eng-platform-1
Taxonomy picker — product categories
- Apparel
- Tops
- T-Shirts
- Hoodies
- Sweaters
- Bottoms
- Jeans
- Shorts
- Joggers
- Footwear
- Accessories
Selected: tops/t-shirts
Installation
pnpm dlx @hex-core/cli add treeTaxonomy picker
Categorize a record by picking a leaf in a 3-level taxonomy
<Tree
aria-label="Category"
data={taxonomy}
selected={category}
onSelect={setCategory}
/>API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
datarequired | object | — | Root nodes (TreeNode[]). |
defaultExpanded | object | — | Initial expanded ids (uncontrolled). string[]. |
expanded | object | — | Controlled expanded ids. string[]. |
onExpandedChange | function | — | Callback (ids: string[]) => void. |
selected | string | — | Controlled selected node id. |
onSelect | function | — | Callback (id: string) => void on activation. |
aria-labelrequired | string | — | Accessible name for the tree landmark. |
className | string | — | Additional CSS classes |
AI Guidance
When to use
Use for hierarchical data the user navigates by keyboard or click — org charts, taxonomy pickers, generic nav trees. Pair with selected + onSelect for picker semantics; pair with onExpandedChange to control expansion externally.
When not to use
Don't use for filesystem-shaped data — FileTree adds folder/file icon-by-extension. Don't use for two-level groupings without item-selection — Accordion is the cleaner abstraction. Don't use for primary site nav (NavigationMenu).
Common mistakes
- Forgetting aria-label — required, no fallback
- Confusing data prop (TreeNode[]) with FileTree's nodes prop (FileTreeNode[]) — same shape but different icon defaults
- Trying to pass selected without onSelect — controlled-mode without an updater leaves it stuck
Accessibility
role='tree' on root, role='treeitem' per row, aria-expanded on parents, aria-selected on the chosen leaf. Keyboard: ↑↓ move focus, → expand (or jump to first child if expanded), ← collapse (or jump to parent), Home/End first/last visible row, Enter/Space activate.
Related components
Token budget: 700
Verified against @hex-core/components@1.9.0