Treeview
A hierarchical list of expandable items with roving keyboard navigation. Supports single and multi-select, controlled and uncontrolled expansion and selection.
Features
Tree structure
Selection
State
Mounted collapse
Animation composition
Typeahead
Levels
State attributes
Installation
npm install @ariaui/treeview
Examples
Three playgrounds from the legacy doc: a deep hierarchy with chevrons, a repo-style file tree with Lucide icons, and a multi-select root for range and modifier selection.
Styling uses shared class strings in treeviewExampleTokens.ts; the base demo uses @heroicons/react/24/solid for chevrons.
Simple
Nested folders and leaves with chevron affordances.
No preview output yet.
Advanced
Selectable folders and files with checkboxes, icons, avatars, and row actions.
No preview output yet.
Advanced controlled
value and onValueChange drive the same advanced checkbox tree from React state.
No preview output yet.
Framer Motion
Slotted groups animated from collapsed height to measured content height.
No preview output yet.
Anatomy
import * as Treeview from "@ariaui/treeview";
export default function Example() {
return (
<Treeview.Root>
<Treeview.Item>
<Treeview.Group>
<Treeview.Item />
</Treeview.Group>
</Treeview.Item>
</Treeview.Root>
);
}
API Reference
Root
Context provider and state owner. Manages expansion, selection, and roving focus. Renders a `<div>` and forwards all div props.
| Prop | Type | Default |
|---|---|---|
expanded | string[] | — |
defaultExpanded | string[] | [] |
onExpandedChange | (expanded: string[]) => void | — |
value | string | string[] | — |
defaultValue | string | string[] | — |
onValueChange | (value: string | string[]) => void | — |
multiSelect | boolean | false |
disabled | boolean | false |
| Attribute | Values |
|---|---|
| role | 'tree' |
| aria-multiselectable | 'true' when `multiSelect` is enabled; omitted otherwise |
Item
A single node in the tree. Renders a `<div>`. Items without children are leaf nodes — they are never expandable and never receive `aria-expanded`. Children are hidden when the item is collapsed. Place `Treeview.Toggle` inside the label to expand or collapse without changing selection. Nesting `Item` elements inside a `Group` inside another `Item` creates deeper tree levels.
| Prop | Type | Default |
|---|---|---|
value* | string | — |
label | React.ReactNode | — |
disabled | boolean | false |
| Attribute | Values |
|---|---|
| role | 'treeitem' |
| aria-selected | 'true' when selected, 'false' otherwise |
| aria-expanded | 'true' | 'false' when item has children; omitted on leaf nodes |
| aria-disabled | 'true' when disabled; omitted otherwise |
| aria-level | integer depth — 1 at root, incremented per nested Group |
| data-state | 'selected' | 'unchecked' |
| data-expanded | 'true' | 'false' |
| data-selected | present when selected |
| data-disabled | present when disabled |
CheckboxItem
`Item` variant for checkable tree rows. It derives checked state from `Root` selection, toggles checked state on row click, Enter, or Space, and renders a `<div>` with `role="treeitem"`. Place `Treeview.Toggle` inside the label to expand or collapse without changing checked state.
| Prop | Type | Default |
|---|---|---|
value* | string | — |
label | React.ReactNode | — |
disabled | boolean | false |
| Attribute | Values |
|---|---|
| role | 'treeitem' |
| aria-checked | 'true' when all descendants are checked, 'mixed' when some descendants are checked, 'false' otherwise |
| aria-selected | 'true' when checked/selected, 'false' otherwise |
| aria-expanded | 'true' | 'false' when item has children; omitted on leaf nodes |
| data-state | 'checked' | 'unchecked' | 'indeterminate' |
| data-selected | present when checked/selected |
| data-disabled | present when disabled |
Toggle
Expansion control for parent item labels. Renders a `<span>`, forwards span props, and toggles the owning `Item` or `CheckboxItem` without changing selection or checked state.
| Attribute | Values |
|---|---|
| data-state | 'open' | 'closed' when the owning item has children |
| data-expanded | 'true' | 'false' when the owning item has children |
| data-disabled | present when the owning item is disabled |
Group
Container for child items. Increments `aria-level` for all descendant `Item` elements. Renders a `<div>` by default and can slot group props onto an animation element with `asChild`. Place a `Group` as a child of an `Item` to make that item expandable. Collapsed groups are hidden by default. Use `asChild` when an animation layer needs to measure collapsed content.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
| Attribute | Values |
|---|---|
| role | 'group' |
| data-expanded | 'true' | 'false' when `asChild` is enabled |
| data-treeview-collapsed-branch | present when an `asChild` group is collapsed |
| aria-hidden | 'true' when an `asChild` group is collapsed |
Keyboard
| Shortcut | Action |
|---|---|
| ↓ | Move focus to the next visible item. |
| ↑ | Move focus to the previous visible item. |
| → | On a collapsed item with children: expand it. On an expanded item or leaf: no-op. |
| ← | On an expanded item: collapse it. On a collapsed or leaf item: move focus to the parent. At root level: no-op. |
| Home | Move focus to the first visible item. |
| End | Move focus to the last visible item. |
| Enter | In single-select mode, expand or collapse parent items without selecting them; toggle selection on leaf items. In multi-select mode, add the focused item to the selection. |
| Space | In single-select mode, expand or collapse parent items without selecting them; toggle selection on leaf items. In multi-select mode, toggle the focused item. Shift+Space extends the range. |
| Ctrl+A | Select all visible items. Multi-select mode only. |
| A–Z/0–9 | Typeahead. Moves focus to the next item whose label starts with the typed character. Wraps; buffer clears after 500ms of inactivity. |
Accessibility
Treeview follows the WAI-ARIA APG Tree View pattern:
Rootrenders withrole="tree". WhenmultiSelectis enabled,aria-multiselectable="true"is set automatically so assistive tech announces the selection model.Each
Itemis arole="treeitem"witharia-levelreflecting its depth. Only items that have a childGroupreceivearia-expanded; leaf items omit the attribute per the APG.The tree uses roving tabindex — only the focused item has
tabIndex={0}. Arrow keys move focus,Tableaves the tree, and disabled items are skipped by navigation.aria-selectedis always present on every item to let screen readers announce selection changes consistently.aria-disabledis set on disabled items and on every item whenRootis disabled.Always provide an accessible name for the tree — pass
aria-labeloraria-labelledbyonRoot, especially when the tree has no visible heading.Use
labelprop (or children) to provide visible, descriptive text for each item. Avoid icon-only items without an accompanyingaria-label, and give expandable rows a visible expand/collapse affordance (e.g. a rotating chevron driven bydata-expanded).In single-select mode,
EnterandSpaceexpand or collapse parent items without selecting them; leaf items toggle selection. In multi-select mode,Enteradds the focused item to the selection,Spacetoggles it, andCtrl+Aselects every visible item — pair that with a visible selection count so users know what they have acted on.