Behavior

Positioning and direction

The drawer can open from any edge. Set the Open Direction prop to control the entry point. Each direction uses its own CSS transforms and border-radius rules.

Direction
Behavior

Bottom (default)

Slides up, rounded top corners, max-height capped

Top

Slides down, rounded bottom corners, accounts for admin bar

Left

Slides in from the left, full-height with rounded corners

Right

Slides in from the right, full-height with rounded corners

Drag-to-close

On open drawers, a pointer drag in the closing direction moves the drawer and dims the overlay proportionally. Releasing past the close threshold (25% of the drawer dimension) closes it — otherwise it snaps back.

  • Velocity detection — fast swipes close immediately regardless of distance

  • Over-drag dampening — dragging past the open position applies logarithmic resistance

  • Scroll awareness — dragging is suppressed for 100ms after scrolling inside the drawer body, preventing scroll-to-close conflicts

  • Handle-only mode — restrict drag to the .c-drawer__handle element with the handleOnly option

  • No-drag mode — disable swipe-to-close entirely with the Disable Drag to Close prop

  • cursor: grabbing is applied globally during drag via .c-drawer--dragging

Snap points

Vertical drawers (top or bottom) can rest at multiple heights instead of just open or closed. Add data-snap-point to any element inside the drawer body and the drawer will snap to that element's edge as the user drags.

Use "top" to snap to the element's top edge, "bottom" to snap to its bottom edge. The drawer opens to the smallest snap point first, and dragging below it closes the drawer. Snap points are ignored for left/right drawers.

Snap navigation buttons

Add data-snap-to to any button inside the drawer to step between snap points on click — useful for discoverability and for visitors who won't drag.

  • "next" expands to the next-larger snap point. "previous" collapses to the next-smaller one.

  • At the extremes the button does nothing — "next" no-ops at full height, "previous" no-ops at the smallest snap point. It never closes the drawer.

  • Use a real <button> element. The component does not synthesize keyboard or focus behavior, so a <div> would not be operable by keyboard or screen-reader users.

  • The button's availability is reflected with aria-disabled at the extremes. Style the inactive state with [data-snap-to][aria-disabled="true"] if so you desire.

  • On non-snap drawers (no data-snap-point elements, or left/right direction) the button is ignored — it's inert markup.

Nested drawers

You can open a drawer from inside another drawer. When this happens, the parent scales back slightly while the child opens on top, then restores when the child closes.

1

Add a Drawer component to the page

This is your parent drawer.

2

Inside the body of that drawer, insert a second Drawer

This is your child drawer.

3

Give the child drawer its own Unique ID

4

Add a button inside the parent drawer's body

Set the child's Open Trigger Selector to match that button.

5

The component handles everything else

The child drawer is moved to the correct position, the parent scales back on open, and focus stays within the active drawer.

A few things to keep in mind:

  • Passive drawers cannot be nested — they don't participate in the stack.

  • The child drawer gets its own close gesture and close button. Closing it returns the parent to full size.

  • You can nest multiple levels deep, but one or two is the practical limit for usability.

Passive mode

Passive mode renders the drawer as a non-modal notification bar. It has no overlay, cannot trap focus, and does not lock body scroll.

  • Overlay is hidden (CSS managed), body scroll is not locked

  • Click outside does not close — only drag or a close button dismisses it

  • Trigger elements do not receive aria-expanded updates

  • pointer-events: none on the wrapper lets users interact with content beneath

  • Ideal for bottom-sheet notifications that don't demand immediate attention

Enable with the Passive Mode prop or the passive constructor option.

Auto-open and persistence

Drawers can open automatically on page load with configurable delay and storage-backed frequency control.

Frequency option
Behavior

every-visit

Always show (no persistence)

until-dismissed

Show until the user closes it, then never again

once

Show one time only (recorded on open)

after-delay

Re-show after a configurable duration since last dismissal

Duration strings accept 30s, 2h, 7d, or bare numbers (treated as hours). All persistence uses localStorage with keys namespaced under etch-drawer-.

Configure with the Auto Open, Auto Open Delay, Auto Open Reshow, and Auto Open Reshow Delay props.

Etch builder integration

Inside the Etch visual builder iframe, the Drawer disables all gesture handling and event binding. The builder controls open/close via the Show In Builder prop, which toggles visibility on the wrapper element through a MutationObserver.

  • No drag, no pointer events, no keyboard bindings

  • CSS rules handle visibility from the prop value

  • The open/close class toggle still synchronizes data-state for preview rendering

Last updated