alpha

NavigationTree

A NavigationTree provides users with a way to navigate a nested, hierarchical set of links.

Theme 
Example
NavigationTree.tsx
NavigationTree.css
RoutedNavigationTree.tsx
import {NavigationTree, NavigationTreeItem, NavigationTreeItemContent, NavigationTreeItemLink} from './NavigationTree';
import {Button} from './Button';
import {MoreHorizontal} from 'lucide-react';
import {RoutedNavigationTree} from './RoutedNavigationTree';

<RoutedNavigationTree defaultSelectedRoute="/photos">
  {({selectedRoute}) => (
    <NavigationTree aria-label="Files" selectedRoute={selectedRoute} defaultExpandedKeys={['files']}>
      <NavigationTreeItem id="home" href="/home" textValue="Home">
        <NavigationTreeItemContent>
          <NavigationTreeItemLink>Home</NavigationTreeItemLink>
          <Button variant="quiet" aria-label="More options"><MoreHorizontal size={16} aria-hidden /></Button>
        </NavigationTreeItemContent>
      </NavigationTreeItem>
      <NavigationTreeItem id="files" href="/files" textValue="Files">
        <NavigationTreeItemContent>
          <NavigationTreeItemLink>Files</NavigationTreeItemLink>
          <Button variant="quiet" aria-label="More options"><MoreHorizontal size={16} aria-hidden /></Button>
        </NavigationTreeItemContent>
        <NavigationTreeItem id="photos" href="/photos" textValue="Photos">
          <NavigationTreeItemContent>
            <NavigationTreeItemLink>Photos</NavigationTreeItemLink>
            <Button variant="quiet" aria-label="More options"><MoreHorizontal size={16} aria-hidden /></Button>
          </NavigationTreeItemContent>
        </NavigationTreeItem>
        <NavigationTreeItem id="videos" href="/videos" textValue="Videos">
          <NavigationTreeItemContent>
            <NavigationTreeItemLink>Videos</NavigationTreeItemLink>
            <Button variant="quiet" aria-label="More options"><MoreHorizontal size={16} aria-hidden /></Button>
          </NavigationTreeItemContent>
        </NavigationTreeItem>
      </NavigationTreeItem>
      <NavigationTreeItem id="shared" textValue="Shared">
        <NavigationTreeItemContent>
          <NavigationTreeItemLink>Shared</NavigationTreeItemLink>
          <Button variant="quiet" aria-label="More options"><MoreHorizontal size={16} aria-hidden /></Button>
        </NavigationTreeItemContent>
        <NavigationTreeItem id="food" href="/food" textValue="Food">
          <NavigationTreeItemContent>
            <NavigationTreeItemLink>Food</NavigationTreeItemLink>
            <Button variant="quiet" aria-label="More options"><MoreHorizontal size={16} aria-hidden /></Button>
          </NavigationTreeItemContent>
        </NavigationTreeItem>
        <NavigationTreeItem id="drinks" href="/drinks" textValue="Drinks">
          <NavigationTreeItemContent>
            <NavigationTreeItemLink>Drinks</NavigationTreeItemLink>
            <Button variant="quiet" aria-label="More options"><MoreHorizontal size={16} aria-hidden /></Button>
          </NavigationTreeItemContent>
        </NavigationTreeItem>
      </NavigationTreeItem>
    </NavigationTree>
  )}
</RoutedNavigationTree>

Content

NavigationTree follows the Collection Components API, accepting both static and dynamic collections. The example above shows a static collection. This example shows a dynamic collection, passing a list of objects to the items prop and a function to render the children.

Example
RoutedNavigationTree.tsx
import {NavigationTree, NavigationTreeItem, NavigationTreeItemContent, NavigationTreeItemLink} from './NavigationTree';
import {RoutedNavigationTree} from './RoutedNavigationTree';

