Skip to Content

Side navigation

A left side expandable / collapsable navigation menu.

import * as React from 'react';
import { SidenavButton, SideNavigation } from '@itwin/itwinui-react';
import {
  SvgHome,
  SvgFlag,
  SvgFolderOpened,
  SvgSettings,
} from '@itwin/itwinui-icons-react';

export default () => {
  const [activeIndex, setActiveIndex] = React.useState(0);

  return (
    <SideNavigation
      items={[
        <SidenavButton
          startIcon={<SvgHome />}
          key={0}
          isActive={activeIndex === 0}
          onClick={() => setActiveIndex(0)}
        >
          Home
        </SidenavButton>,
        <SidenavButton
          startIcon={<SvgFlag />}
          key={1}
          isActive={activeIndex === 1}
          onClick={() => setActiveIndex(1)}
        >
          Issues
        </SidenavButton>,
        <SidenavButton startIcon={<SvgFolderOpened />} key={2} disabled>
          Documents
        </SidenavButton>,
      ]}
      secondaryItems={[
        <SidenavButton
          startIcon={<SvgSettings />}
          key={3}
          isActive={activeIndex === 3}
          onClick={() => setActiveIndex(3)}
        >
          Settings
        </SidenavButton>,
      ]}
    />
  );
};

The side navigation is a way for the user to quickly switch between different workflows within a product. The menu items listed may change from user to user depending on their job function. The side navigation can be viewed in a minimal way using just icons or can be expanded to show labels. Menu items can open a single page or can expand into a submenu.

Variants

Basic

The basic variant contains interactive buttons with associated icons. An expander button can be used to collapse and expand the side navigation panel. When the side panel is expanded, the icon is accompanied by a right-aligned label. When collapsed, a tooltip with the corresponding label pops up on-hover of a menu item. The expander button is placed at the top of the panel by default, or it can be at the bottom or hidden via the use of expanderPlacement property.

import * as React from 'react';
import { SidenavButton, SideNavigation } from '@itwin/itwinui-react';
import {
  SvgHome,
  SvgFlag,
  SvgFolderOpened,
  SvgSettings,
} from '@itwin/itwinui-icons-react';

export default () => {
  return (
    <SideNavigation
      items={[
        <SidenavButton startIcon={<SvgHome />} key={0}>
          Home
        </SidenavButton>,
        <SidenavButton startIcon={<SvgFlag />} key={1}>
          Issues
        </SidenavButton>,
        <SidenavButton startIcon={<SvgFolderOpened />} key={2} disabled>
          Documents
        </SidenavButton>,
      ]}
      secondaryItems={[
        <SidenavButton startIcon={<SvgSettings />} key={3}>
          Settings
        </SidenavButton>,
      ]}
    />
  );
};

Active item

Active menu item allows the currently selected item to be highlighted via the key and activeIndex property which specify the index to highlight for better user feedback.

import * as React from 'react';
import { SidenavButton, SideNavigation } from '@itwin/itwinui-react';
import { SvgPlaceholder, SvgSettings } from '@itwin/itwinui-icons-react';

export default () => {
  const [activeIndex, setActiveIndex] = React.useState(0);
  const mainItems = [...Array(3).fill(null)].map((_, index) => (
    <SidenavButton
      startIcon={<SvgPlaceholder />}
      key={index}
      isActive={activeIndex === index}
      onClick={() => setActiveIndex(index)}
    >
      {`App ${index}`}
    </SidenavButton>
  ));
  return (
    <SideNavigation
      items={mainItems}
      secondaryItems={[
        <SidenavButton startIcon={<SvgSettings />} key={3}>
          Settings
        </SidenavButton>,
      ]}
    />
  );
};

The submenu is the menu that expands when one of the menu items is clicked. It contains all subitems and page links associated to the main item. When the submenu appears, the main page’s content does not yet change; the user must select something within the submenu first for the page content to change.

import * as React from 'react';
import {
  Anchor,
  IconButton,
  SidenavButton,
  SideNavigation,
  Text,
  SidenavSubmenu,
  SidenavSubmenuHeader,
} from '@itwin/itwinui-react';
import {
  SvgHome,
  SvgFlag,
  SvgFolderOpened,
  SvgSettings,
} from '@itwin/itwinui-icons-react';

export default () => {
  const itemsData = [
    { label: 'Home', icon: <SvgHome /> },
    { label: 'Issues', icon: <SvgFlag /> },
    { label: 'Documents', icon: <SvgFolderOpened /> },
    { label: 'Settings', icon: <SvgSettings /> },
  ];

  const [activeItem, setActiveItem] = React.useState(2);
  const [isSubmenuOpen, setIsSubmenuOpen] = React.useState(true);
  const [activeSubItem, setActiveSubItem] = React.useState(0);

  const items = itemsData.map(({ label, icon }, index) => (
    <SidenavButton
      key={index}
      startIcon={icon}
      isActive={activeItem === index}
      isSubmenuOpen={label === 'Documents' && isSubmenuOpen} // needed for proper styling when submenu is open but page is not active
      onClick={() => {
        if (label !== 'Documents') {
          setActiveItem(index);
          setActiveSubItem(-1);
          setIsSubmenuOpen(false);
        } else {
          setIsSubmenuOpen((open) => !open);
        }
      }}
    >
      {label}
    </SidenavButton>
  ));

  return (
    <div className='demo-container'>
      <SideNavigation
        expanderPlacement='bottom'
        items={items.slice(0, 3)}
        secondaryItems={[items[3]]}
        isSubmenuOpen={isSubmenuOpen}
        submenu={
          <SidenavSubmenu>
            <SidenavSubmenuHeader
              actions={
                <IconButton label='Submenu settings' styleType='borderless'>
                  <SvgSettings />
                </IconButton>
              }
            >
              <span>Documents</span>
            </SidenavSubmenuHeader>
            <Text variant='leading'>All documents</Text>
            <ul>
              {[...Array(10).fill(null)].map((_, index) => (
                <li key={index}>
                  <Anchor
                    onClick={() => {
                      setActiveItem(2);
                      setActiveSubItem(index);
                    }}
                  >
                    Folder {index}
                  </Anchor>
                </li>
              ))}
            </ul>
          </SidenavSubmenu>
        }
      />
      <div className='demo-item-label'>
        <Text>{itemsData[activeItem]?.label} page</Text>
        <Text isMuted>
          {activeSubItem >= 0 && `Contents of Folder ${activeSubItem}`}
        </Text>
      </div>
    </div>
  );
};

Props

Prop Description Default
items
Buttons shown in the top portion of sidenav. Recommended to use SidenavButton components.
ReactNode[]
secondaryItems
Buttons shown at the bottom of sidenav.
ReactNode[]
expanderPlacement
Control the placement of "expander" icon button (or hide it).
"hidden" | "top" | "bottom"
'top'
isExpanded
Controlled flag to expand/collapse the sidenav.
boolean
onExpanderClick
Callback fired when the "expander" icon is clicked.
() => void
submenu
Submenu to show supplemental info assicated to the main item.
Should be used with the isSubmenuOpen props from both SideNavigation and SidenavButton.
Element
isSubmenuOpen
Set to true to display the provided submenu.
Note that there is an identical prop in SidenavButton which should also be set to true for proper styling when submenu is open but page is not active yet.
boolean
false
wrapperProps
Passes props for SideNav wrapper.
DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
contentProps
Passes props for SideNav content.
DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
topProps
Passes props for SideNav top.
DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
bottomProps
Passes props for SideNav bottom.
DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
as
"symbol" | "object" | "div" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | ... 158 more ... | FunctionComponent<...>