alpha

SideNav

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

Example
RoutedSideNav.tsx
import {SideNav, SideNavItem, SideNavItemContent, SideNavItemLink} from '@react-spectrum/s2/SideNav';
import {RoutedSideNav} from './RoutedSideNav';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};

<RoutedSideNav defaultSelectedRoute="/guidelines">
  {({selectedRoute}) => (
    <SideNav
      aria-label="Files"
      selectedRoute={selectedRoute}
      styles={style({height: 240, width: 210})}
      defaultExpandedKeys={['guidelines', 'color']}>
      <SideNavItem href="/guidelines" id="guidelines" textValue="Guidelines">
        <SideNavItemContent><SideNavItemLink>Guidelines</SideNavItemLink></SideNavItemContent>
        <SideNavItem href="/style" id="style" textValue="Style">
          <SideNavItemContent><SideNavItemLink>Style</SideNavItemLink></SideNavItemContent>
        </SideNavItem>
        <SideNavItem href="/color" id="color" textValue="Color">
          <SideNavItemContent><SideNavItemLink>Color</SideNavItemLink></SideNavItemContent>
          <SideNavItem href="/background-layers" id="background-layers" textValue="Background Layers">
            <SideNavItemContent><SideNavItemLink>Background Layers</SideNavItemLink></SideNavItemContent>
          </SideNavItem>
        </SideNavItem>
      </SideNavItem>
      <SideNavItem id="support" textValue="Support">
        <SideNavItemContent>Support</SideNavItemContent>
        <SideNavItem href="/contact-us" id="contact-us" textValue="Contact Us">
          <SideNavItemContent><SideNavItemLink>Contact Us</SideNavItemLink></SideNavItemContent>
        </SideNavItem>
      </SideNavItem>
    </SideNav>
  )}
</RoutedSideNav>

Content

SideNav 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.

Documents
Project
Photos
Example
RoutedSideNav.tsx
import {SideNav, SideNavItem, SideNavItemContent, SideNavItemLink, Collection} from '@react-spectrum/s2/SideNav';
import {RoutedSideNav} from './RoutedSideNav';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};

<RoutedSideNav defaultSelectedRoute="/notes"> {({selectedRoute}) => ( <SideNav aria-label="Files" styles={style({height: 260, width: 210})} selectedRoute={selectedRoute} defaultExpandedKeys={[1, 2, 5]} items={items}> {function renderItem(item) { return (
<SideNavItem textValue={item.title} href={item.href}> <SideNavItemContent>{item.href ? <SideNavItemLink>{item.title}</SideNavItemLink> : item.title}</SideNavItemContent> {/* recursively render children */} {item.children && <Collection items={item.children}> {renderItem} </Collection>} </SideNavItem> ); }} </SideNav> )} </RoutedSideNav>

Slots

SideNavItemContent supports icons, Text, SideNavItemLink, ActionMenu, and ActionButtonGroup as children.

Documents
Project
Photos
Example
RoutedSideNav.tsx
import {SideNav, SideNavItem, SideNavItemContent, SideNavItemLink, Collection, Text} from '@react-spectrum/s2/SideNav';
import {RoutedSideNav} from './RoutedSideNav';
import {ActionMenu, MenuItem} from '@react-spectrum/s2/ActionMenu';
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';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};

<RoutedSideNav defaultSelectedRoute="/notes"> {({selectedRoute}) => ( <SideNav aria-label="Files" styles={style({height: 300, width: 210})} selectedRoute={selectedRoute} defaultExpandedKeys={[1, 2, 5]} items={items}> {function renderItem(item) { return (
<SideNavItem textValue={item.title} href={item.href}> <SideNavItemContent> { item.href ? <SideNavItemLink> {item.type === 'directory' ? <Folder /> : <File />} <Text>{item.title}</Text> </SideNavItemLink> : <> {item.type === 'directory' ? <Folder /> : <File />} <Text>{item.title}</Text> </> } <ActionMenu> <MenuItem> <Edit /> <Text>Edit</Text> </MenuItem> <MenuItem> <Delete /> <Text>Delete</Text> </MenuItem> </ActionMenu> </SideNavItemContent> {item.children && <Collection items={item.children}> {renderItem} </Collection>} </SideNavItem> ); }} </SideNav> )} </RoutedSideNav>

Routing

SideNavs do not support an uncontrolled selection state, you are responsible for managing it through the selectedRoute prop. You may wire this up to a router or other state management solution. The example below derives selectedRoute from the router's current location, and provides React Aria's RouterProvider with the router's navigate function so that clicking an item performs a client side navigation.

If a SideNavItem has an href, then you must pass a SideNavItemLink as a child of the SideNavItemContent.

See Routing setup in Getting Started for more info.

Example
router.tsx
import {SideNav, SideNavItem, SideNavItemContent, SideNavItemLink, Text} from '@react-spectrum/s2/SideNav';
import {RouterProvider} from 'react-aria-components';
import {MemoryRouter, useLocation, useNavigate} from './router';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import CCLibrary from '@react-spectrum/s2/icons/CCLibrary';
import Files from '@react-spectrum/s2/icons/Files';
import Images from '@react-spectrum/s2/icons/Images';

