Nav Menu
A vertical navigation menu with collapsible groups, commonly used in sidebars and dashboards. Built using Column, Row, Text, and Icon components.
Dashboard
Home
Analytics
Users
Settings
General
Security
Source
'use client';
import { createContext, useContext, useState } from 'react';
import { Column, Row, Text, Icon } from '@umami/react-zen';
import { ChevronRight } from 'lucide-react';
const NavMenuContext = createContext({});
export function NavMenu({ onItemClick, children, ...props }) {
return (
<NavMenuContext.Provider value={{ onItemClick }}>
<Column gap="1" {...props}>
{children}
</Column>
</NavMenuContext.Provider>
);
}
export function NavMenuGroup({ title, defaultOpen = true, collapsible = true, children, ...props }) {
const [isOpen, setIsOpen] = useState(defaultOpen);
return (
<Column {...props}>
<Row
paddingY="2"
paddingX="3"
alignItems="center"
justifyContent="space-between"
className={collapsible ? 'cursor-pointer' : ''}
onClick={collapsible ? () => setIsOpen(!isOpen) : undefined}
>
<Text size="sm" weight="semibold" color="muted" transform="uppercase">
{title}
</Text>
{collapsible && (
<Icon size="sm" color="muted" rotate={isOpen ? 90 : 0}>
<ChevronRight />
</Icon>
)}
</Row>
{(collapsible ? isOpen : true) && <Column>{children}</Column>}
</Column>
);
}
export function NavMenuItem({ icon, isSelected, children, ...props }) {
const { onItemClick } = useContext(NavMenuContext);
return (
<Row
paddingY="2"
paddingX="3"
borderRadius="md"
alignItems="center"
gap="2"
onClick={onItemClick}
backgroundColor={isSelected ? 'interactive' : undefined}
className={`cursor-pointer ${!isSelected ? 'hover:bg-interactive' : ''}`}
{...props}
>
{icon && (
<Icon size="sm" color="muted">
{icon}
</Icon>
)}
<Text
color={isSelected ? undefined : 'muted'}
weight={isSelected ? 'medium' : undefined}
>
{children}
</Text>
</Row>
);
}Variations
Without icons
Pages
Dashboard
Reports
Settings
Non-collapsible groups
Navigation
Home
Settings