Skip to Content
ComponentsSidebar

Sidebar

Primary navigation menu for left side of the page that includes support for branding, links, etc.

Documentation

"use client"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, Nav, NavAccountItem, NavBody, NavFooter, NavItem, NavList, Sidebar, SidebarToggle, } from "@optiaxiom/react"; import { IconBinaryTree, IconChartLine, IconExternalLink, IconFlag2, IconLayoutSidebar, IconSettings, IconVocabulary, } from "@tabler/icons-react"; import { useState } from "react"; import { Canvas } from "../Canvas"; export function App() { const [selected, setSelected] = useState("flags"); return ( <Canvas> <Sidebar defaultExpanded> <Nav> <NavBody> <NavList> <NavItem active={selected === "projects"} icon={<IconBinaryTree />} onClick={() => setSelected("projects")} > Projects </NavItem> <NavItem active={selected === "flags"} icon={<IconFlag2 />} onClick={() => setSelected("flags")} > Flags </NavItem> <NavItem active={selected === "events"} icon={<IconChartLine />} onClick={() => setSelected("events")} > Events </NavItem> <NavItem active={selected === "settings"} icon={<IconSettings />} onClick={() => setSelected("settings")} > Settings </NavItem> <NavItem addonAfter={<IconExternalLink size="16" />} asChild icon={<IconVocabulary />} > <a href="/">Tutorial</a> </NavItem> </NavList> </NavBody> <NavFooter> <NavList> <SidebarToggle icon={<IconLayoutSidebar />} /> <DropdownMenu> <DropdownMenuTrigger asChild> <NavAccountItem name="Rhaenyra Targaryen" organization="Optimizely" src="https://i.pravatar.cc/150?img=10" /> </DropdownMenuTrigger> <DropdownMenuContent align="end" side="right"> <DropdownMenuItem>View Profile</DropdownMenuItem> <DropdownMenuItem>Settings</DropdownMenuItem> <DropdownMenuItem>Logout</DropdownMenuItem> </DropdownMenuContent> </DropdownMenu> </NavList> </NavFooter> </Nav> </Sidebar> </Canvas> ); }
import { Nav, NavAccountItem, NavBody, NavFooter, NavHeader, NavItem, NavList, Sidebar, SidebarToggle, } from "@optiaxiom/react"; import { NavGroup, NavGroupContent, NavGroupTrigger, NavSeparator, SubNav, } from "@optiaxiom/react/unstable"; export default () => ( <Sidebar> <Nav> <NavHeader /> <NavBody> <NavList> <NavItem /> <NavGroup> <NavGroupTrigger /> <NavSeparator /> <NavGroupContent> <NavItem /> </NavGroupContent> </NavGroup> </NavList> </NavBody> <NavFooter> <NavList> <SidebarToggle /> <NavItem /> <NavAccountItem /> </NavList> </NavFooter> </Nav> <SubNav /> </Sidebar> );

The Nav component is used to create the primary navigation panel.

import { Nav, Sidebar } from "@optiaxiom/react"; import { Canvas } from "../../Canvas"; import { Note } from "../../Note"; export function App() { return ( <Canvas size="sm"> <Sidebar expanded> <Nav> <Note description="The primary navigation panel." title="Nav" /> </Nav> </Sidebar> </Canvas> ); }

We can also create additional secondary navigation panels using the SubNav component. The rest of the hierarchy within SubNav is the exact same as Nav.

import { Nav, Sidebar, SubNav } from "@optiaxiom/react"; import { Canvas } from "../../Canvas"; import { Note } from "../../Note"; export function App() { return ( <Canvas size="sm"> <Sidebar> <Nav /> <SubNav> <Note description="A secondary navigation panel." title="SubNav" /> </SubNav> </Sidebar> </Canvas> ); }

Each navigation panel contains three sections: header, body, and footer.

import { Nav, NavBody, NavFooter, NavHeader, Sidebar } from "@optiaxiom/react"; import { Canvas } from "../../Canvas"; import { Note } from "../../Note"; export function App() { return ( <Canvas> <Sidebar expanded> <Nav> <NavHeader> <Note description="A sticky header that is always visible at the top of the panel." title="NavHeader" /> </NavHeader> <NavBody> <Note description="The main navigation body that is scrollable and should contain all your navigation items." title="NavBody" /> </NavBody> <NavFooter> <Note description="A sticky footer that is always visible at the bottom of the panel." title="NavFooter" /> </NavFooter> </Nav> </Sidebar> </Canvas> ); }

Both primary and secondary navigation panels can contain these sections.

