Side Nav components are used traditionally as a secondary form of navigation where the primary navigation is located hierarchically above the page frame.
Side Nav is mostly intended to use within the Sidebar component.
<Sidebar>
<State initial={0}>
{([active, setActive]) => (
<SideNav
title={
<span>
Marketing
<Tag subtle compact>Within Sidebar</Tag>
</span>
}>
<SideNav.Item onClick={() => setActive(0)} active={active===0}>Dashboard</SideNav.Item>
<SideNav.Item onClick={() => setActive(1)} active={active===1}>Campaigns</SideNav.Item>
<SideNav.Item onClick={() => setActive(2)} active={active===2}>Emails</SideNav.Item>
<SideNav.Item onClick={() => setActive(3)} active={active===3}>Audiences</SideNav.Item>
</SideNav>
)}
</State>
</Sidebar>
<State initial={0}>
{([active, setActive]) => (
<SideNav
title={
<span>
Marketing
<Tag color="warning" subtle compact>Plain</Tag>
</span>
}>
<SideNav.Item onClick={() => setActive(0)} active={active===0} icon="odometer">Dashboard</SideNav.Item>
<SideNav.Item onClick={() => setActive(1)} active={active===1} icon="bullhorn">Campaigns</SideNav.Item>
<SideNav.Item onClick={() => setActive(2)} active={active===3} icon="email">Emails</SideNav.Item>
<SideNav.Item onClick={() => setActive(3)} active={active===4} icon="group_work">Audiences</SideNav.Item>
</SideNav>
)}
</State>
Collapsible
Side Nav item can be rendered as collapsible menu, also known as Accordion.
<Sidebar>
<State initial={0}>
{([active, setActive]) => (
<SideNav>
<SideNav.Item onClick={() => setActive(0)} active={active===0}>Dashboard</SideNav.Item>
<SideNav.Item
active={[2, 3, 4].includes(active)}
collapsible={{expanded: false}}
>
Campaigns
<SideNav>
<SideNav.Item onClick={() => setActive(2)} active={active===2}>First Item</SideNav.Item>
<SideNav.Item onClick={() => setActive(3)} active={active===3}>Second Item</SideNav.Item>
<SideNav.Item onClick={() => setActive(4)} active={active===4}>Third Item</SideNav.Item>
</SideNav>
</SideNav.Item>
<SideNav.Item
active={[5, 6, 7].includes(active)}
collapsible={{expanded: true}}
>
Emails
<SideNav>
<SideNav.Item onClick={() => setActive(5)} active={active===5}>First Item</SideNav.Item>
<SideNav.Item onClick={() => setActive(6)} active={active===6}>Second Item</SideNav.Item>
<SideNav.Item onClick={() => setActive(7)} active={active===7}>Third Item</SideNav.Item>
</SideNav>
</SideNav.Item>
<SideNav.Item
active={[8, 9, 10].includes(active)}
collapsible={{expanded: false}}
>
Audiences
<SideNav>
<SideNav.Item onClick={() => setActive(8)} active={active===8}>First Item</SideNav.Item>
<SideNav.Item onClick={() => setActive(9)} active={active===9}>Second Item</SideNav.Item>
<SideNav.Item onClick={() => setActive(10)} active={active===10}>Third Item</SideNav.Item>
</SideNav>
</SideNav.Item>
</SideNav>
)}
</State>
</Sidebar>
<Sidebar>
<State initial={0}>
{([active, setActive]) => (
<SideNav>
<SideNav.Item onClick={() => setActive(0)} active={active===0} icon="odometer">Dashboard</SideNav.Item>
<SideNav.Item
active={[2, 3, 4].includes(active)}
collapsible={{expanded: true}}
icon="bullhorn"
>
Campaigns
<SideNav>
<SideNav.Item onClick={() => setActive(2)} active={active===2}>First Item</SideNav.Item>
<SideNav.Item onClick={() => setActive(3)} active={active===3}>Second Item</SideNav.Item>
<SideNav.Item onClick={() => setActive(4)} active={active===4}>Third Item</SideNav.Item>
</SideNav>
</SideNav.Item>
<SideNav.Item
active={[5, 6, 7].includes(active)}
collapsible={{expanded: false}}
icon="email"
>
Emails
<SideNav>
<SideNav.Item onClick={() => setActive(5)} active={active===5}>First Item</SideNav.Item>
<SideNav.Item onClick={() => setActive(6)} active={active===6}>Second Item</SideNav.Item>
<SideNav.Item onClick={() => setActive(7)} active={active===7}>Third Item</SideNav.Item>
</SideNav>
</SideNav.Item>
<SideNav.Item
active={[8, 9, 10].includes(active)}
collapsible={{expanded: false}}
icon="group_work"
>
Audiences
<SideNav>
<SideNav.Item onClick={() => setActive(8)} active={active===8}>First Item</SideNav.Item>
<SideNav.Item onClick={() => setActive(9)} active={active===9}>Second Item</SideNav.Item>
<SideNav.Item onClick={() => setActive(10)} active={active===10}>Third Item</SideNav.Item>
</SideNav>
</SideNav.Item>
</SideNav>
)}
</State>
</Sidebar>
Best practices:
- no icon allowed on left side of nested item
- no collapsible allowed inside nested collapsibe (only one level of nesting is allowed)
Decorations and Secondary Action
Side Nav item can be decorated with:
- icon on the left (allowed only for first level items)
- custom content on the right, like Icon or Status Light
- custom inline content, like Tag or Badge
- disabled state
Item can have Secondary Action on the right side, like Button or Action Menu.
Besides that search may be injected into the top of Side Nav.
Individual items can be rendered as regular links.
<Sidebar>
<SideNav>
<SideNav.Group title="Icon">
<SideNav.Item icon="bookmark">Bookmarks</SideNav.Item>
<SideNav.Item
icon="settings"
suffix={<Tooltip text="Help"><Icon name="help_outline" size="20px" style={{opacity: .4}} /></Tooltip>}
>
Settings
</SideNav.Item>
</SideNav.Group>
<SideNav.Group title="Content on the Right">
<SideNav.Item
icon="notifications"
suffix={<StatusLight color="critical" />}
>
Notifications
</SideNav.Item>
<SideNav.Item
icon="movie"
suffix={
<Button
fill="subtle"
iconName="add"
onClick={(e) => {e.stopPropagation(); alert('Button pressed.');}}
size="xsmall"
/>
}
>
Movies
</SideNav.Item>
<SideNav.Item
icon="palette"
suffix={
<Button
fill="subtle"
iconName="more_vert"
onClick={(e) => {e.stopPropagation(); alert('Action menu opened.');}}
size="xsmall"
/>
}
>
Colors and Theme
</SideNav.Item>
</SideNav.Group>
<SideNav.Group title="Inline">
<SideNav.Item icon="local_bar">
Drinks
<Tag color="info" compact subtle>New!</Tag>
</SideNav.Item>
<SideNav.Item icon="security">
Security
<Tag compact badge color="warning">2</Tag>
</SideNav.Item>
</SideNav.Group>
</SideNav>
</Sidebar>
<Sidebar>
<SideNav style={{marginTop: '-2px'}}>
<Form.Input
icon={{ name: 'search', size: 20, className: 'm-x--half' }}
iconPosition="left"
placeholder="Search"
xsmall
className="m-b-half m-t-2 m-x-1"
/>
<SideNav.Group title="Administration">
<SideNav.Item>Bookmarks</SideNav.Item>
<SideNav.Item>Settings</SideNav.Item>
<SideNav.Item disabled>Admin console (disabled item)</SideNav.Item>
<SideNav.Item>User Profile</SideNav.Item>
</SideNav.Group>
<SideNav.Group title="Links">
<SideNav.Item
suffix={<Icon name="open_in_new" size={20} style={{opacity: .4}} />}
href="https://www.servicetitan.com/"
target="_blank"
>
ServiceTitan
</SideNav.Item>
<SideNav.Item
suffix={<Icon name="open_in_new" size={20} style={{opacity: .4}} />}
href="https://github.com/servicetitan/anvil"
target="_blank"
>
Github
</SideNav.Item>
<SideNav.Item
suffix={<Icon name="open_in_new" size={20} style={{opacity: .4}} />}
href="https://medium.com/servicetitan-design"
target="_blank"
>
Medium
</SideNav.Item>
</SideNav.Group>
</SideNav>
</Sidebar>
Groups
Use SideNav.Group to group navigation items based on related categories.
<Sidebar>
<State initial={0}>
{([active, setActive]) => (
<SideNav title="Marketing">
<SideNav.Item onClick={() => setActive(0)} active={active===0}>Dashboard</SideNav.Item>
<SideNav.Item onClick={() => setActive(1)} active={active===1}>Campaigns</SideNav.Item>
<SideNav.Item onClick={() => setActive(2)} active={active===2}>Emails</SideNav.Item>
<SideNav.Item onClick={() => setActive(3)} active={active===3}>Audiences</SideNav.Item>
<SideNav.Group title="Integrations">
<SideNav.Item onClick={() => setActive(4)} active={active===4}>Catalog</SideNav.Item>
<SideNav.Item onClick={() => setActive(5)} active={active===5}>Updates</SideNav.Item>
<SideNav.Item onClick={() => setActive(6)} active={active===6}>Sync Log</SideNav.Item>
</SideNav.Group>
</SideNav>
)}
</State>
</Sidebar>
<Sidebar>
<State initial={0}>
{([active, setActive]) => (
<SideNav title={<span>Marketing<Tag color="warning" subtle compact>Pro</Tag></span>}>
<SideNav.Group title="Email">
<SideNav.Item onClick={() => setActive(0)} active={active===0}>Dashboard</SideNav.Item>
<SideNav.Item onClick={() => setActive(1)} active={active===1}>Campaigns</SideNav.Item>
<SideNav.Item onClick={() => setActive(2)} active={active===2}>Email Templates</SideNav.Item>
<SideNav.Item onClick={() => setActive(3)} active={active===3}>Audiences</SideNav.Item>
</SideNav.Group>
<SideNav.Group title="Direct Mail">
<SideNav.Item onClick={() => setActive(4)} active={active===4}>Dashboard</SideNav.Item>
<SideNav.Item onClick={() => setActive(5)} active={active===5}>Campaigns</SideNav.Item>
<SideNav.Item onClick={() => setActive(6)} active={active===6}>Postcard Templates</SideNav.Item>
<SideNav.Item onClick={() => setActive(7)} active={active===7}>Audiences</SideNav.Item>
</SideNav.Group>
</SideNav>
)}
</State>
</Sidebar>
Keyboard Support
- When focus is inside Side Nav, press
up
or down
to move focus up and down.
- Use
space
or enter
to collapse, expand or navigate the item.
Best Practices
The Side Nav component should:
- Group navigation items based on related categories.
- Only one item should be active at all time.
- Direct the user to a page that has a unique URL
- Common container is Sidebar
- For a third level of navigation, use a Tab.
Importing
import { SideNav } from '@servicetitan/design-system';