Skip to Content

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