SutraUI.Drawer (Sutra UI v0.3.0)
View SourceA collapsible drawer navigation component with mobile toggle support.
The drawer provides a responsive navigation panel that can be toggled open/closed.
By default, drawers are closed on desktop and require a trigger button or programmatic
control to open. Use the open attribute to make a drawer initially open.
It supports:
- Mobile overlay mode with backdrop
- Desktop persistent mode (via
openattribute) - Left or right positioning
- Collapsible submenu sections
- Active page highlighting
- Custom header and footer sections
JavaScript Hook
The drawer requires JavaScript for:
- Mobile toggle functionality
- Close on backdrop click
- Close on click outside (when drawer is open)
- Responsive breakpoint handling
- Active page link detection and highlighting
- Managing open/closed state
The component uses a colocated JavaScript hook that is initialized by
providing a unique id attribute.
Click Outside to Close
When the drawer is open, clicking anywhere outside of it (except on trigger buttons) will automatically close the drawer. This provides an intuitive way to dismiss the drawer without requiring an explicit close button.
Examples
Basic drawer with trigger button
<.drawer_trigger for="main-drawer" /> <.drawer id="main-drawer">
</.drawer>
Drawer initially open on desktop
<.drawer_trigger for="app-drawer" /> <.drawer id="app-drawer" side="left" open> <:header> <div class="flex items-center gap-2 p-2">
<img src="/logo.svg" alt="Logo" class="w-8 h-8" />
<span class="font-semibold">My App</span></:header>
<.drawer_group label="Main"> <.drawer_item href="/">Home</.drawer_item> <.drawer_item href="/dashboard">Dashboard</.drawer_item> </.drawer_group>
<:footer> <.drawer_item href="/settings">Settings</.drawer_item> </:footer> </.drawer>
Drawer with collapsible sections
<.drawer_trigger for="nav-drawer" /> <.drawer id="nav-drawer"> <.drawer_group label="Navigation"> <.drawer_item href="/">Overview</.drawer_item>
<.drawer_submenu label="Projects" open>
<.drawer_item href="/projects/active">Active</.drawer_item>
<.drawer_item href="/projects/archived">Archived</.drawer_item></.drawer_submenu>
<.drawer_item href="/team">Team</.drawer_item> </.drawer_group> </.drawer>
Right-side drawer with custom trigger
<.drawer_trigger for="filter-drawer" variant="outline">
Toggle Filters</.drawer_trigger> <.drawer id="filter-drawer" side="right"> <.drawer_group label="Filters"> <p>Filter options here...</p> </.drawer_group> </.drawer>
Programmatic Control
You can control the drawer state from JavaScript using custom events:
// Toggle drawer
document.dispatchEvent(new CustomEvent('sutra-ui:drawer', {
detail: { id: 'main-drawer' }
}));
// Open drawer
document.dispatchEvent(new CustomEvent('sutra-ui:drawer', {
detail: { id: 'main-drawer', action: 'open' }
}));
// Close drawer
document.dispatchEvent(new CustomEvent('sutra-ui:drawer', {
detail: { id: 'main-drawer', action: 'close' }
}));Accessibility
- Uses semantic
<aside>and<nav>elements - Includes proper ARIA labels and
aria-hiddenstate - Sets
inertattribute when closed to prevent keyboard navigation - Automatically manages focus when opened/closed
- Active page links marked with
aria-current="page"
Mobile Behavior
On mobile (below breakpoint):
- Drawer becomes a full-screen overlay
- Clicking outside the nav closes the drawer
- Clicking links automatically closes the drawer
- Use
data-keep-mobile-drawer-openattribute to prevent auto-close on specific elements
CSS Variables
The drawer uses these CSS variables:
--drawer-width: Desktop drawer width (default: 16rem)--drawer-mobile-width: Mobile drawer width (default: 18rem)--drawer: Background color--drawer-foreground: Text color--drawer-accent: Hover/active background--drawer-accent-foreground: Hover/active text color--drawer-border: Border color--drawer-ring: Focus ring color
Summary
Functions
Renders a drawer navigation component.
Renders a drawer group with an optional label/heading.
Renders a drawer navigation item (link).
Renders a separator/divider in the drawer.
Renders a collapsible drawer submenu.
Renders a button to toggle the drawer open/closed.
Functions
Renders a drawer navigation component.
Attributes
id(required) - Unique identifier for the drawer (required for hook)side- Which side to position the drawer ("left" or "right", default: "left")open- Initial open state for desktop (default: false)mobile_open- Initial open state for mobile (default: false)breakpoint- Pixel width for mobile breakpoint (default: 768)label- ARIA label for navigation (default: "Drawer navigation")class- Additional CSS classes for the aside container
Slots
header- Optional header content (rendered in nav > header)footer- Optional footer content (rendered in nav > footer)inner_block(required) - Main drawer content (rendered in nav > section)
Toggle Button
Use drawer_trigger/1 to create a toggle button for the drawer:
<.drawer_trigger for="my-drawer" />
<.drawer id="my-drawer">
<!-- drawer content -->
</.drawer>Attributes
id(:string) (required) - Unique identifier for the drawer (required for hook).side(:string) - Which side to position the drawer. Defaults to"left". Must be one of"left","right","top", or"bottom".open(:boolean) - Initial open state for desktop. Defaults tofalse.mobile_open(:boolean) - Initial open state for mobile. Defaults tofalse.breakpoint(:integer) - Pixel width for mobile breakpoint. Defaults to768.label(:string) - ARIA label for navigation. Defaults to"Drawer navigation".class(:string) - Additional CSS classes. Defaults tonil.
Slots
header- Optional header content.footer- Optional footer content.inner_block(required) - Main drawer content.
Renders a drawer group with an optional label/heading.
Attributes
label- Optional heading text for the groupclass- Additional CSS classes
Examples
<.drawer_group label="Navigation">
<.drawer_item href="/">Home</.drawer_item>
<.drawer_item href="/about">About</.drawer_item>
</.drawer_group>
<.drawer_group>
<.drawer_item href="/settings">Settings</.drawer_item>
</.drawer_group>Attributes
label(:string) - Optional heading for the group. Defaults tonil.class(:string) - Additional CSS classes. Defaults tonil.
Slots
inner_block(required)
Renders a drawer navigation item (link).
Attributes
href(required) - URL for the linkvariant- Visual variant ("default" or "outline")size- Size variant ("default", "sm", or "lg")current- Whether this is the current pageclass- Additional CSS classesrest- Additional HTML attributes
Examples
<.drawer_item href="/">Home</.drawer_item>
<.drawer_item href="/dashboard" variant="outline">
Dashboard
</.drawer_item>
<.drawer_item href="/settings" current>
Settings
</.drawer_item>
<.drawer_item href="/profile" size="sm">
Profile
</.drawer_item>Attributes
href(:string) (required) - URL for the link.variant(:string) - Visual variant. Defaults to"default". Must be one of"default", or"outline".size(:string) - Size variant. Defaults to"default". Must be one of"default","sm", or"lg".current(:boolean) - Whether this is the current page. Defaults tofalse.class(:string) - Additional CSS classes. Defaults tonil.- Global attributes are accepted. Additional HTML attributes. Supports all globals plus:
["target", "rel", "data-ignore-current", "data-keep-mobile-drawer-open"].
Slots
inner_block(required)
Renders a separator/divider in the drawer.
Examples
<.drawer_separator />
Renders a button to toggle the drawer open/closed.
Attributes
for(required) - The ID of the drawer to togglevariant- Visual variant. One ofprimary,secondary,destructive,outline,ghost,link. Defaults toghost.size- Size variant. One ofdefault,sm,lg,icon. Defaults toicon.class- Additional CSS classes
Examples
Default icon button (hamburger menu)
<.drawer_trigger for="main-drawer" />
Custom variant and size
<.drawer_trigger for="main-drawer" variant="outline" size="sm" />
Custom content
<.drawer_trigger for="main-drawer" variant="primary"> <span>Menu</span> </.drawer_trigger>
Attributes
for(:string) (required) - ID of the drawer to toggle.variant(:string) - Visual style variant. Defaults to"ghost". Must be one of"primary","secondary","destructive","outline","ghost", or"link".size(:string) - Size variant. Defaults to"icon". Must be one of"default","sm","lg", or"icon".class(:string) - Additional CSS classes. Defaults tonil.- Global attributes are accepted. Additional HTML attributes.
Slots
inner_block- Custom button content (defaults to hamburger icon).