Skip to content

components/Overlay

import { … } from 'zidane-ui'ui/src/components/Overlay.tsx

ConfirmDialog in an Overlay
Overlay + zg-float dialog
Lightbox

Components#

OverlayComponent#

Renders a layer above the page through a portal: a scrim that fades in and out, with the surface drawn by children. It adds scroll lock, Esc to close, focus return on close and, with trapFocus, a modal focus trap that makes the rest of the page inert. The layer stays mounted until the scrim's exit finishes.

TypeScript
function Overlay(props: OverlayProps): ReactPortal | null
Parameters
NameTypeDescription
propsOverlayProps

Component props.

ReactPortal | null
Overlay props
NameTypeDefaultDescription
children(state: 'open' | 'closed') => ReactNode

Renders the surface. It receives open or closed, to put on the surface's data-state. The state is closed on the first frame and during exit, so CSS has a from-state.

className?string

Position of the layer (the scrim fills it).

closeOnEscape?booleantrue

Close the layer on Esc while it is the topmost layer.

exitMs?deprecatednumber

Exit duration in milliseconds. Ignored.

Deprecated. The exit lasts as long as its motion; kept so older callers compile.

inertSelector?string

Elements made inert while open (e.g. main, footer).

onClose() => void

Called when the scrim is clicked, or on Esc when closeOnEscape is on.

openboolean

Whether the layer is shown.

scrimClassName?string''

Extra classes on the scrim.

style?CSSProperties

Inline styles on the root element, merged after the component's own.

trapFocus?booleantrue

Make the layer modal: focus moves in on open, Tab stays inside, and the rest of body goes inert.

ui/src/components/Overlay.tsx:250

Functions#

useLayerFunction#

The behaviour of a layer whose root (layerRef, a child of body) is portaled by the caller: scroll lock, stacking, Esc, focus and the inert background, as described above. Overlay and Lightbox both run on it. Returns whether this layer is the topmost one right now, for a caller that handles more keys of its own.

TypeScript
function useLayer(
  open: boolean,
  layerRef: RefObject<HTMLElement | null>,
  options?: LayerOptions,
): () => boolean
Parameters
NameTypeDefaultDescription
openboolean

Whether the layer is open. Scroll lock, stacking, Esc handling and the focus trap run only while it is.

layerRefRefObject<HTMLElement | null>

Ref to the layer's root element, a child of body the caller portals.

options?LayerOptions{}

Esc handling, focus trap and inert background options, see LayerOptions.

() => boolean

ui/src/components/Overlay.tsx:110

Interfaces#

LayerOptionsInterface#

Options of useLayer.

TypeScript
interface LayerOptions
LayerOptions properties
NameTypeDescription
inertSelector?string

Elements made inert while open (e.g. main, footer).

initialFocus?RefObject<HTMLElement | null>

Where focus lands on open when nothing inside took it already; else the first control, else the layer.

onEscape?() => void

Called on Esc while this is the topmost layer. Omit to leave Esc alone (it still never reaches a layer below).

trapFocus?boolean

Modal: focus moves in, Tab stays in, the rest of body goes inert. Default true.

ui/src/components/Overlay.tsx:87

OverlayPropsInterface#

Props for Overlay.

TypeScript
interface OverlayProps
OverlayProps properties
NameTypeDefaultDescription
children(state: 'open' | 'closed') => ReactNode

Renders the surface. It receives open or closed, to put on the surface's data-state. The state is closed on the first frame and during exit, so CSS has a from-state.

className?string

Position of the layer (the scrim fills it).

closeOnEscape?booleantrue

Close the layer on Esc while it is the topmost layer.

exitMs?deprecatednumber

Exit duration in milliseconds. Ignored.

Deprecated. The exit lasts as long as its motion; kept so older callers compile.

inertSelector?string

Elements made inert while open (e.g. main, footer).

onClose() => void

Called when the scrim is clicked, or on Esc when closeOnEscape is on.

openboolean

Whether the layer is shown.

scrimClassName?string''

Extra classes on the scrim.

style?CSSProperties

Inline styles on the root element, merged after the component's own.

trapFocus?booleantrue

Make the layer modal: focus moves in on open, Tab stays inside, and the rest of body goes inert.

ui/src/components/Overlay.tsx:202