TreeView
A tree view provides users with a way to navigate nested hierarchical information.
Content
TreeView
follows the Collection Components API, accepting both static and dynamic collections. This example shows a dynamic collection, passing a list of objects to the items
prop, and a recursive function to render the children.
import {TreeView, TreeViewItem, TreeViewItemContent, Collection} from '@react-spectrum/s2';
<TreeView
aria-label="Files"
defaultExpandedKeys={[1, 4]}
items={items}
selectionMode="multiple">
{function renderItem(item) {
return (
<TreeViewItem>
<TreeViewItemContent>{item.title}</TreeViewItemContent>
{/* recursively render children */}
<Collection items={item.children}>
{renderItem}
</Collection>
</TreeViewItem>
);
}}
</TreeView>
Slots
TreeViewItemContent
supports icons, Text
, ActionMenu, and ActionButtonGroup as children.
import {TreeView, TreeViewItem, TreeViewItemContent, Collection, ActionMenu, MenuItem, Text} from '@react-spectrum/s2';
import Folder from '@react-spectrum/s2/icons/Folder';
import File from '@react-spectrum/s2/icons/File';
import Edit from '@react-spectrum/s2/icons/Edit';
import Delete from '@react-spectrum/s2/icons/Delete';
<TreeView
aria-label="Files"
defaultExpandedKeys={[1, 4]}
items={items}
selectionMode="multiple">
{function renderItem(item) {
return (
<TreeViewItem>
<TreeViewItemContent>
{item.type === 'directory' ? <Folder /> : <File />}
<Text>{item.title}</Text>
<ActionMenu>
<MenuItem>
<Edit />
<Text>Edit</Text>
</MenuItem>
<MenuItem>
<Delete />
<Text>Delete</Text>
</MenuItem>
</ActionMenu>
</TreeViewItemContent>
<Collection items={item.children}>
{renderItem}
</Collection>
</TreeViewItem>
);
}}
</TreeView>
Asynchronous loading
Use renderEmptyState to display a spinner during initial load. To enable infinite scrolling, render a <TreeViewLoadMoreItem>
at the end of each <TreeViewItem>
.
import {TreeView, TreeViewItem, TreeViewItemContent, TreeViewLoadMoreItem, Collection} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useAsyncList} from 'react-stately';
interface Character {
name: string
}
function AsyncLoadingExample() {
return (
<TreeView
aria-label="Async loading tree"
styles={style({height: 300})}>
<TreeViewItem>
<TreeViewItemContent>Pokemon</TreeViewItemContent>
<Collection items={pokemonList.items}>
{(item) => (
<TreeViewItem id={item.name}>
<TreeViewItemContent>{item.name}</TreeViewItemContent>
</TreeViewItem>
)}
</Collection>
<TreeViewLoadMoreItem
onLoadMore={pokemonList.loadMore}
isLoading={pokemonList.loadingState === 'loadingMore'} />
</TreeViewItem>
<TreeViewItem>
<TreeViewItemContent>Star Wars</TreeViewItemContent>
<Collection items={starWarsList.items}>
{(item) => (
<TreeViewItem id={item.name}>
<TreeViewItemContent>{item.name}</TreeViewItemContent>
</TreeViewItem>
)}
</Collection>
<TreeViewLoadMoreItem
onLoadMore={starWarsList.loadMore}
isLoading={starWarsList.loadingState === 'loadingMore'} />
</TreeViewItem>
</TreeView>
);
}
Links
Use the href
prop on a <TreeItem>
to create a link. See the client side routing guide to learn how to integrate with your framework. See the selection guide for more details.
import {TreeView, TreeViewItem, TreeViewItemContent} from '@react-spectrum/s2';
<TreeView
aria-label="TreeView with links"
selectionMode="multiple"
defaultExpandedKeys={['bulbasaur', 'ivysaur']}>
<TreeViewItem
href="https://pokemondb.net/pokedex/bulbasaur"
target="_blank"
id="bulbasaur">
<TreeViewItemContent>Bulbasaur</TreeViewItemContent>
<TreeViewItem
id="ivysaur"
href="https://pokemondb.net/pokedex/ivysaur"
target="_blank">
<TreeViewItemContent>Ivysaur</TreeViewItemContent>
<TreeViewItem
id="venusaur"
title="Venusaur"
href="https://pokemondb.net/pokedex/venusaur"
target="_blank">
<TreeViewItemContent>Venusaur</TreeViewItemContent>
</TreeViewItem>
</TreeViewItem>
</TreeViewItem>
</TreeView>
Empty state
Use renderEmptyState
to render placeholder content when the tree is empty.
import {TreeView, IllustratedMessage, Heading, Content, Link} from '@react-spectrum/s2';
import FolderOpen from '@react-spectrum/s2/illustrations/linear/FolderOpen';
<TreeView
aria-label="Search results"
renderEmptyState={() => (
<IllustratedMessage>
<FolderOpen />
<Heading>No results</Heading>
<Content>Press <Link href="https://adobe.com">here</Link> for more info.</Content>
</IllustratedMessage>
)}>
{[]}
</TreeView>
Selection and actions
Use the selectionMode
prop to enable single or multiple selection. The selected items can be controlled via the selectedKeys
prop, matching the id
prop of the items. The onAction
event handles item actions. Items can be disabled with the isDisabled
prop. See the selection guide for more details.
Current selection:
API
<TreeView>
<TreeViewItem>
<TreeViewItemContent>
<Icon />
<Text />
<ActionMenu /> or <ActionButtonGroup />
</TreeViewItemContent>
<TreeViewItem>
{/* ... */}
</TreeViewItem>
<TreeViewLoadMoreItem />
</TreeViewItem>
</TreeView>
TreeView
Name | Type | |
---|---|---|
styles | StylesPropWithHeight | |
Spectrum-defined styles, returned by the style() macro. | ||
expandedKeys | Iterable | |
The currently expanded keys in the collection (controlled). | ||
defaultExpandedKeys | Iterable | |
The initial expanded keys in the collection (uncontrolled). | ||
isDetached | boolean | |
Whether the tree should be displayed with a detached style. | ||
isEmphasized | boolean | |
Whether the tree should be displayed with a emphasized style. | ||
children | ReactNode | | |
The contents of the collection. | ||
items | Iterable | |
Item objects in the collection. | ||
renderEmptyState |
| |
Provides content to display when there are no items in the list. | ||
dependencies | ReadonlyArray | |
Values that should invalidate the item cache when using dynamic collections. | ||
selectionMode | SelectionMode | |
The type of selection that is allowed in the collection. | ||
selectedKeys | 'all' | Iterable | |
The currently selected keys in the collection (controlled). | ||
defaultSelectedKeys | 'all' | Iterable | |
The initial selected keys in the collection (uncontrolled). | ||
onSelectionChange |
| |
Handler that is called when the selection changes. | ||
disabledKeys | Iterable | |
The item keys that are disabled. These items cannot be selected, focused, or otherwise interacted with. | ||
disabledBehavior | DisabledBehavior | |
Whether disabledKeys applies to all interactions, or only selection. | ||
disallowEmptySelection | boolean | |
Whether the collection allows empty selection. | ||
shouldSelectOnPressUp | boolean | |
Whether selection should occur on press up instead of press down. | ||
escapeKeyBehavior | 'clearSelection' | 'none' | |
Whether pressing the escape key should clear selection in the grid list or not. Most experiences should not modify this option as it eliminates a keyboard user's ability to easily clear selection. Only use if the escape key is being handled externally or should not trigger selection clearing contextually. | ||
TreeViewItem
Name | Type | |
---|---|---|
hasChildItems | boolean | |
Whether this item has children, even if not loaded yet. | ||
id | Key | |
The unique id of the tree row. | ||
value | T | |
The object value that this tree item represents. When using dynamic collections, this is set automatically. | ||
textValue | string | |
A string representation of the tree item's contents, used for features like typeahead. | ||
children | ReactNode | |
The content of the tree item along with any nested children. Supports static nested tree items or use of a Collection to dynamically render nested tree items. | ||
isDisabled | boolean | |
Whether the item is disabled. | ||
TreeViewItemContent
Name | Type | |
---|---|---|
children | ReactNode | |
Rendered contents of the tree item or child items. |
TreeViewLoadMoreItem
Name | Type | |
---|---|---|
loadingState | LoadingState | |
The current loading state of the TreeView or TreeView row. | ||
onLoadMore |
| |
Handler that is called when more items should be loaded, e.g. while scrolling near the bottom. |