Tree
Primitive

Tree

Headless hierarchical tree primitives for expandable one-dimensional navigation and selection.

Live behavior

Tree in motion

Interactive
Atom behavior · App-owned appearance
Preparing behavior…

Expand a branch and move through visible tree items.

waiting for input

When to Use

Use Tree for nested items that expand and collapse in one main column, such as a file browser or category picker. Use TreeGrid when every row also has several navigable columns, and use Accordion when sections contain general content instead of selectable items.

Features

The behavior Atom owns before your product adds appearance.

  • Implements WAI-ARIA tree, treeitem, and group roles.
  • Supports controlled and uncontrolled selection.
  • Supports controlled and uncontrolled expansion.
  • Supports single and multiple selection.
  • Supports typeahead, roving active item, disabled items, Field context, and form submission.
  • Supports nested groups with automatic levels.
  • Supports RTL-aware arrow-key navigation through dir and Direction.Provider.

Import

tsx
import { Tree } from "@flowstack-ui/atom";

Anatomy

tsx
<Tree.Root>
  <Tree.Item>
    <Tree.ItemText />
    <Tree.Group>
      <Tree.Item />
    </Tree.Group>
  </Tree.Item>
</Tree.Root>

API Reference

Root

Owns selection, expansion, visible-item navigation, typeahead, form values, and the single focus target that points to the active Item.

PropTypeDefault
childrenReactNode-
valuestring | string[] | null-
defaultValuestring | string[] | nullnull or []
onValueChange(value) => void-
expandedValuestring[]-
defaultExpandedValuestring[][]
onExpandedValueChange(value: string[]) => void-
onBlurFocusEventHandler<HTMLElement>-
onFocusFocusEventHandler<HTMLElement>-
onKeyDownKeyboardEventHandler<HTMLElement>-
multiplebooleanfalse
disabledbooleanField value
readOnlybooleanField value
requiredbooleanField value
invalidbooleanField value
orientation"vertical" | "horizontal""vertical"
dir"ltr" | "rtl"Direction.Provider
loopbooleanfalse
namestring-
formstring-
asChildbooleanfalse
renderRenderProp-
ARIA attributeValues
role"tree"
aria-activedescendantActive visible Item ID
aria-describedbyExplicit IDs or inherited Field description/error IDs
aria-disabledtrue when disabled
aria-invalidtrue when invalid
aria-multiselectabletrue in multiple mode
aria-orientationCurrent orientation
aria-readonlytrue when read-only
aria-requiredtrue when required
Data attributeValues
[data-slot]"tree"
[data-filled]Present when at least one Item is selected
[data-active]Present while an Item is active
[data-disabled]Present when disabled
[data-readonly]Present when read-only
[data-invalid]Present when invalid
[data-multiple]Present in multiple mode

Item

Registers one selectable node, its parent and level, and optional expansion state. It receives pointer selection while Root keeps DOM focus.

PropTypeDefault
valuestringrequired
labelstring-
disabledbooleanfalse
expandablebooleanfalse
asChildbooleanfalse
renderRenderProp-
ARIA attributeValues
role"treeitem"
aria-selectedCurrent selected state
aria-disabledtrue when Item or Root is disabled
aria-expandedExpansion state when the Item has children
aria-levelAutomatic nesting level
aria-labelledbyItemText ID when ItemText is mounted
Data attributeValues
[data-slot]"tree-item"
[data-state]"checked" | "unchecked"
[data-level]Automatic nesting level
[data-selected]Present when selected
[data-active]Present when active
[data-expandable]Present when expandable
[data-expanded]Present when expanded
[data-disabled]Present when disabled

ItemText

Registers the visible label used for Item naming and printable-character typeahead. It renders a span by default.

PropTypeDefault
asChildbooleanfalse
renderRenderProp-

ARIA: ItemText adds no ARIA attributes; Item references its generated ID.

Data attributeValues
[data-slot]"tree-item-text"

Group

Groups child Items, increments their automatic level, and follows its parent Item's expansion state.

PropTypeDefault
forceMountbooleanfalse
asChildbooleanfalse
renderRenderProp-
ARIA attributeValues
role"group"
aria-hiddentrue when force-mounted but collapsed
Data attributeValues
[data-slot]"tree-group"
[data-state]"open" | "closed"

Advanced compound parts can use the public Tree, Item, and Branch context hooks and providers.

Examples

Expandable Branch

tsx
import { Tree } from "@flowstack-ui/atom";

export default function ComponentTree() {
  return (
    <Tree.Root defaultExpandedValue={["components"]} aria-label="Components">
      <Tree.Item value="components" expandable>
        <Tree.ItemText>Components</Tree.ItemText>
        <Tree.Group><Tree.Item value="button">Button</Tree.Item></Tree.Group>
      </Tree.Item>
    </Tree.Root>
  );
}

Accessibility

Tree follows the WAI-ARIA tree view pattern with Root focus and aria-activedescendant. Provide an accessible name with a visible Field label, aria-label, or aria-labelledby. When focus first enters, the first enabled visible selected Item becomes active; if there is no such selection, the first enabled visible Item becomes active. Arrow navigation stops at the first and last visible Item by default; set loop to opt into wrapping. Printable-character typeahead matches enabled visible item text; a single-character search cycles forward from the current matching item, while multi-character buffers match exact prefixes.

KeyDescription
ArrowDown / ArrowUpMoves between visible items in vertical orientation
ArrowRight / ArrowLeftMoves between items in horizontal orientation, mirrored when dir="rtl"
Expand arrowExpands a collapsed item or moves to its first child: ArrowRight in LTR, ArrowLeft in RTL
Collapse arrowCollapses an expanded item or moves to its parent: ArrowLeft in LTR, ArrowRight in RTL
Home / EndMoves to first or last visible item
Enter / SpaceSelects the item and toggles expansion when expandable
Printable characterTypeahead search

Changelog

Unreleased

0.24.0

  • Added source-led Agent Knowledge for one-dimensional hierarchy selection, nested relationships, expansion and selection state, focus, typeahead, forms, direction, and virtualization boundaries.

0.17.1

  • Corrected initial focus so the first enabled visible selected Item becomes active before falling back to the first enabled visible Item.
  • Changed the default loop value to false so arrow navigation stops at the first and last visible Item; wrapping remains available with loop.

0.2.0

  • Fixed pointer targeting so whitespace inside nested groups does not reactivate or select the parent item.
  • Added Direction.Provider and dir support to mirror horizontal Tree navigation and expand/collapse arrow behavior in RTL.
  • Standardized Tree typeahead so a single-character search cycles from the current matching item while multi-character buffers still match exact prefixes.

0.1.0

  • Initial Atom release.