function Example() {
  let items = [
    {id: 'overview', url: '/overview', label: 'Overview'},
    {id: 'reports', url: '/reports', label: 'Reports'},
    {id: 'settings', url: '/settings', label: 'Settings'}
  ];

  return (
    <RoutedNavigationTree defaultSelectedRoute="/reports">
      {({selectedRoute}) => (
        <NavigationTree aria-label="Sections" items={items} selectedRoute={selectedRoute}>
          {item => (
            <NavigationTreeItem href={item.url} textValue={item.label}>
              <NavigationTreeItemContent>
                <NavigationTreeItemLink>{item.label}</NavigationTreeItemLink>
              </NavigationTreeItemContent>
            </NavigationTreeItem>
          )}
        </NavigationTree>
      )}
    </RoutedNavigationTree>
  );
}

Sections

Use NavigationTreeSection to group related items, with an optional NavigationTreeHeader to label each group. Sections without a header must have an aria-label.

Personal
Projects
Example
RoutedNavigationTree.tsx
import {NavigationTree, NavigationTreeItem, NavigationTreeItemContent, NavigationTreeItemLink, NavigationTreeSection, NavigationTreeHeader} from './NavigationTree';
import {RoutedNavigationTree} from './RoutedNavigationTree';

<RoutedNavigationTree defaultSelectedRoute="/projects/apollo">
  {({selectedRoute}) => (
    <NavigationTree aria-label="Workspace" selectedRoute={selectedRoute}>
      <NavigationTreeSection>
        <NavigationTreeHeader>Personal</NavigationTreeHeader>
        <NavigationTreeItem href="/home" textValue="Home">
          <NavigationTreeItemContent>
            <NavigationTreeItemLink>Home</NavigationTreeItemLink>
          </NavigationTreeItemContent>
        </NavigationTreeItem>
        <NavigationTreeItem href="/starred" textValue="Starred">
          <NavigationTreeItemContent>
            <NavigationTreeItemLink>Starred</NavigationTreeItemLink>
          </NavigationTreeItemContent>
        </NavigationTreeItem>
      </NavigationTreeSection>
      <NavigationTreeSection>
        <NavigationTreeHeader>Projects</NavigationTreeHeader>
        <NavigationTreeItem href="/projects/apollo" textValue="Apollo">
          <NavigationTreeItemContent>
            <NavigationTreeItemLink>Apollo</NavigationTreeItemLink>
          </NavigationTreeItemContent>
        </NavigationTreeItem>
        <NavigationTreeItem href="/projects/gemini" textValue="Gemini">
          <NavigationTreeItemContent>
            <NavigationTreeItemLink>Gemini</NavigationTreeItemLink>
          </NavigationTreeItemContent>
        </NavigationTreeItem>
      </NavigationTreeSection>
    </NavigationTree>
  )}
</RoutedNavigationTree>

Current route

Each NavigationTreeItem accepts an href. Set the selectedRoute prop on the NavigationTree to the current page's path, and the item whose href matches is marked with aria-current="page" (and a data-current attribute for styling).

Combine NavigationTree with a client side router by wrapping your app in a RouterProvider so that activating a link updates the route. Then set selectedRoute. In this example the router navigation is stored in local state to show the current route updating as you activate links.

import {NavigationTree, NavigationTreeItem, NavigationTreeItemContent, NavigationTreeItemLink} from './NavigationTree';
import {RouterProvider} from 'react-aria-components';
import {useState} from 'react';

function Example() {
  let [route, setRoute] = useState('/inbox');
  return (
    <RouterProvider navigate={setRoute}>
      <NavigationTree aria-label="Mail" selectedRoute={route}>
        <NavigationTreeItem href="/inbox" textValue="Inbox">
          <NavigationTreeItemContent>
            <NavigationTreeItemLink>Inbox</NavigationTreeItemLink>
          </NavigationTreeItemContent>
        </NavigationTreeItem>
        <NavigationTreeItem href="/drafts" textValue="Drafts">
          <NavigationTreeItemContent>
            <NavigationTreeItemLink>Drafts</NavigationTreeItemLink>
          </NavigationTreeItemContent>
        </NavigationTreeItem>
        <NavigationTreeItem href="/sent" textValue="Sent">
          <NavigationTreeItemContent>
            <NavigationTreeItemLink>Sent</NavigationTreeItemLink>
          </NavigationTreeItemContent>
        </NavigationTreeItem>
      </NavigationTree>
    </RouterProvider>
  );
}

API

