npm install @marmoui/uiyarn add @marmoui/uipnpm add @marmoui/uibun add @marmoui/uiImport the layout components from the package:
import {
SidebarProvider,
SideNavigation,
SidebarPanel,
SidebarItem,
SidebarSubItem
} from '@marmoui/ui';Complete layout with sidebar and main content
const mainNavItems = [
{
id: 'dashboard',
label: 'Dashboard',
iconOutlined: MdOutlineDashboard,
iconFilled: MdDashboard,
path: '/dashboard',
secondaryItems: [
{ id: 'overview', label: 'Overview', path: '/dashboard/overview' },
{ id: 'analytics', label: 'Analytics', path: '/dashboard/analytics' },
],
},
{
id: 'campaigns',
label: 'Campaigns',
iconOutlined: MdOutlineCampaign,
iconFilled: MdCampaign,
path: '/campaigns',
secondaryItems: [
{ id: 'active', label: 'Active', path: '/campaigns/active' },
{ id: 'drafts', label: 'Drafts', path: '/campaigns/drafts' },
{ id: 'archived', label: 'Archived', path: '/campaigns/archived' },
],
},
{
id: 'contacts',
label: 'Contacts',
iconOutlined: MdPeopleOutline,
iconFilled: MdPeople,
path: '/contacts',
secondaryItems: [
{ id: 'all', label: 'All Contacts', path: '/contacts/all' },
{ id: 'segments', label: 'Segments', path: '/contacts/segments' },
],
},
];
function AppLayout({ children }) {
return (
<SidebarProvider mainNavItems={mainNavItems}>
<div className="flex h-screen">
<SideNavigation />
<main className="flex-1 overflow-auto">
{children}
</main>
</div>
</SidebarProvider>
);
}Combining layout with page section headers
function DashboardPage() {
return (
<SidebarProvider mainNavItems={mainNavItems}>
<div className="flex h-screen">
<SideNavigation />
<main className="flex-1 overflow-auto bg-bg">
<PageSection
pageTitle="Dashboard"
primaryAction={{
label: 'Create Campaign',
onClick: () => {},
}}
/>
<div className="p-6">
{/* Page content */}
</div>
</main>
</div>
</SidebarProvider>
);
}Use SidebarPanel independently for custom layouts
function CustomLayout() {
const [isOpen, setIsOpen] = useState(true);
const [activeItem, setActiveItem] = useState('overview');
return (
<div className="flex h-screen">
<SidebarPanel
title="Settings"
isOpen={isOpen}
onToggle={() => setIsOpen(!isOpen)}
>
<SidebarItem
label="Overview"
iconOutlined={MdOutlineDashboard}
iconFilled={MdDashboard}
isActive={activeItem === 'overview'}
onClick={() => setActiveItem('overview')}
/>
<SidebarItem
label="Account"
iconOutlined={MdPeopleOutline}
iconFilled={MdPeople}
isActive={activeItem === 'account'}
onClick={() => setActiveItem('account')}
>
<SidebarSubItem
label="Profile"
isActive={activeItem === 'profile'}
onClick={() => setActiveItem('profile')}
/>
<SidebarSubItem
label="Security"
isActive={activeItem === 'security'}
onClick={() => setActiveItem('security')}
/>
</SidebarItem>
</SidebarPanel>
<main className="flex-1">
{/* Content */}
</main>
</div>
);
}Customize sidebar behavior with config options
<SidebarProvider
mainNavItems={mainNavItems}
config={{
defaultSecondaryOpen: true,
animationDuration: 300,
collapsedWidth: 64,
expandedWidth: 224,
}}
>
<div className="flex h-screen">
<SideNavigation />
<main className="flex-1">{children}</main>
</div>
</SidebarProvider>function DashboardLayout({ children }) {
return (
<SidebarProvider mainNavItems={dashboardNav}>
<div className="flex h-screen bg-bg">
<SideNavigation />
<div className="flex-1 flex flex-col overflow-hidden">
<PageSection pageTitle="Dashboard" />
<main className="flex-1 overflow-auto p-6">
{children}
</main>
</div>
</div>
</SidebarProvider>
);
}function SettingsLayout({ children }) {
const [activeSection, setActiveSection] = useState('general');
return (
<div className="flex h-screen">
<SidebarPanel title="Settings" isOpen={true}>
<SidebarItem
label="General"
isActive={activeSection === 'general'}
onClick={() => setActiveSection('general')}
/>
<SidebarItem
label="Security"
isActive={activeSection === 'security'}
onClick={() => setActiveSection('security')}
/>
<SidebarItem
label="Notifications"
isActive={activeSection === 'notifications'}
onClick={() => setActiveSection('notifications')}
/>
</SidebarPanel>
<main className="flex-1 p-6">
{children}
</main>
</div>
);
}Wrap your entire application or layout section with SidebarProvider for consistent state management.
Group related items together and use clear, descriptive labels.
Save the user's sidebar open/closed preference in local storage.
Use Material Design icons with outlined/filled variants for visual consistency.
Limit primary navigation to 5-7 items. Use secondary panels for additional items.
Keep navigation depth to 3 levels maximum for usability.
| Prop | Type | Default | Description |
|---|---|---|---|
mainNavItems | MainNavItem[] | - | Primary navigation items with icons and paths |
config | SidebarConfig | - | Configuration options for sidebar behavior |
className | string | - | Additional className for wrapper |
children | ReactNode | - | Application content |
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional className |
interface MainNavItem {
id: string;
label: string;
iconOutlined: IconType;
iconFilled: IconType;
path: string;
secondaryItems?: SecondaryNavItem[];
}
interface SecondaryNavItem {
id: string;
label: string;
path: string;
subItems?: SubNavItem[];
}interface SidebarConfig {
defaultSecondaryOpen?: boolean;
animationDuration?: number;
collapsedWidth?: number;
expandedWidth?: number;
}Semantic Navigation
The layout system uses proper semantic HTML with <nav> elements and ARIA landmarks for screen reader navigation.
<nav> elements with distinct aria-labels