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>,
]}
/>
);
};
Submenu
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<...> |