# 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.

Source: https://ngwr.dev/reference/components/popover  
Kind: Directive, CDK Overlay

## Installation

```angular-ts
import { WrPopover } from 'ngwr/popover';

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

## Basic usage

```html
<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).

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

## Hover trigger

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

## Positions

```html
<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`.

```html
<!-- 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

```html
<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.

```angular-html
<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.

```angular-ts
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 |
| --- | --- | --- | --- |
| `wrPopover`required | 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` |
