DirectiveCDK Overlay

Popover

Anchored content panel. Project a template (popover) or pass a plain string (tooltip — use mode="tooltip"). Click or hover to open; a tooltip also answers a keyboard focus. Built on CDK Overlay.

Installation

import { WrPopover } from 'ngwr/popover';

@Component({ imports: [WrPopover] })
export class MyComponent {}

Basic usage

<wr-btn [wrPopover]="info">Details</wr-btn>

<ng-template #info>
  <div style="padding: 1rem; max-width: 16rem">
    Anything you can render in a template.
  </div>
</ng-template>

Responsive (bottom-sheet)

Popover mode only — with responsive (or app-wide via provideWrResponsiveOverlays()) the panel slides up as a full-width bottom-sheet with a backdrop on small viewports. Tooltips never become sheets. Open this on a phone (or narrow the window below 640px).

<wr-btn [wrPopover]="tpl" responsive>Details</wr-btn>

Hover trigger

<wr-btn [wrPopover]="card" trigger="hover">Hover me</wr-btn>

Positions

<wr-btn [wrPopover]="hint" position="right">Right</wr-btn>

Tooltip mode

Pass a string + mode="tooltip" for a small dark hint panel. Opens on hover or on a KEYBOARD focus — never on a .focus() call, which is what a dialog or drawer does when it hands focus back to the trigger it was opened from. Dismisses when focus leaves, on pointer-leave, or Escape. Uses aria-describedby instead of aria-haspopup.

SaveDeleteOpen
<!-- Pass a string + mode="tooltip" — opens on hover or a keyboard
     focus, closes when focus leaves / on pointer-leave / Escape. A .focus()
     call opens nothing: that is an overlay handing focus back, not a user.
     Uses aria-describedby. -->
<wr-btn [wrPopover]="'Save changes'" mode="tooltip" position="top">Save</wr-btn>

Tooltip — custom delays

Hover
<wr-btn
  [wrPopover]="'Slow to appear'"
  mode="tooltip"
  [showDelay]="500"
  [hideDelay]="100"
>
  Hover
</wr-btn>

Template reference

The directive exports itself as wrPopover, so a template can reach the instance and drive the panel from anywhere on the page.

<wr-btn [wrPopover]="card" #details="wrPopover">Details</wr-btn>

<!-- Anywhere else in the same template -->
<wr-btn (click)="details.toggle()">Toggle from here</wr-btn>
<wr-btn [disabled]="!details.isOpen()" (click)="details.close()">Close</wr-btn>

Scrolling containers

The panel is anchored to the trigger and repositions while the page scrolls — but only for the window and for scroll containers the CDK has been told about. Inside your own overflow: auto box (a side panel, a scrollable card, a table body) the panel is placed once and then stays put, drifting away from its trigger as the box scrolls. Mark the container with cdkScrollable and it follows again. The same rule covers every anchored ngwr overlay: popover, tooltip mode, dropdown, popconfirm, select, cascader, tree and the date pickers, and equally the four that reposition without being listed here — mention, tour, the colour-picker trigger and a context-menu submenu.

import { CdkScrollable } from '@angular/cdk/scrolling';

@Component({
  imports: [CdkScrollable, WrPopover],
  template: `
    <!-- One attribute. Without it the panel is positioned when it opens and
         never again for this box — the window is tracked automatically, a
         nested scroller only once it registers itself. -->
    <div class="side-panel" cdkScrollable>
      <wr-btn [wrPopover]="info">Details</wr-btn>
    </div>
  `,
})
export class PanelComponent {}

API

NameDescriptionTypeDefault
wrPopoverrequiredContent to render inside the panel. - In popover mode (default): pass a TemplateRef. - In tooltip mode: pass a plain string.TemplateRef<unknown> | string
modeShape preset. - 'popover' (default) — template content, click trigger, dialog semantics. - 'tooltip' — text content, hover / keyboard-focus trigger, role="tooltip", aria-describedby on the host.'popover' | 'tooltip''popover'
triggerHow the popover opens. Ignored in tooltip mode — a tooltip is always hover plus keyboard focus.'click' | 'hover''click'
positionAnchor side.WrPopoverPosition | null'bottom' for popover, 'top' for tooltip
showDelayTooltip only — delay before showing, in ms.number120
hideDelayTooltip only — delay before hiding, in ms.number60
responsivePopover mode only — present the panel as a full-width bottom-sheet on small viewports instead of an anchored panel. undefined follows the app-wide provideWrResponsiveOverlays() setting; true/false overrides it. Tooltips never become sheets.boolean | undefinedundefined
ariaLabelPopover mode only — accessible name of the panel. role="dialog" with no name announces as a bare "dialog", so the catalog's popover.label is used when nothing is given. A popover has no universal name; whenever the panel has a heading or a purpose, pass it.string | nullnull
(opened)Fires after the panel opens.void
(closed)Fires after the panel closes.void

CSS variables

Custom properties ngwr/popover publishes. Each default below is declared on the component's own selector, so a :root override is shadowed by it — set them on that selector, on a wrapper you scope yourself, or inline on the element. Unlike the BEM class names, these are the supported way to restyle the component.

VariableDefaultDeclared on
--wr-tooltip-bgvar(--wr-color-surface).wr-tooltip
--wr-tooltip-bordervar(--wr-color-outline).wr-tooltip
--wr-tooltip-colorvar(--wr-color-on-surface).wr-tooltip