Tree View
A component that is used to show a tree hierarchy.
Anatomy
<TreeView.Root>
<TreeView.Label />
<TreeView.Tree>
<TreeView.NodeProvider>
<TreeView.Branch>
<TreeView.BranchControl>
<TreeView.BranchIndicator />
<TreeView.BranchText />
</TreeView.BranchControl>
<TreeView.BranchContent>
<TreeView.BranchIndentGuide />
<TreeView.Item>
<TreeView.ItemText />
</TreeView.Item>
</TreeView.BranchContent>
</TreeView.Branch>
</TreeView.NodeProvider>
</TreeView.Tree>
</TreeView.Root>
Examples
Controlled Expanded
Pass the expandedValue and onExpandedChange props to the TreeView.Root component to control the expanded state of
the tree view.
Controlled Selection
Pass the selectedValue and onSelectionChange props to the TreeView.Root component to control the selected state of
the tree view.
Root Provider
An alternative way to control the tree view is to use the RootProvider component and the useTreeView hook. This way
you can access the state and methods from outside the component.
Lazy Loading
Lazy loading is a feature that allows the tree view to load children of a node on demand (or async). This helps to improve the initial load time and memory usage.
To use this, you need to provide the following:
loadChildren— A function that is used to load the children of a node.onLoadChildrenComplete— A callback that is called when the children of a node are loaded. Used to update the tree collection.childrenCount— A number that indicates the number of children of a branch node.
Lazy Mount
Lazy mounting is a feature that allows the content of a tree view to be rendered only when it is expanded. This is
useful for performance optimization, especially when tree content is large or complex. To enable lazy mounting, use the
lazyMount prop on the TreeView.Root component.
In addition, the unmountOnExit prop can be used in conjunction with lazyMount to unmount the tree view content when
branches are collapsed, freeing up resources. The next time a branch is expanded, its content will be re-rendered.
Filtering
Filtering is useful when you have a large tree and you want to filter the nodes to only show the ones that match the
search query. Here's an example that composes the filter method from the TreeCollection and useFilter hook to
filter the nodes.
Links
Tree items can be rendered as links to another page or website. This could be useful for documentation sites.
Here's an example that modifies the tree collection to represent an hierarchical link structure. It uses the asChild
prop to render the tree items as links, passing the href prop to a <a> element.
Virtualized
For large tree views with thousands of nodes, virtualization can significantly improve performance by only rendering visible nodes.
Key implementation details:
- Use
useTreeViewhook withTreeView.RootProviderfor programmatic control - Pass
scrollToIndexFnto enable keyboard navigation within the virtualized list - Use
getVisibleNodes()to get the flattened list of currently visible nodes
Checkbox Tree
Use the defaultCheckedValue prop to enable checkbox selection mode. This allows users to select multiple nodes with
checkboxes, including parent-child selection relationships.
Expand and Collapse All
Use the expand() and collapse() methods from the tree view context to programmatically expand or collapse all
branches.
Mutation
Use the collection's remove() and replace() methods to dynamically add and remove nodes from the tree. This is
useful for building file explorer interfaces where users can create and delete files.
Rename Node
Enable inline renaming of nodes using the canRename prop and onRenameComplete callback. Press F2 to
activate rename mode on the focused node.
Guides
Type Safety
The TreeView.RootComponent type enables you to create typed wrapper components that maintain full type safety for tree
nodes.
import { TreeView as ArkTreeView } from '@ark-ui/react/tree-view'
const TreeView: ArkTreeView.RootComponent = (props) => {
return <ArkTreeView.Root {...props}>{/* ... */}</ArkTreeView.Root>
}
Use the wrapper with full type inference on onSelectionChange and other callbacks:
const App = () => {
const collection = createTreeCollection({
initialItems: [
{ id: '1', label: 'React', children: [] },
{ id: '2', label: 'Vue', children: [] },
],
})
return (
<TreeView
collection={collection}
onSelectionChange={(e) => {
// e.items is typed as Array<{ id: string, label: string, children: [] }>
console.log(e.items)
}}
>
{/* ... */}
</TreeView>
)
}
API Reference
Props
Root
| Prop | Default | Type |
|---|---|---|
collection | TreeCollection<T>The collection of tree nodes | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
canRename | (node: T, indexPath: IndexPath) => booleanFunction to determine if a node can be renamed | |
checkedValue | string[]The controlled checked node value | |
defaultCheckedValue | string[]The initial checked node value when rendered. Use when you don't need to control the checked node value. | |
defaultExpandedValue | string[]The initial expanded node ids when rendered. Use when you don't need to control the expanded node value. | |
defaultFocusedValue | stringThe initial focused node value when rendered. Use when you don't need to control the focused node value. | |
defaultSelectedValue | string[]The initial selected node value when rendered. Use when you don't need to control the selected node value. | |
expandedValue | string[]The controlled expanded node ids | |
expandOnClick | true | booleanWhether clicking on a branch should open it or not |
focusedValue | stringThe value of the focused node | |
ids | Partial<{ root: string; tree: string; label: string; node: (value: string) => string }>The ids of the tree elements. Useful for composition. | |
lazyMount | false | booleanWhether to enable lazy mounting |
loadChildren | (details: LoadChildrenDetails<T>) => Promise<T[]>Function to load children for a node asynchronously. When provided, branches will wait for this promise to resolve before expanding. | |
onBeforeRename | (details: RenameCompleteDetails) => booleanCalled before a rename is completed. Return false to prevent the rename. | |
onCheckedChange | (details: CheckedChangeDetails) => voidCalled when the checked value changes | |
onExpandedChange | (details: ExpandedChangeDetails<T>) => voidCalled when the tree is opened or closed | |
onFocusChange | (details: FocusChangeDetails<T>) => voidCalled when the focused node changes | |
onLoadChildrenComplete | (details: LoadChildrenCompleteDetails<T>) => voidCalled when a node finishes loading children | |
onLoadChildrenError | (details: LoadChildrenErrorDetails<T>) => voidCalled when loading children fails for one or more nodes | |
onRenameComplete | (details: RenameCompleteDetails) => voidCalled when a node label rename is completed | |
onRenameStart | (details: RenameStartDetails<T>) => voidCalled when a node starts being renamed | |
onSelectionChange | (details: SelectionChangeDetails<T>) => voidCalled when the selection changes | |
selectedValue | string[]The controlled selected node value | |
selectionMode | 'single' | 'multiple' | 'single'Whether the tree supports multiple selection - "single": only one node can be selected - "multiple": multiple nodes can be selected |
typeahead | true | booleanWhether the tree supports typeahead search |
unmountOnExit | false | booleanWhether to unmount on exit. |
BranchContent
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | tree-view |
[data-part] | branch-content |
[data-state] | "open" | "closed" |
[data-depth] | The depth of the item |
[data-path] | The path of the item |
[data-value] | The value of the item |
BranchControl
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | tree-view |
[data-part] | branch-control |
[data-path] | The path of the item |
[data-state] | "open" | "closed" |
[data-disabled] | Present when disabled |
[data-selected] | Present when selected |
[data-focus] | Present when focused |
[data-renaming] | |
[data-value] | The value of the item |
[data-depth] | The depth of the item |
[data-loading] | Present when loading |
BranchIndentGuide
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | tree-view |
[data-part] | branch-indent-guide |
[data-depth] | The depth of the item |
BranchIndicator
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | tree-view |
[data-part] | branch-indicator |
[data-state] | "open" | "closed" |
[data-disabled] | Present when disabled |
[data-selected] | Present when selected |
[data-focus] | Present when focused |
[data-loading] | Present when loading |
Branch
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | tree-view |
[data-part] | branch |
[data-depth] | The depth of the item |
[data-branch] | |
[data-value] | The value of the item |
[data-path] | The path of the item |
[data-selected] | Present when selected |
[data-state] | "open" | "closed" |
[data-disabled] | Present when disabled |
[data-loading] | Present when loading |
| CSS Variable | Description |
|---|---|
--depth | The depth value for the Branch |
BranchText
Renders a <span> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | tree-view |
[data-part] | branch-text |
[data-disabled] | Present when disabled |
[data-state] | "open" | "closed" |
[data-loading] | Present when loading |
BranchTrigger
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | tree-view |
[data-part] | branch-trigger |
[data-disabled] | Present when disabled |
[data-state] | "open" | "closed" |
[data-value] | The value of the item |
[data-loading] | Present when loading |
ItemIndicator
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | tree-view |
[data-part] | item-indicator |
[data-disabled] | Present when disabled |
[data-selected] | Present when selected |
[data-focus] | Present when focused |
Item
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | tree-view |
[data-part] | item |
[data-path] | The path of the item |
[data-value] | The value of the item |
[data-focus] | Present when focused |
[data-selected] | Present when selected |
[data-disabled] | Present when disabled |
[data-renaming] | |
[data-depth] | The depth of the item |
| CSS Variable | Description |
|---|---|
--depth | The depth value for the Item |
ItemText
Renders a <span> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | tree-view |
[data-part] | item-text |
[data-disabled] | Present when disabled |
[data-selected] | Present when selected |
[data-focus] | Present when focused |
Label
Renders a <h2> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
NodeCheckboxIndicator
| Prop | Default | Type |
|---|---|---|
fallback | string | number | bigint | boolean | ReactElement<unknown, string | JSXElementConstructor<any>> | Iterable<ReactNode> | ReactPortal | Promise<...> | |
indeterminate | string | number | bigint | boolean | ReactElement<unknown, string | JSXElementConstructor<any>> | Iterable<ReactNode> | ReactPortal | Promise<...> |
NodeCheckbox
Renders a <span> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | tree-view |
[data-part] | node-checkbox |
[data-state] | "checked" | "unchecked" | "indeterminate" |
[data-disabled] | Present when disabled |
NodeProvider
| Prop | Default | Type |
|---|---|---|
indexPath | number[]The index path of the tree node | |
node | NonNullable<T>The tree node |
NodeRenameInput
Renders a <input> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
RootProvider
| Prop | Default | Type |
|---|---|---|
value | UseTreeViewReturn<T> | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
lazyMount | false | booleanWhether to enable lazy mounting |
unmountOnExit | false | booleanWhether to unmount on exit. |
Tree
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Context
API
| Property | Type |
|---|---|
collection | TreeCollection<V>The tree collection data |
expandedValue | string[]The value of the expanded nodes. |
setExpandedValue | (value: string[]) => voidSets the expanded value |
selectedValue | string[]The value of the selected nodes. |
setSelectedValue | (value: string[]) => voidSets the selected value |
checkedValue | string[]The value of the checked nodes |
toggleChecked | (value: string, isBranch: boolean) => voidToggles the checked value of a node |
setChecked | (value: string[]) => voidSets the checked value of a node |
clearChecked | VoidFunctionClears the checked value of a node |
getCheckedMap | () => CheckedValueMapReturns the checked details of branch and leaf nodes |
getVisibleNodes | () => V[]Returns the visible nodes as a flat array of nodes and their index path |
expand | (value?: string[]) => voidFunction to expand nodes. If no value is provided, all nodes will be expanded |
collapse | (value?: string[]) => voidFunction to collapse nodes If no value is provided, all nodes will be collapsed |
select | (value?: string[]) => voidFunction to select nodes If no value is provided, all nodes will be selected |
deselect | (value?: string[]) => voidFunction to deselect nodes If no value is provided, all nodes will be deselected |
focus | (value: string) => voidFunction to focus a node by value |
selectParent | (value: string) => voidFunction to select the parent node of the focused node |
expandParent | (value: string) => voidFunction to expand the parent node of the focused node |
startRenaming | (value: string) => voidFunction to start renaming a node by value |
submitRenaming | (value: string, label: string) => voidFunction to submit the rename and update the node label |
cancelRenaming | () => voidFunction to cancel renaming without changes |
Accessibility
Complies with the Tree View WAI-ARIA design pattern.
Keyboard Support
| Key | Description |
|---|---|
Tab | Moves focus to the tree view, placing the first tree view item in focus. |
EnterSpace | Selects the item or branch node |
ArrowDown | Moves focus to the next node |
ArrowUp | Moves focus to the previous node |
ArrowRight | When focus is on a closed branch node, opens the branch. When focus is on an open branch node, moves focus to the first item node. |
ArrowLeft | When focus is on an open branch node, closes the node. When focus is on an item or branch node, moves focus to its parent branch node. |
Home | Moves focus to first node without opening or closing a node. |
End | Moves focus to the last node that can be focused without expanding any nodes that are closed. |
a-zA-Z | Focus moves to the next node with a name that starts with the typed character. The search logic ignores nodes that are descendants of closed branch. |
* | Expands all sibling nodes that are at the same depth as the focused node. |
Shift + ArrowDown | Moves focus to and toggles the selection state of the next node. |
Shift + ArrowUp | Moves focus to and toggles the selection state of the previous node. |
Ctrl + A | Selects all nodes in the tree. If all nodes are selected, unselects all nodes. |