Skip to content
Ndop UI

Dialog primitive

Headless Dialog: the behavior, keyboard support and ARIA of the WAI-ARIA Dialog (Modal) pattern, with no styles.

Import

Primitives ship in the @ndop/primitives package and have no styles. Their state is on data attributes for you to style. The styled Dialog is built on this one.

import {
  NdDialog,
  NdDialogClose,
  NdDialogContent,
  NdDialogDescription,
  NdDialogOverlay,
  NdDialogPortal,
  NdDialogTitle,
  NdDialogTrigger,
} from '@ndop/primitives/dialog';

Accessibility

Implements the Dialog (Modal) pattern of the WAI-ARIA Authoring Practices.

Keyboard

Keys the component handles.

Key Action
TabMoves focus to the next focusable element inside the dialog; from the last one, wraps to the first.
ShiftTabMoves focus to the previous focusable element inside the dialog; from the first one, wraps to the last.
EscapeCloses the dialog, unless closeOnEscape is false.

Focus

  • On open: focus moves to the first focusable element in the content, or to the content element itself when it has none.
  • While open: focus is trapped in the content.
  • On close: focus returns to the element that had it before opening, usually the trigger.

Right-to-left

Nothing mirrors: the dialog is centered, and Tab order follows the DOM.

API reference

NdDialog

[ndDialog]from @ndop/primitives/dialog

Root of a modal dialog (WAI-ARIA Dialog (Modal) pattern). Holds the open state and renders the ng-template[ndDialogPortal] content into a CDK overlay while open: page scroll is blocked, focus is trapped in the content and returned on close, and Escape closes. Put it on an ng-container so it adds no element. The dialog never renders open on the server; an initial open state takes effect after hydration.

NdDialog binding Type Default
[defaultOpen]
Initial open state when open is not bound.
booleanfalse
[closeOnEscape]
Whether Escape closes the dialog.
booleantrue
[closeOnOverlayClick]
Whether a click on [ndDialogOverlay] closes the dialog.
booleantrue
[(open)]
Whether the dialog is open. Two-way bindable with [(open)].
booleanfalse

NdDialogClose

[ndDialogClose]from @ndop/primitives/dialog

Button that closes its NdDialog.

NdDialogContent

[ndDialogContent]role dialogfrom @ndop/primitives/dialog

The dialog box: role="dialog", aria-modal="true", tabindex="-1", and aria-labelledby / aria-describedby pointing at the title and description. Focus is trapped inside it while open.

Manages aria-modal, aria-labelledby, aria-describedby.

Data attribute Values
data-state โ€”

NdDialogDescription

[ndDialogDescription]from @ndop/primitives/dialog

The dialog's description; its id describes the content (aria-describedby). Keeps an id the element already has.

NdDialogOverlay

[ndDialogOverlay]from @ndop/primitives/dialog

Optional backdrop rendered behind the content. Hidden from assistive technology; a click on it closes the dialog unless closeOnOverlayClick is false.

Manages aria-hidden.

Data attribute Values
data-state โ€”

NdDialogPortal

ng-template[ndDialogPortal]from @ndop/primitives/dialog

Marks the ng-template whose content the NdDialog renders while open.

NdDialogTitle

[ndDialogTitle]from @ndop/primitives/dialog

The dialog's title; its id labels the content (aria-labelledby). Keeps an id the element already has.

NdDialogTrigger

[ndDialogTrigger]from @ndop/primitives/dialog

Button that opens and closes its NdDialog. Sets aria-haspopup="dialog", aria-expanded, aria-controls (only while open, since the content doesn't exist when closed) and data-state.

Manages aria-haspopup, aria-expanded, aria-controls.

Data attribute Values
data-state โ€”