import { Nav, NavBody, NavFooter, NavHeader, Sidebar, SubNav, } from "@optiaxiom/react"; import { Canvas } from "../../Canvas"; import { Note } from "../../Note"; export function App() { return ( <Canvas> <Sidebar> <Nav /> <SubNav> <NavHeader> <Note description="A sticky header that is always visible at the top of the panel." title="NavHeader" /> </NavHeader> <NavBody> <Note description="The main navigation body that is scrollable and should contain all your navigation items." title="NavBody" /> </NavBody> <NavFooter> <Note description="A sticky footer that is always visible at the bottom of the panel." title="NavFooter" /> </NavFooter> </SubNav> </Sidebar> </Canvas> ); }

Use NavList and NavItem to place navigation lists inside the body (or header/footer) navigation sections.

import { Nav, NavBody, NavItem, NavList, Sidebar } from "@optiaxiom/react"; import { IconDashboard, IconDeviceDesktop, IconTestPipe, } from "@tabler/icons-react"; import { Canvas } from "../../Canvas"; export function App() { return ( <Canvas size="auto"> <Sidebar expanded> <Nav> <NavBody> <NavList> <NavItem icon={<IconDashboard />}>CMP</NavItem> <NavItem icon={<IconDeviceDesktop />}>CMS</NavItem> <NavItem icon={<IconTestPipe />}>Experimentation</NavItem> </NavList> </NavBody> </Nav> </Sidebar> </Canvas> ); }

Enable the active prop on NavItem to highlight the currently active/selected navigation item.

"use client"; import { Nav, NavBody, NavItem, NavList, Sidebar } from "@optiaxiom/react"; import { IconDashboard, IconDeviceDesktop, IconTestPipe, } from "@tabler/icons-react"; import { useState } from "react"; import { Canvas } from "../../Canvas"; export function App() { const [selected, setSelected] = useState<string>("CMP"); return ( <Canvas size="auto"> <Sidebar expanded> <Nav> <NavBody> <NavList> <NavItem active={selected === "CMP"} icon={<IconDashboard />} onClick={() => setSelected("CMP")} > CMP </NavItem> <NavItem active={selected === "CMS"} icon={<IconDeviceDesktop />} onClick={() => setSelected("CMS")} > CMS </NavItem> <NavItem active={selected === "Experimentation"} icon={<IconTestPipe />} onClick={() => setSelected("Experimentation")} > Experimentation </NavItem> </NavList> </NavBody> </Nav> </Sidebar> </Canvas> ); }

Set asChild to true on NavItem and wrap children in an <a> element to render buttons as links.

import { Nav, NavBody, NavItem, NavList, Sidebar } from "@optiaxiom/react"; import { IconExternalLink, IconVocabulary } from "@tabler/icons-react"; import { Canvas } from "../../Canvas"; export function App() { return ( <Canvas size="auto"> <Sidebar expanded> <Nav> <NavBody> <NavList> <NavItem addonAfter={<IconExternalLink size="16" />} asChild icon={<IconVocabulary />} > <a href="/">Tutorial</a> </NavItem> </NavList> </NavBody> </Nav> </Sidebar> </Canvas> ); }

Use NavAccountItem to include an account profile button within navigation lists.

import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, Nav, NavAccountItem, NavFooter, NavList, Sidebar, } from "@optiaxiom/react"; import { Canvas } from "../../Canvas"; export function App() { return ( <Canvas size="auto"> <Sidebar expanded> <Nav> <NavFooter> <NavList> <DropdownMenu> <DropdownMenuTrigger asChild> <NavAccountItem name="Rhaenyra Targaryen" organization="Optimizely" src="https://i.pravatar.cc/150?img=10" /> </DropdownMenuTrigger> <DropdownMenuContent align="end" side="right"> <DropdownMenuItem>View Profile</DropdownMenuItem> <DropdownMenuItem>Settings</DropdownMenuItem> <DropdownMenuItem>Logout</DropdownMenuItem> </DropdownMenuContent> </DropdownMenu> </NavList> </NavFooter> </Nav> </Sidebar> </Canvas> ); }

Use SidebarToggle to include a toggle button within navigation lists for collapsing/expanding the primary navigation panel.

Use the expanded and defaultExpanded props on Sidebar to toggle between controlled and uncontrolled usage. And combine it with onExpandedChange to listen for changes to the state.

