OPERATOR

TreeView

Hierarchy

Relays
Relay Alpha
Relay Bravo
Services

Items have globally unique, stable string id, label, optional children, and optional disabled. Keep IDs stable when records or labels update to preserve selection and focus. Selection can be controlled with selectedId and onSelectionChange, while expansion uses expandedIds and onExpandedChange. Use defaultExpandedIds for initial local expansion.

The installed React Aria tree uses treegrid row semantics. Up/Down moves between visible rows. Right expands a branch or enters it; Left collapses or returns to its parent. Home/End moves to first/last visible row. Typeahead uses supplied labels. Selection follows keyboard navigation; Enter/Space selects without clearing the current selection. Programmatic selectedId={null} can clear it.

Deep hierarchies

Labels wrap and keep a readable width of about ten characters. When a hierarchy is so deep that its rows need more width than the tree has, the rows run on and the tree scrolls sideways inside itself; the page never widens. Moving focus with the arrow keys brings the focused row's label into view.

Site 1
Area 2
Unit 3
System 4
Loop 5
Skid 6
Equipment 7
Assembly 8
Component 9
Pressure sensor PT-104

Disabled

Relays
Relay Alpha

Props

PROPTYPEDEFAULTREQUIRED
itemsarray—yes
labelstring"Navigation"no
selectedId

Controlled selected string ID; null clears the selection.

string—no
onSelectionChange

(id: string | null) => void. Navigation may select as focus moves.

function—no
expandedIds

Controlled expanded string IDs.

array—no
defaultExpandedIds

Initial expanded IDs for local state.

array—no
onExpandedChange

(ids: string[]) => void.

function—no
disabledbooleanfalseno
emptyMessagestring"No items."no

Accessibility

  • React Aria handles focus movement, selection, expansion, and typeahead.
  • Each expandable row has an explicitly named chevron control.
  • Rows and chevrons have visible keyboard focus and at least 24px targets.
  • In forced-colors mode the selected row is outlined in the Highlight system color and keyboard focus is a system-color outline.
  • Disabled items suppress selection and expansion; data labels preserve their casing.

Manifest entry

<TreeView label="Assets" items={groups} selectedId={selectedId} onSelectionChange={setSelectedId} />
View agent manifest
{
  "description": "React Aria hierarchical treegrid with stable string IDs, single selection, expansion, arrow-key navigation, and typeahead. Labels wrap and keep a readable width; a hierarchy deeper than the tree is wide scrolls sideways inside the tree, and keyboard focus brings the focused row's label into view. Accepts id, style, aria-labelledby, aria-describedby and data attributes.",
  "props": {
    "items": {
      "type": "array",
      "items": {
        "id": "unique string",
        "label": "string",
        "children": "optional recursive TreeViewItem[]",
        "disabled": "optional boolean"
      },
      "required": true
    },
    "label": {
      "type": "string",
      "default": "Navigation"
    },
    "selectedId": {
      "type": "string",
      "description": "Controlled selected string ID; null clears the selection."
    },
    "onSelectionChange": {
      "type": "function",
      "description": "(id: string | null) => void. Navigation may select as focus moves."
    },
    "expandedIds": {
      "type": "array",
      "description": "Controlled expanded string IDs."
    },
    "defaultExpandedIds": {
      "type": "array",
      "description": "Initial expanded IDs for local state."
    },
    "onExpandedChange": {
      "type": "function",
      "description": "(ids: string[]) => void."
    },
    "disabled": {
      "type": "boolean",
      "default": false
    },
    "emptyMessage": {
      "type": "string",
      "default": "No items."
    }
  },
  "composable_with": [
    "AppShell",
    "Inspector"
  ],
  "never_inside": [
    "Button"
  ],
  "example": "<TreeView label=\"Assets\" items={groups} selectedId={selectedId} onSelectionChange={setSelectedId} />"
}

On this page