Drawer <l-drawer>
Drawers display supplementary content in a panel that slides in from a screen edge. Commonly used for navigation menus, filters, and detail views without leaving the current page.
<l-drawer>Options
Placement
Set placement to the edge the drawer slides from — start (default, inline-start), end (inline-end), top (block-start), or bottom (block-end). Open with command="--show" on a trigger button; the buttons below open one drawer per edge.
This drawer slides in from the start.
This drawer slides in from the top.
This drawer slides in from the bottom.
This drawer slides in from the end.
Code
<button
type="button"
class="l-button"
command="--show"
commandfor="drawer-end"
>
<l-icon name="lucide:panel-right"></l-icon>
End
</button>
<l-drawer
id="drawer-end"
title="Drawer"
placement="end"
>
<button
slot="close"
type="button"
class="l-close"
data-appearance="ring"
aria-label="Close"
command="--hide"
commandfor="drawer-end"
></button>
<p>This drawer slides in from the end.</p>
</l-drawer>Inset
Add inset to float the drawer away from the viewport edges with a uniform gap and rounded corners. Tune the gap with the --inset-gap CSS custom property. Works with every placement — the buttons below open one drawer per edge.
This drawer floats away from the edges with rounded corners.
This drawer floats away from the edges with rounded corners.
This drawer floats away from the edges with rounded corners.
This drawer floats away from the edges with rounded corners.
Code
<button
type="button"
class="l-button"
command="--show"
commandfor="drawer-inset"
>
<l-icon name="lucide:panel-right"></l-icon>
End
</button>
<l-drawer
id="drawer-inset"
title="Drawer"
placement="end"
inset
>
<button
slot="close"
type="button"
class="l-close"
data-appearance="ring"
aria-label="Close"
command="--hide"
commandfor="drawer-inset"
></button>
<p>This drawer floats away from the edges with rounded corners.</p>
</l-drawer>Light dismiss
Add light-dismiss to close when the backdrop is clicked.
Click the backdrop or press Escape to close.
Code
<button
type="button"
class="l-button"
command="--show"
commandfor="drawer-light-dismiss"
>
Open drawer
</button>
<l-drawer
id="drawer-light-dismiss"
title="Drawer"
light-dismiss
>
<button
slot="close"
type="button"
class="l-close"
data-appearance="ring"
aria-label="Close"
command="--hide"
commandfor="drawer-light-dismiss"
></button>
<p>Click the backdrop or press Escape to close.</p>
</l-drawer>Examples
Navigation
Mobile navigation menu with link items.
Code
<button
type="button"
class="l-button"
command="--show"
commandfor="drawer-nav"
>
Menu
</button>
<l-drawer
id="drawer-nav"
title="Navigation"
>
<button
slot="close"
type="button"
class="l-close"
data-appearance="ring"
aria-label="Close"
command="--hide"
commandfor="drawer-nav"
></button>
<nav>
<ul class="flex flex-col gap-1">
<li>
<a
href="#"
class="flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium hover:bg-gray-100"
>Home</a
>
</li>
<li>
<a
href="#"
class="flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium hover:bg-gray-100"
>Products</a
>
</li>
<li>
<a
href="#"
class="flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium hover:bg-gray-100"
>Orders</a
>
</li>
<li>
<a
href="#"
class="flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium hover:bg-gray-100"
>Customers</a
>
</li>
<li>
<a
href="#"
class="flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium hover:bg-gray-100"
>Settings</a
>
</li>
</ul>
</nav>
</l-drawer>Filters
End-side filter panel with a footer for actions.
Code
<button
type="button"
class="l-button"
command="--show"
commandfor="drawer-filters"
>
Filters
</button>
<l-drawer
id="drawer-filters"
title="Filters"
placement="end"
style="--size: 380px"
>
<button
slot="close"
type="button"
class="l-close"
data-appearance="ring"
aria-label="Close"
command="--hide"
commandfor="drawer-filters"
></button>
<div class="flex flex-col gap-6">
<fieldset>
<legend class="text-sm font-medium mb-2">Category</legend>
<div class="flex flex-col gap-2">
<label class="flex items-center gap-2 text-sm"
><input
type="checkbox"
checked
/>
Electronics</label
>
<label class="flex items-center gap-2 text-sm"><input type="checkbox" /> Clothing</label>
<label class="flex items-center gap-2 text-sm"><input type="checkbox" /> Books</label>
</div>
</fieldset>
<fieldset>
<legend class="text-sm font-medium mb-2">Price range</legend>
<div class="flex flex-col gap-2">
<label class="flex items-center gap-2 text-sm"
><input
type="radio"
name="price"
checked
/>
All prices</label
>
<label class="flex items-center gap-2 text-sm"
><input
type="radio"
name="price"
/>
Under $50</label
>
<label class="flex items-center gap-2 text-sm"
><input
type="radio"
name="price"
/>
$50 – $100</label
>
<label class="flex items-center gap-2 text-sm"
><input
type="radio"
name="price"
/>
Over $100</label
>
</div>
</fieldset>
</div>
<menu slot="footer">
<button
type="button"
class="l-button"
command="--hide"
commandfor="drawer-filters"
>
Cancel
</button>
<button
type="button"
class="l-button"
data-variant="primary"
>
Apply
</button>
</menu>
</l-drawer>Accessibility
Criteria
- Role
Rendered as a native
<dialog>in the shadow root — built-indialogrole and modal semanticsWCAG4.1.2RGAA7.1- Focus management
Focus is trapped inside the modal; moves to the first focusable element on open
WCAG2.4.3RGAA10.7- Focus restoration
Focus returns to the trigger element when the drawer closes
WCAG2.4.3- Close button
Consumer provides the close button via
slot="close"witharia-label="Close"WCAG2.4.6- Motion
Slide animation respects
prefers-reduced-motionWCAG2.3.3
Keyboard interactions
API reference
Importing
import 'luxen-ui/drawer';Attributes & Properties
placement'start' | 'end' | 'top' | 'bottom' | undefinedProperty- Edge the drawer slides in from. Defaults to the start (inline-start) edge.
insetbooleandefault:falseProperty- Detach the drawer from the viewport edges, floating it with a uniform gap and rounded corners.
titlestringProperty- Dialog title rendered in the header and used as the dialog's accessible name.
openbooleandefault:falseProperty- Whether the dialog is open.
light-dismissbooleandefault:falseProperty- Close when the backdrop is clicked.
without-headerbooleandefault:falseProperty- Hide the header entirely (title and close slot).
Commands
Open and close the drawer by toggling its open property, or via the Invoker Commands API from any light-DOM button. Custom commands must start with --.
INFO
The Invoker Commands API is ✓ Baseline Newly Available (since 2025-12-12). For older browser versions, load the invokers-polyfill once at app startup:
import 'invokers-polyfill';--showCommand- Sets
open = true. --hideCommand- Sets
open = false.
Events
showcancelableEvent- Fired when the drawer is about to open. Cancelable — call
event.preventDefault()to keep it closed. after-showEvent- Fired after the open animation completes. Not cancelable.
hidecancelableEvent- Fired when the drawer is about to close. Cancelable — call
event.preventDefault()to keep it open. after-hideEvent- Fired after the close animation completes. Not cancelable.
Slots
(default)Slot- Body content.
titleSlot- Custom heading element. Overrides the default
<h2>rendered from thetitleproperty. Also provides the dialog's accessible name. closeSlot- Close button (typically
<button class="l-close">). footerSlot- Footer actions.
CSS parts
dialogPart- The native
<dialog>element. headerPart- The header wrapper containing the title and close slot.
titlePart- The drawer title heading.
bodyPart- The body wrapper around the default slot.
footerPart- The footer wrapper around the footer slot.
CSS custom properties
--sizedefault:320pxCustom property- Drawer size on the axis perpendicular to its edge (width for
start/end, height fortop/bottom). --border-radiusdefault:6pxCustom property- Drawer border radius on the inner edges (all corners when
inset). --inset-gapdefault:1remCustom property- Gap between the drawer and the viewport edges when
insetis set. --shadowCustom property- Drop shadow applied to the floating panel when
insetis set. Set tononeto remove it. --show-durationdefault:200msCustom property- Open transition duration.
--hide-durationdefault:200msCustom property- Close transition duration.
--backdropCustom property- Backdrop color.
--widthdefault:31remCustom property- Dialog width.
--paddingdefault:1.5remCustom property- Padding applied to the header, footer, and inline-padding of the body. Set to
0to remove all internal spacing (e.g. for edge-to-edge media). --backdrop-blurdefault:0Custom property- Backdrop blur amount (any CSS length).
0means no blur; set e.g.4pxfor a subtle frost.