PersonalHomeApolloPhotosVideosNavigationTreeNavigationTreeSectionNavigationTreeHeaderLinkNavigationTreeItemButton slot="chevron"
<NavigationTree>
  <NavigationTreeSection>
    <NavigationTreeHeader />
    <NavigationTreeItem>
      <NavigationTreeItemContent>
        <Link />
        <Button slot="chevron" />
      </NavigationTreeItemContent>
    </NavigationTreeItem>
  </NavigationTreeSection>
</NavigationTree>

A NavigationTree provides users with a way to navigate a nested, hierarchical set of links.

NameType
selectedRoutestringnull

The route that is currently selected, matched against each item's href.

expandedKeysIterable<Key>

The currently expanded keys in the collection (controlled).

defaultExpandedKeysIterable<Key>

The initial expanded keys in the collection (uncontrolled).

childrenReactNode(item: T) => ReactNode

The contents of the collection.

itemsIterable<T>

Item objects in the collection.

dependenciesReadonlyArray<any>

Values that should invalidate the item cache when using dynamic collections.

disabledKeysIterable<Key>

The item keys that are disabled. These items cannot be selected, focused, or otherwise interacted with.

Default className: react-aria-NavigationTree

Render PropCSS Selector
isEmptyCSS Selector: [data-empty]
Whether the tree has no items and should display its empty state.
isFocusedCSS Selector: [data-focused]
Whether the tree is currently focused.
isFocusVisibleCSS Selector: [data-focus-visible]
Whether the tree is currently keyboard focused.
stateCSS Selector:
State of the tree.

A NavigationTreeItem represents an individual item in a NavigationTree.

NameType
childrenReactNode

The content of the side nav item along with any nested children. Supports static nested side nav items or use of a Collection to dynamically render nested side nav items.

idKey

The unique id of the tree row.

textValuestring

A string representation of the tree item's contents, used for features like typeahead.

isDisabledboolean

Whether the item is disabled.

hasChildItemsboolean

Whether this item has children, even if not loaded yet.

Default className: react-aria-NavigationTreeItem

Render PropCSS Selector
isCurrentCSS Selector: [data-current]
Whether this item is the current route (its href matches the NavigationTree's selectedRoute).
isCurrentAncestorCSS Selector: [data-current-ancestor]
Whether this item is an ancestor of the current-route item (at any level, regardless of whether it is expanded or collapsed).
isExpandedCSS Selector: [data-expanded]
Whether the tree item is expanded.
hasChildItemsCSS Selector: [data-has-child-items]
Whether the tree item has child tree items.
levelCSS Selector: [data-level="number"]
What level the tree item has within the tree.
isFocusVisibleWithinCSS Selector: [data-focus-visible-within]
Whether the tree item's children have keyboard focus.
stateCSS Selector:
The state of the tree.
idCSS Selector:
The unique id of the tree row.
isHoveredCSS Selector: [data-hovered]
Whether the item is currently hovered with a mouse.
isPressedCSS Selector: [data-pressed]
Whether the item is currently in a pressed state.
isSelectedCSS Selector: [data-selected]
Whether the item is currently selected.
isFocusedCSS Selector: [data-focused]
Whether the item is currently focused.
isFocusVisibleCSS Selector: [data-focus-visible]
Whether the item is currently keyboard focused.
isDisabledCSS Selector: [data-disabled]
Whether the item is non-interactive, i.e. both selection and actions are disabled and the item may not be focused. Dependent on disabledKeys and disabledBehavior.
selectionModeCSS Selector: [data-selection-mode="single | multiple"]
The type of selection that is allowed in the collection.
selectionBehaviorCSS Selector:
The selection behavior for the collection.
NameType
children<>

The children of the component. A function may be provided to alter the children based on component state.

A NavigationTreeSection represents a section within a NavigationTree.

NameType
idKey

The unique id of the section.

childrenReactNode(item: T) => ReactElement

Static child items or a function to render children.

itemsIterable<T>

Item objects in the section.

dependenciesReadonlyArray<any>

Values that should invalidate the item cache when using dynamic collections.

A NavigationTreeHeader renders the header of a NavigationTreeSection.

NameType
childrenReactNode

The children of the component.