Skip to content

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.

HTML tag<l-drawer>
Native HTML
Progressive
Custom
Shadow DOM
Custom Element · Shadow DOM

Options

Basic

Open with command="--show" on a trigger button. Slides in from the left.

This drawer slides in from the left.

Code
html
<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
html
<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
html
<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
html
<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

Mobile navigation menu with link items.

Code
html
<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.

Category
Price range
Code
html
<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-in dialog role and modal semantics

WCAG4.1.2
RGAA7.1
Accessible name

The title property is rendered as an <h2> inside the drawer header

WCAG4.1.2
RGAA11.1
Focus management

Focus is trapped inside the modal; moves to the first focusable element on open

WCAG2.4.3
RGAA10.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" with aria-label="Close"

WCAG2.4.6
Motion

Slide animation respects prefers-reduced-motion

WCAG2.3.3

Keyboard interactions

Escape
Closes the drawer
Tab
Cycles focus through focusable elements inside the drawer
ShiftTab
Cycles focus backward through focusable elements inside the drawer

API reference

Importing

js
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:

js
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 the title property.

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 for bottom).
--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 0 to remove all internal spacing (e.g. for edge-to-edge media).
--backdrop-blurdefault:0Custom property
Backdrop blur amount (any CSS length). 0 means no blur; set e.g. 4px for a subtle frost.