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
Basic
Open with command="--show" on a trigger button. Slides in from the left.
This drawer slides in from the left.
Code
<button
type="button"
class="l-button"
command="--show"
commandfor="drawer-default"
>
Open drawer
</button>
<l-drawer
id="drawer-default"
title="Drawer"
>
<button
slot="close"
type="button"
class="l-close"
data-appearance="ring"
aria-label="Close"
command="--hide"
commandfor="drawer-default"
></button>
<p>This drawer slides in from the left.</p>
</l-drawer>Placement
Set placement to control which edge the drawer slides from. Defaults to start (inline-start). Use placement="end" for the inline-end edge or placement="bottom" for the block-end edge.
End
This drawer slides in from the right.
Code
<button
type="button"
class="l-button"
command="--show"
commandfor="drawer-end"
>
Open right drawer
</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 right.</p>
</l-drawer>Bottom
This drawer slides in from the bottom.
Code
<button
type="button"
class="l-button"
command="--show"
commandfor="drawer-bottom"
>
Open bottom drawer
</button>
<l-drawer
id="drawer-bottom"
title="Drawer"
placement="bottom"
>
<button
slot="close"
type="button"
class="l-close"
data-appearance="ring"
aria-label="Close"
command="--hide"
commandfor="drawer-bottom"
></button>
<p>This drawer slides in from the bottom.</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
Right-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' | 'bottom' | undefinedProperty- Edge the drawer slides in from. Defaults to the start (inline-start) edge.
titlestringProperty- Dialog title rendered in the header.
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
showEvent- Fired when the drawer opens. Not cancelable.
after-showEvent- Fired after the open animation completes.
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.
Slots
(default)Slot- Body content.
closeSlot- Close button (typically
<button class="l-close">). footerSlot- Footer actions.
titleSlot- Custom heading element. Overrides the default
<h2>rendered from thetitleproperty.
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 forbottom). --border-radiusdefault:6pxCustom property- Drawer border radius on the inner edges.
--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.