XDSMobileNav@xds/core · MobileNav

Usage

A slide-out drawer for mobile navigation. MobileNav is the mobile counterpart to SideNav and accepts the same children. Use it on narrow viewports where a persistent sidebar is not practical.

Best practices

GuidancePractices
DoShare the same nav items between MobileNav and SideNav by extracting them into a variable.
DoProvide a title when the drawer's purpose is not obvious from its content.
Don'tUse MobileNav on desktop — use a persistent SideNav instead.

Import

ts
import {XDSMobileNav} from '@xds/core/MobileNav'

Props

PropTypeDescription
isOpenrequired
booleanWhether the drawer is open.
onOpenChangerequired
(isOpen: boolean) => voidCalled when the drawer visibility changes (backdrop click, Escape key, or close button).
childrenrequired
ReactNodeDrawer content — typically XDSSideNavSection/XDSSideNavItem, or any ReactNode.
title
stringOptional title shown at the top of the drawer.
width
number (default: 280)Drawer width in pixels. Capped at 85vw to prevent overflow on small screens.
side
'start' | 'end' (default: 'start')Which side the drawer slides from. Start is left in LTR, right in RTL.

Examples

Common configurations, variations, and states.
MobileNav — Basic DrawerMobile navigation drawer with sectioned nav items triggered by a menu button
tsx
'use client';
import {useState} from 'react';
import {XDSMobileNav} from '@xds/core/MobileNav';
import {XDSSideNavSection, XDSSideNavItem} from '@xds/core/SideNav';
import {XDSButton} from '@xds/core/Button';
import {XDSIcon} from '@xds/core/Icon';
import {
HomeIcon,
FolderIcon,
ChartBarIcon,
Cog6ToothIcon,
UsersIcon,
} from '@heroicons/react/24/outline';
export default function MobileNavBasicMobileNav() {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<XDSButton
label="Open Navigation"
icon={<XDSIcon icon="menu" color="inherit" />}
variant="ghost"
onClick={() => setIsOpen(true)}
isIconOnly
/>
<XDSMobileNav
isOpen={isOpen}
onOpenChange={open => setIsOpen(open)}
header="Navigation">
<XDSSideNavSection title="Main">
<XDSSideNavItem
label="Dashboard"
icon={HomeIcon}
isSelected
href="/dashboard"
/>
<XDSSideNavItem label="Projects" icon={FolderIcon} href="/projects" />
<XDSSideNavItem
label="Analytics"
icon={ChartBarIcon}
href="/analytics"
/>
</XDSSideNavSection>
<XDSSideNavSection title="Settings">
<XDSSideNavItem
label="General"
icon={Cog6ToothIcon}
href="/settings"
/>
<XDSSideNavItem label="Team" icon={UsersIcon} href="/team" />
</XDSSideNavSection>
</XDSMobileNav>
</>
);
}
MobileNav — End Side DrawerNavigation drawer that slides in from the right side of the screen
tsx
'use client';
import {useState} from 'react';
import {XDSMobileNav} from '@xds/core/MobileNav';
import {XDSSideNavSection, XDSSideNavItem} from '@xds/core/SideNav';
import {XDSButton} from '@xds/core/Button';
import {Cog6ToothIcon, UsersIcon} from '@heroicons/react/24/outline';
export default function MobileNavEndSideMobileNav() {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<XDSButton label="Open from Right" onClick={() => setIsOpen(true)} />
<XDSMobileNav
isOpen={isOpen}
onOpenChange={open => setIsOpen(open)}
header="Settings"
side="end">
<XDSSideNavSection title="Settings">
<XDSSideNavItem
label="General"
icon={Cog6ToothIcon}
href="/settings"
/>
<XDSSideNavItem label="Team" icon={UsersIcon} href="/team" />
</XDSSideNavSection>
</XDSMobileNav>
</>
);
}
MobileNav — Without TitleMobile navigation drawer without a title header
tsx
'use client';
import {useState} from 'react';
import {XDSMobileNav} from '@xds/core/MobileNav';
import {XDSSideNavSection, XDSSideNavItem} from '@xds/core/SideNav';
import {XDSButton} from '@xds/core/Button';
import {XDSIcon} from '@xds/core/Icon';
import {HomeIcon, FolderIcon} from '@heroicons/react/24/outline';
export default function MobileNavWithoutTitleMobileNav() {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<XDSButton
label="Open Navigation"
icon={<XDSIcon icon="menu" color="inherit" />}
variant="ghost"
onClick={() => setIsOpen(true)}
isIconOnly
/>
<XDSMobileNav isOpen={isOpen} onOpenChange={open => setIsOpen(open)}>
<XDSSideNavSection title="Main">
<XDSSideNavItem
label="Dashboard"
icon={HomeIcon}
isSelected
href="/dashboard"
/>
<XDSSideNavItem label="Projects" icon={FolderIcon} href="/projects" />
</XDSSideNavSection>
</XDSMobileNav>
</>
);
}

Showcase source

tsx
'use client';
import {useState} from 'react';
import {XDSMobileNav} from '@xds/core/MobileNav';
import {XDSSideNavSection, XDSSideNavItem} from '@xds/core/SideNav';
import {XDSButton} from '@xds/core/Button';
import {XDSIcon} from '@xds/core/Icon';
export default function MobileNavShowcase() {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<XDSButton
label="Open Navigation"
icon={<XDSIcon icon="menu" color="inherit" />}
variant="ghost"
onClick={() => setIsOpen(true)}
isIconOnly
/>
<XDSMobileNav
isOpen={isOpen}
onOpenChange={setIsOpen}
header="Navigation">
<XDSSideNavSection title="Main">
<XDSSideNavItem label="Dashboard" isSelected href="/dashboard" />
<XDSSideNavItem label="Projects" href="/projects" />
<XDSSideNavItem label="Analytics" href="/analytics" />
</XDSSideNavSection>
<XDSSideNavSection title="Settings">
<XDSSideNavItem label="General" href="/settings" />
<XDSSideNavItem label="Team" href="/team" />
</XDSSideNavSection>
</XDSMobileNav>
</>
);
}