SideNavigation
A side navigation recipe that composes Panel and SidebarNav into an application shell.
Import
import { SideNavigation } from "@cfa/react-core";Guidelines
When to use
- Side Navigation is for top-level app destinations.
Do
- Use short, parallel destination names, one or two words.
- Mark the current destination with
aria-current="page".
Avoid
- Using Side Navigation for subsections or in-page navigation.
- Using Side Navigation for a temporary, task-scoped panel. Use Drawer.
- Using deep multi-level trees. Split sub-areas into page content instead.
Usage
Use SideNavigation as an opinionated, pre-composed application shell. It owns the Panel and SidebarNav composition, maps item data into navigation content, and places children in the adjacent content area. Place SideNavigation.Trigger in the content area so the panel can be reopened after it closes.
View interactive examples in Storybook.
import { SideNavigation } from "@cfa/react-core";import { Home, Settings } from "@cfa/icons/system";
function DataDrivenSideNavigation() { const [current, setCurrent] = React.useState("home"); const items = [ { type: "link", id: "home", href: "#home", label: "Home", icon: <Home size="xs" />, }, { type: "section", id: "settings", label: "Settings", icon: <Settings size="xs" />, items: [ { id: "general", href: "#general", label: "General" }, { id: "profile", href: "#profile", label: "Profile" }, ], }, ];
return ( <SideNavigation layout="contained" disableKeyboardShortcut aria-label="Application navigation" header="Application" items={items} currentKey={current} onItemPress={(key) => setCurrent(String(key))} contentAs="section" contentAriaLabel="Example content" > <div style={{ padding: 16 }}> <SideNavigation.Trigger aria-label="Toggle side navigation" /> <h2>Current page: {current}</h2> <p>This content renders in the inset next to the side navigation.</p> </div> </SideNavigation> );}Footer
Pass a footer node for content below the navigation list. The UserInfo recipe is a common choice for signed-in user summaries.
import { UserInfo } from "@cfa/react-core";
<SideNavigation aria-label="Application navigation" items={items}> {children}</SideNavigation>;Data Model
Each entry in items uses an explicit type field. Top-level links use type: "link", expandable groups use type: "section", and separators use type: "divider". Nested section links omit type because they are always links. Recipe intentionally supports common navigation fields rather than every underlying Panel or SidebarNav prop.
const items = [ { type: "link", id: "home", href: "/", label: "Home", icon: <Home size="xs" />, }, { type: "section", id: "settings", label: "Settings", icon: <Settings size="xs" />, items: [ { id: "general", href: "/settings/general", label: "General" }, { id: "profile", href: "/settings/profile", label: "Profile" }, ], }, { type: "divider", id: "settings-divider" }, { type: "link", id: "help", href: "/help", label: "Help", },];currentKey marks the current item with aria-current="page". Sections that contain the current item expand automatically. Use onItemPress when the application needs to react to item selection in addition to normal link navigation.
Set closeOnNavigate to close the panel after a link is selected. It defaults to "mobile" so overlay drawers dismiss after navigation on small viewports.
Content Area
The wrapper’s children are rendered in the side navigation content area. Place page content and any external SideNavigation.Trigger there so the panel can be reopened after it closes.
<SideNavigation aria-label="Application navigation" header="Application" items={items} currentKey={current} onItemPress={(key) => setCurrent(String(key))}> <div style={{ padding: 16 }}> <SideNavigation.Trigger aria-label="Toggle side navigation" /> <h1>Home</h1> <p>Main application content.</p> </div></SideNavigation>For contained layouts nested inside an existing page, use contentAs and contentAriaLabel to avoid adding another page-level main landmark.
<SideNavigation layout="contained" disableKeyboardShortcut aria-label="Dashboard navigation" items={items} contentAs="section" contentAriaLabel="Dashboard content"> <DashboardContent /></SideNavigation>Opinionated Composition
SideNavigation is intentionally not a recipe namespace for assembling raw Panel and SidebarNav primitives. If an application needs deeper customization than the data-driven API supports, compose Panel and SidebarNav directly instead of routing those concerns through the recipe.