Skip to content
Ndop UI

Popover primitive

Headless Popover: the behavior, keyboard support and ARIA of the WAI-ARIA dialog role 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 Popover is built on this one.

import {
  NdPopover,
  NdPopoverClose,
  NdPopoverContent,
  NdPopoverPortal,
  NdPopoverTrigger,
} from '@ndop/primitives/popover';

Accessibility

Implements the dialog role pattern of the WAI-ARIA Authoring Practices.

Keyboard

Keys the component handles.

Key Action
EscapeCloses the popover and returns focus to the trigger.
TabMoves focus through the content; past the last element, the popover closes and focus moves to what follows the trigger.
ShiftTabMoves focus backwards through the content; before the first element, the popover closes and focus returns to the trigger.

Focus

  • On open: focus moves to the first focusable element in the content, or to the content element.
  • Focus is not trapped.
  • On close with Escape or PopoverClose: focus returns to the trigger.
  • On close because focus or a pointer left: focus stays where the user put it.

Right-to-left

side="start" and side="end" place the content on the inline start and end of the trigger, which swap in RTL; align="start" and align="end" swap likewise.

API reference

NdPopover

[ndPopover]from @ndop/primitives/popover

Root of a popover: non-modal content anchored to a trigger (WAI-ARIA dialog role without a focus trap). Renders the ng-template[ndPopoverPortal] into a CDK overlay positioned next to the trigger, flipping to the opposite side when it doesn't fit. Escape, an outside click or focus leaving the content closes it. Put it on an ng-container so it adds no element. The popover never renders open on the server; an initial open state takes effect after hydration.

NdPopover binding Type Default
[defaultOpen]
Initial open state when open is not bound.
booleanfalse
[(open)]
Whether the popover is open. Two-way bindable with [(open)].
booleanfalse

NdPopoverClose

[ndPopoverClose]from @ndop/primitives/popover

Button that closes its NdPopover and returns focus to where it was before opening.

NdPopoverContent

[ndPopoverContent]role dialogfrom @ndop/primitives/popover

The popover panel: role="dialog", tabindex="-1", with data-side and data-align reporting where it actually sits. Name it with aria-label or aria-labelledby. Focus moving outside it, other than to the trigger, closes the popover.

NdPopoverContent binding Type Default
[side]
Preferred side of the trigger; start and end swap in RTL.
'start' | 'end' | 'bottom' | 'top''bottom'
[align]
Preferred alignment along that side.
'start' | 'end' | 'center''center'
[sideOffset]
Gap from the trigger, in pixels.
number4
Data attribute Values
data-state —
data-side —
data-align —

NdPopoverPortal

ng-template[ndPopoverPortal]from @ndop/primitives/popover

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

NdPopoverTrigger

[ndPopoverTrigger]from @ndop/primitives/popover

Button that opens and closes its NdPopover, and anchors the content. Sets aria-haspopup="dialog", aria-expanded, aria-controls while open, and data-state.

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

Data attribute Values
data-state —