import { Nav, NavFooter, NavList, Sidebar, SidebarToggle, } from "@optiaxiom/react"; import { IconLayoutSidebar } from "@tabler/icons-react"; import { Canvas } from "../../Canvas"; export function App() { return ( <Canvas> <Sidebar defaultExpanded> <Nav> <NavFooter> <NavList> <SidebarToggle icon={<IconLayoutSidebar />} /> </NavList> </NavFooter> </Nav> </Sidebar> </Canvas> ); }

Use NavGroup, NavGroupTrigger, and NavGroupContent to group related navigation items together inside a section.

import { Nav, NavBody, NavGroup, NavGroupContent, NavGroupTrigger, NavItem, NavList, Sidebar, } from "@optiaxiom/react"; import { IconDashboard, IconDeviceDesktop, IconTestPipe, } from "@tabler/icons-react"; import { Canvas } from "../../Canvas"; export function App() { return ( <Canvas size="auto"> <Sidebar expanded> <Nav> <NavBody> <NavList> <NavGroup> <NavGroupTrigger>Location</NavGroupTrigger> <NavGroupContent> <NavItem icon={<IconDashboard />}>CMP</NavItem> <NavItem icon={<IconDeviceDesktop />}>CMS</NavItem> <NavItem icon={<IconTestPipe />}>Experimentation</NavItem> </NavGroupContent> </NavGroup> </NavList> </NavBody> </Nav> </Sidebar> </Canvas> ); }

Use the collapsible prop on NavGroup to make the section collapsible. Use the defaultOpen/open/onOpenChange props if you want to control the collapsed/expanded state.

import { Nav, NavBody, NavGroup, NavGroupContent, NavGroupTrigger, NavItem, NavList, Sidebar, } from "@optiaxiom/react"; import { IconDashboard, IconDeviceDesktop, IconTestPipe, } from "@tabler/icons-react"; import { Canvas } from "../../Canvas"; export function App() { return ( <Canvas size="auto"> <Sidebar expanded> <Nav> <NavBody> <NavList> <NavGroup collapsible> <NavGroupTrigger>Location</NavGroupTrigger> <NavGroupContent> <NavItem icon={<IconDashboard />}>CMP</NavItem> <NavItem icon={<IconDeviceDesktop />}>CMS</NavItem> <NavItem icon={<IconTestPipe />}>Experimentation</NavItem> </NavGroupContent> </NavGroup> </NavList> </NavBody> </Nav> </Sidebar> </Canvas> ); }

Use NavSeparator inside NavGroup to add separators between navigation items or groups.

import { Nav, NavBody, NavGroup, NavGroupContent, NavGroupTrigger, NavItem, NavList, NavSeparator, Sidebar, } from "@optiaxiom/react"; import { IconCopy, IconDashboard, IconDeviceDesktop, IconRectangle, IconTestPipe, } from "@tabler/icons-react"; import { Canvas } from "../../Canvas"; export function App() { return ( <Canvas size="auto"> <Sidebar expanded> <Nav> <NavBody> <NavList> <NavItem icon={<IconCopy />}>All</NavItem> <NavItem icon={<IconRectangle />}>Recent</NavItem> <NavGroup> <NavSeparator /> <NavGroupTrigger>Location</NavGroupTrigger> <NavGroupContent> <NavItem icon={<IconDashboard />}>CMP</NavItem> <NavItem icon={<IconDeviceDesktop />}>CMS</NavItem> <NavItem icon={<IconTestPipe />}>Experimentation</NavItem> </NavGroupContent> </NavGroup> </NavList> </NavBody> </Nav> </Sidebar> </Canvas> ); }
"use client"; import { NavBody, NavGroup, NavGroupContent, NavGroupTrigger, NavItem, NavList, NavSeparator, Sidebar, SubNav, } from "@optiaxiom/react"; import { IconCopy, IconDashboard, IconDeviceDesktop, IconRectangle, IconReport, IconStar, IconTestPipe, IconTrash, } from "@tabler/icons-react"; import { useState } from "react"; import { Canvas } from "../Canvas"; import { PrimaryNav } from "./PrimaryNav"; export function App() { const [selected, setSelected] = useState<string>("CMP"); return ( <Canvas> <Sidebar> <PrimaryNav /> <SubNav> <NavBody> <NavList> <NavItem active={selected === "All"} icon={<IconCopy />} onClick={() => setSelected("All")} > All </NavItem> <NavItem active={selected === "Recent"} icon={<IconRectangle />} onClick={() => setSelected("Recent")} > Recent </NavItem> <NavItem active={selected === "Favorites"} icon={<IconStar />} onClick={() => setSelected("Favorites")} > Favorites </NavItem> <NavItem active={selected === "Trash"} icon={<IconTrash />} onClick={() => setSelected("Trash")} > Trash </NavItem> <NavGroup> <NavSeparator /> <NavGroupTrigger>Location</NavGroupTrigger> <NavGroupContent> <NavItem active={selected === "CMP"} icon={<IconDashboard />} onClick={() => setSelected("CMP")} > CMP </NavItem> <NavItem active={selected === "CMS"} icon={<IconDeviceDesktop />} onClick={() => setSelected("CMS")} > CMS </NavItem> <NavItem active={selected === "Experimentation"} icon={<IconTestPipe />} onClick={() => setSelected("Experimentation")} > Experimentation </NavItem> </NavGroupContent> </NavGroup> <NavGroup> <NavSeparator /> <NavGroupTrigger>Analytics</NavGroupTrigger> <NavGroupContent> <NavItem active={selected === "Dashboard"} icon={<IconDashboard />} onClick={() => setSelected("Dashboard")} > Dashboard </NavItem> <NavItem active={selected === "Reports"} icon={<IconReport />} onClick={() => setSelected("Reports")} > Reports </NavItem> </NavGroupContent> </NavGroup> </NavList> </NavBody> </SubNav> </Sidebar> </Canvas> ); }