function FilesSideNav() {
  let navigate = useNavigate();
  let {pathname} = useLocation();

  return (
    <RouterProvider navigate={navigate}>
      <SideNav aria-label="Files" defaultExpandedKeys={['your-libraries']} selectedRoute={pathname} styles={style({height: 120, width: 210})}>
        <SideNavItem href="/files" textValue="Files">
          <SideNavItemContent>
            <SideNavItemLink>
              <Files />
              <Text>Files</Text>
            </SideNavItemLink>
          </SideNavItemContent>
        </SideNavItem>
        <SideNavItem id="your-libraries" href="/your-libraries" textValue="Your Libraries">
          <SideNavItemContent>
            <SideNavItemLink>
              <CCLibrary />
              <Text>Your Libraries</Text>
            </SideNavItemLink>
          </SideNavItemContent>
          <SideNavItem id="photos" href="/photos" textValue="Photos">
            <SideNavItemContent>
              <SideNavItemLink>
                <Images />
                <Text>Photos</Text>
              </SideNavItemLink>
            </SideNavItemContent>
          </SideNavItem>
        </SideNavItem>
      </SideNav>
    </RouterProvider>
  );
}

<MemoryRouter initialEntries={['/files']}>
  <FilesSideNav />
</MemoryRouter>

Sections

A SideNav can contain sections to group items together. They are non-collapsible and non-interactive.

Example
RoutedSideNav.tsx
import {SideNav, SideNavItem, SideNavItemContent, SideNavItemLink, SideNavSection, SideNavHeader, Text} from '@react-spectrum/s2/SideNav';
import {RoutedSideNav} from './RoutedSideNav';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import UserGroup from '@react-spectrum/s2/icons/UserGroup';
import CCLibrary from '@react-spectrum/s2/icons/CCLibrary';
import Files from '@react-spectrum/s2/icons/Files';
import Images from '@react-spectrum/s2/icons/Images';
import Animation from '@react-spectrum/s2/icons/Animation';
import Download from '@react-spectrum/s2/icons/Download';
import Apps from '@react-spectrum/s2/icons/Apps';

<RoutedSideNav defaultSelectedRoute="/files">
  {({selectedRoute}) => (
    <SideNav aria-label="Files" selectedRoute={selectedRoute} styles={style({height: 260, width: 210})}>
      <SideNavSection>
        <SideNavHeader>Favorites</SideNavHeader>
        <SideNavItem href="/applications" textValue="Applications">
          <SideNavItemContent>
            <SideNavItemLink>
              <Apps />
              <Text>Applications</Text>
            </SideNavItemLink>
          </SideNavItemContent>
        </SideNavItem>
        <SideNavItem href="/downloads" textValue="Downloads">
          <SideNavItemContent>
            <SideNavItemLink>
              <Download />
              <Text>Downloads</Text>
            </SideNavItemLink>
          </SideNavItemContent>
        </SideNavItem>
      </SideNavSection>
      <SideNavSection>
        <SideNavHeader>Workspaces</SideNavHeader>
        <SideNavItem href="/files" textValue="Files">
          <SideNavItemContent>
            <SideNavItemLink>
              <Files />
              <Text>Files</Text>
            </SideNavItemLink>
          </SideNavItemContent>
        </SideNavItem>
        <SideNavItem href="/your-libraries" textValue="Your Libraries">
          <SideNavItemContent>
            <SideNavItemLink>
              <CCLibrary />
              <Text>Your Libraries</Text>
            </SideNavItemLink>
          </SideNavItemContent>
          <SideNavItem href="/photos" textValue="Photos">
            <SideNavItemContent>
              <SideNavItemLink>
                <Images />
                <Text>Photos</Text>
              </SideNavItemLink>
            </SideNavItemContent>
          </SideNavItem>
        </SideNavItem>
        <SideNavItem href="/shared-with-you" id="shared-with-you" textValue="Shared with You">
          <SideNavItemContent>
            <SideNavItemLink>
              <UserGroup />
              <Text>Shared with You</Text>
            </SideNavItemLink>
          </SideNavItemContent>
          <SideNavItem href="/animations" textValue="Animations">
            <SideNavItemContent>
              <SideNavItemLink>
                <Animation />
                <Text>Animations</Text>
              </SideNavItemLink>
            </SideNavItemContent>
          </SideNavItem>
        </SideNavItem>
      </SideNavSection>
    </SideNav>
  )}
</RoutedSideNav>

API

<SideNav>
  <SideNavItem>
    <SideNavItemContent>
      <Icon />
      <Text />
      <ActionMenu /> or <ActionButtonGroup />
    </SideNavItemContent>
  </SideNavItem>
  <SideNavItem href>
    <SideNavItemContent>
      <SideNavItemLink>
        <Icon />
        <Text />
      </SideNavItemLink>
      <ActionMenu /> or <ActionButtonGroup />
    </SideNavItemContent>
  </SideNavItem>
</SideNav>

SideNav

NameType
selectedRoutestringnull

The route that is currently selected.

styles

Spectrum-defined styles, returned by the style() macro.

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.

SideNavItem

NameType
textValuestring

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

hasChildItemsboolean

Whether this item has children.

idKey

The unique id of the tree row.

childrenReactNode

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.

isDisabledboolean

Whether the item is disabled.

SideNavItemContent

NameType
childrenReactNode

Rendered contents of the side nav item or child items.

NameType
childrenReactNode

Rendered contents of the link.

SideNavSection

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.

SideNavHeader

NameType
childrenReactNode

The children of the component.