Navigation Drawer
MD3 navigation drawer — the sidebar of a dashboard, in all three of the shapes a dashboard needs it in.
Walkthrough
1. Standard
Sections group items and badge rides on the end of a row — the sidebar of a dashboard with more pages than one flat list can hold.
<script lang="ts"> import { NavigationDrawer, NavigationDrawerItem, NavigationDrawerSection } from 'omaris'; let selected = $state('inbox');</script><div class="h-80 w-72 max-w-full overflow-hidden rounded-shape-lg border border-border"> <NavigationDrawer label="Mail"> <NavigationDrawerSection label="Mail"> <NavigationDrawerItem label="Inbox" badge={12} selected={selected === 'inbox'} onclick={() => (selected = 'inbox')} /> <NavigationDrawerItem label="Sent" selected={selected === 'sent'} onclick={() => (selected = 'sent')} /> </NavigationDrawerSection> <NavigationDrawerSection label="Commerce" divider> <NavigationDrawerItem label="Orders" badge="New"> {#snippet submenu()} <NavigationDrawerItem label="Open" badge={4} /> <NavigationDrawerItem label="Shipped" /> {/snippet} </NavigationDrawerItem> </NavigationDrawerSection> </NavigationDrawer></div> 2. Collapsed rail
Collapsed, it becomes MD3's rail: icons only, labels as tooltips. What a laptop wants once the content needs the width more than the labels.
<script lang="ts"> import { Button, NavigationDrawer, NavigationDrawerItem } from 'omaris'; let collapsed = $state(true);</script>{#snippet overview()} ...{/snippet}{#snippet orders()} ...{/snippet}{#snippet team()} ...{/snippet}<div class="flex w-full flex-col items-start gap-3"> <Button size="xs" variant="outlined" onclick={() => (collapsed = !collapsed)}> {collapsed ? 'Expand' : 'Collapse'} </Button> <div class="h-64 overflow-hidden rounded-shape-lg border border-border"> <NavigationDrawer bind:collapsed label="Sections"> <NavigationDrawerItem label="Overview" selected> {#snippet icon()}{@render overview()}{/snippet} </NavigationDrawerItem> <NavigationDrawerItem label="Orders"> {#snippet icon()}{@render orders()}{/snippet} </NavigationDrawerItem> <NavigationDrawerItem label="Team"> {#snippet icon()}{@render team()}{/snippet} </NavigationDrawerItem> </NavigationDrawer> </div></div> 3. Modal
mode="modal" slides it over the page on a scrim. In an app, responsive is the one to reach for: a sidebar above the breakpoint, this modal below it, so you write one drawer instead of two.
<script lang="ts"> import { Button, NavigationDrawer, NavigationDrawerItem } from 'omaris'; let open = $state(false);</script><Button variant="tonal" onclick={() => (open = true)}>Open the drawer</Button><NavigationDrawer bind:open mode="modal" label="Sections"> {#snippet header()} <span class="px-2 py-1 text-title-md">omaris</span> {/snippet} <NavigationDrawerItem label="Overview" selected /> <NavigationDrawerItem label="Orders" badge={12} /> <NavigationDrawerItem label="Settings" /></NavigationDrawer>