Props

Supports all Box props in addition to its own. Renders a <div> element.

Prop

asChild

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

false | true

className

string

defaultExpanded

The initial expanded state in uncontrolled mode.

false | true

Default: false

expanded

The expanded state in controlled mode.

false | true

onExpandedChange

Handler that is called when the expanded state changes.

(expanded: boolean) => void

Supports all Box props in addition to its own. Renders an <li> element element but forwards all props to an inner <button> element.

Prop

active

Whether the nav item is currently active.

false | true

addonAfter

Display content inside the button after children.

ReactNode

aria-label

string

asChild

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

false | true

className

string

icon

Display an icon before button content.

ReactNode

Supports all Box props in addition to its own. Renders a <div> element.

Prop

asChild

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

false | true

className

string

defaultExpanded

The initial expanded state in uncontrolled mode.

false | true

expanded

The expanded state in controlled mode.

false | true

onExpandedChange

Handler that is called when the expanded state changes.

(expanded: boolean) => void

Supports all Box props in addition to its own. Renders a <div> element.

Prop

asChild

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

false | true

className

string

Supports all Box props in addition to its own. Renders a <div> element.

Prop

asChild

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

false | true

className

string

Supports all Box props in addition to its own. Renders a <div> element.

Prop

asChild

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

false | true

className

string

Supports all Box props in addition to its own. Renders a <ul> element.

Prop

asChild

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

false | true

className

string

Supports all Box props in addition to its own. Renders an <li> element element but forwards all props to an inner <button> element.

Prop

active

Whether the nav item is currently active.

false | true

addonAfter

Display content inside the button after children.

ReactNode

asChild

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

false | true

className

string

icon

Display an icon before button content.

ReactNode

Supports all Disclosure props in addition to its own. Renders an <li> element element but forwards all props to an inner <div> element.

Prop

asChild

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

false | true

className

string

collapsible

Whether the nav group should be collapsible or not.

false | true

defaultOpen

The initial open state in uncontrolled mode.

false | true

Default: true

disabled

false | true

onOpenChange

Handler that is called when the open state changes.

(open: boolean) => void

open

The open state in controlled mode.

false | true

Supports all DisclosureTrigger props in addition to its own. Renders a <div> element.

Prop

addonAfter

Display content after the button.

ReactNode

addonBefore

Display content before the button.

ReactNode

asChild

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

false | true

chevronPosition

Control which side to place the chevron.

"end" | "start"

className

string

Supports all DisclosureContent props in addition to its own. Renders a <ul> element.

Prop

asChild

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

false | true

className

string

Supports all Separator props in addition to its own. Renders a <div> element.

Prop

asChild

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

false | true

className

string

decorative

Whether or not the component is purely decorative. When true, accessibility-related attributes are updated so that that the rendered element is removed from the accessibility tree.

false | true

orientation

The orientation of the separator.

ResponsiveValue<"horizontal" | "vertical">

Supports all Box props in addition to its own. Renders an <li> element element but forwards all props to an inner <button> element.

Prop

asChild

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

false | true

className

string

name

The name of the user.

string

organization

The name of the current organization user belongs to.

string

src

Render the image inside the avatar.

string

Supports all Box props in addition to its own. Renders a <div> element.

Prop

asChild

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

false | true

className

string

Changelog

  • Added collapsible prop to NavGroup and set the default to false.
  • Added SubNav component
  • Added component
Last updated on