unscripted/ui

Drawer

A panel that slides in from the edge — same native <dialog> as the modal, just anchored to the side and sliding instead of scaling. Focus trap, Esc and light dismiss come free.

dialogexit animations

How it works

It’s the Dialog with two changes: pin it to an edge, and slide instead of scale. Everything else (top layer, focus trap, inert background, Esc, declarative open) is identical, because it’s the same native <dialog>.

  • my-0 mr-0 ml-auto overrides Tailwind’s zeroed dialog margins to push the panel flush against the right edge; h-dvh max-h-dvh makes it full height. Swap to ml-0 mr-auto for a left drawer, or mt-auto mb-0 w-full for a bottom sheet.
  • The slide: the panel sits at translate-x-full (off-screen right) by default, open:translate-x-0 brings it in, and starting:open:translate-x-full sets the entry frame. transition-all transition-discrete (transition-behavior: allow-discrete) keeps display/overlay alive so the panel slides out too, instead of vanishing.
  • commandfor + command="show-modal" opens it declaratively; closedby="any" gives you backdrop-click dismiss. The header’s close button is just command="close".
  • Inside, a flex flex-col with a fixed header and footer and a flex-1 overflow-y-auto body. Long content scrolls while the footer stays put.
  • The panel and that scrollable body both get overscroll-none, and the backdrop gets backdrop:overflow-hidden backdrop:overscroll-contain, so scrolling the cart to its end neither drags the page behind it nor rubber-bands the list. Needs Chrome 144+; elsewhere the background scrolls, nothing breaks.

Accessibility

Same as Dialog: focus moves into the drawer and is trapped, the page behind goes inert, Esc closes it, and focus returns to the trigger on close. Like the dialog, the panel needs an accessible name: the demo points aria-labelledby at the heading, so it announces as “Your cart”.

Reduced motion

The global prefers-reduced-motion rule in the token paste collapses the slide to an instant show/hide. The drawer still opens and closes, it just doesn’t travel.

Browser support

Minimum stable version per engine, resolved at build time from MDN's browser-compat-data; Baseline status from the official web-features dataset. Everything degrades gracefully — the “when missing” column is the actual behavior, not a broken page.

FeatureChromeEdgeFirefoxSafariWhen missing
<dialog> elementBaseline · widely available37799815.4Baseline, widely available. Modal behavior, focus handling and Esc-to-close are native.
Invoker commands (commandfor / command)Baseline 2025 · newly available13513514426.2Buttons with commandfor do nothing. Until Baseline reaches your audience, open the dialog with a 3-line shim or from your framework.
closedby="any" (light dismiss)Limited availability134134141Esc still closes the dialog (platform default); clicking the backdrop does not.
Entry/exit animations (allow-discrete + @starting-style)Baseline 2024 · newly available11711712917.5Elements appear and disappear instantly. Nothing breaks — you just lose the animation.

† @supports cannot test at-rules, so the badge checks transition-behavior: allow-discrete, which co-shipped with @starting-style in every engine.

‡ HTML feature — @supports can only test CSS, and we ship no JS to detect it, so it gets no live badge.