Side Navigation
SideNavigation provides a persistent sidebar navigation with collapsible states, grouped sections, nested items, badges, bottom-pinned items, logo slot, and a feature promotion card.
Side Navigation Playground
dashboard
Installation
You can add the side navigation component to your project manually:
Install the following dependencies:
npm install class-variance-authority clsx tailwind-merge @phosphor-icons/react @react-aria/focus @react-aria/interactions @react-aria/progress react-aria-componentsCopy and paste the following code into your project.
Update the import paths to match your project setup.
Update the import aliases (e.g. @/components, @/utils) in the copied files to match your project's path configuration.
Basic Usage
import { useState } from 'react';
import { SideNavigation } from '@versaui/ui/components/SideNavigation';
import { HouseIcon, ChartBarIcon, GearIcon } from '@phosphor-icons/react';
const sections = [
{
header: 'Main',
items: [
{ id: 'dashboard', label: 'Dashboard', icon: <HouseIcon /> },
{ id: 'reports', label: 'Reports', icon: <ChartBarIcon /> },
]
}
];
function App() {
const [selectedId, setSelectedId] = useState('dashboard');
return (
<SideNavigation
sections={sections}
selectedId={selectedId}
onSelect={(id) => setSelectedId(id)}
/>
);
}Sections and Headers
Group navigation items into labeled sections:
const sections = [
{
header: 'Main',
items: [
{ id: 'dashboard', label: 'Dashboard', icon: <HouseIcon /> },
{ id: 'projects', label: 'Projects', icon: <FilesIcon /> },
]
},
{
header: 'Analysis',
items: [
{ id: 'reports', label: 'Reports', icon: <ChartBarIcon /> },
{ id: 'goals', label: 'Goals', icon: <TargetIcon /> },
]
}
];Nested Items
Menu items can have expandable children:
{
id: 'team',
label: 'Team',
icon: <UsersIcon />,
children: [
{ id: 'members', label: 'Members', badge: 4 },
{ id: 'roles', label: 'Roles' },
{ id: 'permissions', label: 'Permissions' },
]
}Badges
Show notification counts on items:
{ id: 'projects', label: 'Projects', icon: <FilesIcon />, badge: 12 }Bottom Items
Pin items like Settings and Support to the bottom:
const bottomItems = [
{ id: 'settings', label: 'Settings', icon: <GearIcon /> },
{ id: 'help', label: 'Support', icon: <LifebuoyIcon /> },
];
<SideNavigation
sections={sections}
bottomItems={bottomItems}
/>Collapsed State
Toggle between full and icon-only modes:
const [collapsed, setCollapsed] = useState(false);
<SideNavigation
collapsed={collapsed}
onCollapsedChange={setCollapsed}
sections={sections}
/>Neutral Variant
Use the neutral style for a softer selected state with Material surface instead of brand fill:
<SideNavigation
variant="neutral"
sections={sections}
selectedId={selectedId}
onSelect={(id) => setSelectedId(id)}
/>Custom Logo
Provide expanded and collapsed logo variants:
<SideNavigation
logo={<img src="/logo-full.svg" height={24} />}
collapsedLogo={<img src="/logo-icon.svg" height={24} />}
sections={sections}
/>Feature Card
Built-in promotion card with usage indicator:
<SideNavigation
showFeatureCard
featureCardTitle="Upgrade to Pro"
featureCardDescription="Get unlimited projects and priority support"
featureCardButtonText="Upgrade Now"
onFeatureCardClick={() => openUpgradeModal()}
usageTitle="You're almost out of Projects"
usageStatus="4/5 Projects"
usagePercentage={80}
sections={sections}
/>Accessibility
- Uses
<nav>element witharia-labelfor semantic navigation - Keyboard navigation through all items
aria-current="page"on the active item- Collapsible sections use
aria-expandedandaria-controls - Focus management for nested item expansion
MenuItem Interface
interface MenuItem {
id: string;
label: string;
icon: ReactNode;
badge?: number;
disabled?: boolean;
href?: string;
children?: { id: string; label: string; badge?: number; disabled?: boolean; href?: string }[];
}MenuSection Interface
interface MenuSection {
header?: string;
items: MenuItem[];
}SideNavigation Props
| Prop | Type | Default | Description |
|---|---|---|---|
sections | MenuSection[] | [] | Array of navigation sections with headers and items. |
bottomItems | MenuItem[] | [] | Items pinned to the bottom of the sidebar. |
selectedId | string | '' | Currently active item ID. |
onSelect | (id: string) => void | — | Called when an item is selected. |
collapsed | boolean | false | Whether nav is collapsed to icons only. |
onCollapsedChange | (collapsed: boolean) => void | — | Called when collapsed state changes. |
variant | 'primary' | 'neutral' | 'primary' | Style variant for navigation items. Neutral uses Material surface for selected state. |
showLogo | boolean | true | Show logo at the top. |
logo | ReactNode | — | Custom expanded logo element. |
collapsedLogo | ReactNode | — | Custom collapsed logo element. |
logoBrand | LogoBrand | 'versa-ui' | Built-in brand logo preset. |
showFeatureCard | boolean | true | Show feature promotion card. |
featureCardTitle | string | 'Upgrade to Pro' | Feature card title. |
featureCardDescription | string | — | Feature card description. |
featureCardButtonText | string | 'Upgrade Now' | Feature card button text. |
onFeatureCardClick | () => void | — | Feature card button click handler. |
usageTitle | string | — | Usage indicator title. |
usageStatus | string | — | Usage indicator status text. |
usagePercentage | number | 80 | Usage progress bar percentage. |
height | number | string | '100%' | Sidebar height. |
className | string | '' | Additional CSS classes. |