Skip to main content
DismissableLayer is a component that listens for interactions outside of its boundaries and provides callbacks for handling dismissal. It’s essential for building modals, popovers, dropdowns, and other overlay components that should close when users interact outside them.

Installation

Components

DismissableLayer

The main component that wraps content and detects outside interactions.

DismissableLayerBranch

Marks a part of the DOM tree as belonging to the dismissable layer, preventing dismissal when interacting with it.

Props

boolean
When true, hover/focus/click interactions are disabled on elements outside the layer. Users must click twice: once to dismiss the layer, then again to interact with outside elements.Default: false
(event: KeyboardEvent) => void
Event handler called when the Escape key is pressed. Call event.preventDefault() to prevent dismissal.
(event: PointerDownOutsideEvent) => void
Event handler called when a pointer down event occurs outside the layer. Call event.preventDefault() to prevent dismissal.
(event: FocusOutsideEvent) => void
Event handler called when focus moves outside the layer. Call event.preventDefault() to prevent dismissal.
(event: PointerDownOutsideEvent | FocusOutsideEvent) => void
Event handler called for any interaction outside the layer (pointer down or focus). Called before specific handlers. Call event.preventDefault() to prevent dismissal.
() => void
Handler called when the layer should be dismissed (after outside interaction or Escape key, if not prevented).

Usage

Basic Modal

With Disabled Outside Pointer Events

Preventing Dismissal on Specific Interactions

Using Branches

Nested Dismissable Layers

Custom Interaction Handling

Event Details

PointerDownOutsideEvent

A custom event dispatched when pointer down occurs outside the layer.

FocusOutsideEvent

A custom event dispatched when focus moves outside the layer.

Behavior

Layer Stacking

Multiple DismissableLayer components create a stack:
  • Only the topmost layer responds to outside interactions
  • Nested layers are handled correctly
  • Lower layers are paused while upper layers are active

Pointer Events

When disableOutsidePointerEvents={true}:
  • Body pointer events are set to none
  • Only the highest layer with this prop enabled is interactive
  • Prevents accidental interaction with underlying content

Branches

DismissableLayerBranch marks elements as “inside” the layer:
  • Interactions with branches don’t trigger dismissal
  • Useful for tooltips, nested popovers, or portaled content
  • Branches are tracked globally across all layers

Accessibility

Always provide a way to dismiss layers using the keyboard (Escape key is handled automatically) to ensure keyboard users aren’t trapped.
Use disableOutsidePointerEvents carefully as it requires users to click twice to interact with outside content, which may be confusing. Reserve it for critical interactions like modals.

Notes

The component uses custom events (dismissableLayer.pointerDownOutside and dismissableLayer.focusOutside) to communicate between layers and handle stacking properly.
Escape key handling uses useEscapeKeydown internally with capture phase event listeners to ensure the topmost layer handles the event first.
When multiple layers exist, only the topmost layer (highest in the stack) will respond to outside interactions. Lower layers automatically ignore events until they become the topmost layer.