Prodular UI

Tree

Pro

A hierarchical list with expand and collapse, roving focus, type-ahead, selection, icons, metadata and context menus, for explorers, entity browsers and outlines.

npx prodular-ui add tree

Part of Prodular UI Pro. Preview and read the docs freely, install with a license. See pricing

Explorer

Icons, status metadata, a disabled node and a context menu on every row. Arrow keys move, Right and Left open and close, type to jump.

Production4
api-gatewayHealthy
billing-workerDegraded
Databases
ledger-primary
ledger-replica
legacy-cron

Ten thousand nodes

useTree flattens the visible rows, so a virtualizer renders only what is on screen. Keyboard focus follows into rows that render later.

Anatomy

<Tree  aria-label="Services"  items={items}  defaultExpanded={["prod"]}  onAction={(node) => open(node.id)}  contextMenu={(node) => <ContextMenuContent>…</ContextMenuContent>}/>

Guidance

Use it when

  • Hierarchies people browse and act on: services, folders, accounts, investigations.
  • contextMenu for actions on a node, so right click and the keyboard menu key both work.
  • useTree with a virtualizer above a few thousand visible rows.

Avoid

  • A Tree for one level of items. Use a list or Item group.
  • Navigation between pages. Use Sidebar or SettingsNav.
  • Putting buttons inside rows. Use contextMenu or the inspector for row actions.

Rules for AI agents

Published in llms-full.txt, the registry and the MCP server, so coding agents follow them when they build with this component.

  • Give Tree an aria-label or aria-labelledby.
  • Every node id must be unique in the whole tree. When one record appears in two branches, give each occurrence its own id, for example "case-12/entity-4", and map selection back to the record yourself.
  • Put plain text in textValue when label is not a string, so type-ahead and the accessible name work.
  • Do not build a tree from Collapsible and divs with role="treeitem". Use Tree or useTree, which handle roving focus, aria-level, aria-setsize and aria-posinset.
  • Use selectionMode="none" when rows only open things, and onAction for Enter and double click.
  • When rendering rows yourself, spread getItemProps(row) on each TreeItem and keep role="tree" on the container.

API

Tree

PropTypeDefaultDescription
itemsTreeNode[]Nodes: id, label, textValue, icon, meta, children, disabled.
expandedstring[]Open node ids. Use defaultExpanded for uncontrolled.
selectionMode"none" | "single" | "multiple""single"multiple sets aria-multiselectable; Cmd or Ctrl click and Space add to the selection.
selectedstring[]Selected node ids. Use defaultSelected for uncontrolled.
onAction(node: TreeNode) => voidEnter or double click.
contextMenu(node: TreeNode) => ReactNodeReturns a ContextMenuContent for the node.

useTree

PropTypeDefaultDescription
returns{ rows, getItemProps, toggle, select, focus, activeId }Flat visible rows and props for each row, for custom or virtualized rendering.

Installation

The Prodular UI CLI adds the source to components/ui with everything it depends on. In a project that already uses shadcn/ui, the shadcn CLI installs it from the Prodular registry too. See Installation for the first setup.

npx prodular-ui add tree# or, with the registry in components.jsonnpx shadcn@latest add @prodular/tree