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.
<!-- 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
<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
| Name | Description | Type | Default |
|---|---|---|---|
wrPopoverrequired | Content to render inside the panel. - In popover mode (default): pass a TemplateRef. - In tooltip mode: pass a plain string. | TemplateRef<unknown> | string | — |
mode | Shape 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' |
trigger | How the popover opens. Ignored in tooltip mode — a tooltip is always hover plus keyboard focus. | 'click' | 'hover' | 'click' |
position | Anchor side. | WrPopoverPosition | null | 'bottom' for popover, 'top' for tooltip |
showDelay | Tooltip only — delay before showing, in ms. | number | 120 |
hideDelay | Tooltip only — delay before hiding, in ms. | number | 60 |
responsive | Popover 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 | undefined | undefined |
ariaLabel | Popover 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 | null | null |
(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.
| Variable | Default | Declared on |
|---|---|---|
--wr-tooltip-bg | var(--wr-color-surface) | .wr-tooltip |
--wr-tooltip-border | var(--wr-color-outline) | .wr-tooltip |
--wr-tooltip-color | var(--wr-color-on-surface) | .wr-tooltip |