Popover
ProPremium anchored panel with 7 variants, 8 auto-flipping placements, an optional pointer arrow, click/hover/manual triggers, and header/subtitle/close.
</>sv-popover popoveroverlayfloatingvariantarrow
import { SvPopoverComponent } from '@styloviz-pro/overlays';Demo & usage
Basic usage
ProUsage example — open the gallery for the full interactive demo.
Pro
An interactive demo for this component lives in the gallery.
Open live demoMore examples
Semantic variant with arrow
ProHover with delay
ProManual control
ProMenu behaviour
ProPassive callout vs interactive mini form
ProThe Popout preset
ProWhen to use
- Showing rich, possibly interactive content anchored to a trigger.
- Detail cards, mini-forms or menus that exceed what a Tooltip can hold.
- Semantic confirmations or status callouts — reach for the matching `variant`.
- For plain hint text, a Tooltip is lighter; for a list of actions, a Dropdown Menu.
Async states
None — this component has nothing to load, so it has no loading, empty or error state to drive.
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
| open | boolean (two-way) | false | Controls popover visibility. |
| position | PopoverPosition | 'bottom-start' | Placement of the popover relative to the trigger. |
| trigger | PopoverTrigger | 'click' | What triggers opening: click, hover, or manual (programmatic only). |
| title | string | '' | Optional header title for the popover panel. |
| subtitle | string | '' | Optional secondary header line (also wired to `aria-describedby`). |
| variant | PopoverVariant | 'default' | Color / semantic variant. |
| minWidth | number | 200 | Minimum width of the popover panel (px). |
| maxWidth | number | 0 | Maximum width of the popover panel (px). 0 = unconstrained. |
| offset | number | 8 | Gap between the trigger and the panel (px). |
| flip | boolean | true | Flip to the opposite side when there isn't room on the requested side. |
| showArrow | boolean | false | Render a pointer arrow that tracks the trigger. |
| showIcon | boolean | true | Show the built-in variant icon badge in the header. |
| showClose | boolean | false | Show a close (×) button in the header. |
| closeOnOutsideClick | boolean | true | Close when clicking outside the trigger and panel. |
| closeOnEsc | boolean | true | Close on the ESC key. |
| closeOnContentClick | boolean | false | Close when any content inside the panel is clicked (menu behaviour). |
| hoverOpenDelay | number | 0 | Delay before opening on hover (ms). |
| hoverCloseDelay | number | 80 | Delay before closing after the pointer leaves (ms). |
| disabled | boolean | false | Prevent the popover from opening. |
| autoFocus | boolean | false | Move focus into the panel when opened via click/manual (keyboard a11y). |
| interactive | boolean | undefined | undefined | Passive or interactive — the axis asks for, and D2 of `docs/anchored-surfaces-adr.md`. One input moves role, focus and Tab behaviour together, and it is orthogonal to `trigger` (how it opens, never what it is). - `false` — a passive callout. The panel is `role="tooltip"` and the trigger is `aria-describedby` it while open instead of announcing a dialog popup; focus never moves in, `autoFocus` is ignored. Escape, outside click and anchor loss still dismiss it. - `true` — an interactive surface such as a mini form. `role="dialog"`, focus moves to the first focusable element (or the panel itself) on a click/manual open, and Tab / Shift+Tab cycle inside the panel instead of walking out of it. A hover open never moves focus — that is a hover card, and pulling focus to wherever the pointer drifts is not an open. - unset — exactly the behaviour before this input existed: `role="dialog"`, no Tab containment, focus moved only under `[autoFocus]`. |
| align | PopoverAlign | undefined | undefined | Cross-axis alignment folded into `position`'s side: `position="left" align="start"` is the `left-start` placement, which `position` alone cannot spell. Unset leaves `position` exactly as written. |
| ariaLabel | string | 'Popover' | Accessible label used when no `title` is provided. |
| customClass | string | '' | Extra CSS classes merged onto the popover panel surface. |
Outputs
| Event | Payload type | Description |
|---|---|---|
| opened | void | Emitted after the popover opens (by any means, including `[(open)]`). |
| closedEvent | void | Emitted after the popover closes (by any means, including `[(open)]`). |
| openChange | boolean | Emits the new `open` whenever it changes — the output half of `[(open)]`. |
Customization & theming
- Seven variants (default · dark · primary · success · warning · danger · info) with tinted header, icon badge and accent bar.
- Eight placements with automatic flip + viewport clamping; optional pointer arrow via `[showArrow]`. `align` (`start` · `center` · `end`) folds into the side of `position`, which adds the four side-aligned placements (`left-start` … `right-end`) — every Popout configuration is a Popover one (`SV_POPOUT_PRESET`).
- Portaled to `document.body` and re-anchored to its trigger on scroll of any ancestor container (capture-phase) and on resize — never drifts or leaves the viewport.
- Click / hover / manual triggers, configurable `offset`, hover delays, and min/max width. A hover popover also keeps itself open while the pointer travels across the gap towards the panel (a safe corridor, not a longer timer), so reaching for it does not dismiss it — and turning away from the panel mid-way starts the close again rather than leaving it stuck open.
- Placement arithmetic is shared with Dropdown Menu, Popout and Tooltip: twelve placements, conditional flip, viewport clamp, `start`/`end` mirrored for RTL text, and correction for a transformed ancestor that has become the containing block.
- If the trigger is removed or collapses to nothing while the popover is open — the row it sits in is deleted, its `<details>` closes — the popover closes rather than floating over unrelated content. The trigger is size-watched while open, so this happens at the collapse, not at the next scroll.
- Header (title + subtitle + optional close button), content and footer slots; `closeOnOutsideClick` / `closeOnEsc` / `closeOnContentClick` toggles; `customClass` on the surface.
- Responsive: the panel width is capped to the viewport (`max-w-[calc(100vw-1rem)]`) on top of flip + clamp, so wide content can never overflow a small screen.
Best practices
- Do: Leave `[flip]` on (default) so the panel stays on-screen; add `[showArrow]` to anchor it visually to the trigger.
- Do: Use `trigger="click"` (or `"manual"`) for interactive content so it doesn't vanish on mouse-out.
- Do: Match the `variant` to intent — `danger` for destructive callouts, `success` for confirmations.
- Do: Say which kind of popover it is with `[interactive]`: `false` for a passive callout (announced as a description of the trigger, never takes focus), `true` for anything with fields or buttons (a dialog that takes focus and keeps Tab inside). Unset keeps the original behaviour. `trigger` stays separate — it says how the panel opens, never what it is; `trigger="hover"` with `[interactive]="true"` is a hover card.
- Tip: Set `[hoverOpenDelay]` on hover popovers to avoid opening on an accidental pass-over. `[hoverCloseDelay]` is a fallback, not the mechanism that keeps the panel reachable — the pointer travelling towards the panel already cancels the close.
Accessibility
- Trigger exposes `aria-haspopup="dialog"`, `aria-expanded` and `aria-controls`; the panel is `role="dialog"` labelled via `aria-labelledby`/`aria-label` and described via `aria-describedby` (subtitle).
- With `[autoFocus]` focus moves into the panel on click/manual open; on close focus returns to the trigger unless the user has already put it somewhere else (an outside click on another control keeps its focus). Closes on Esc and outside click (both configurable).
- `[interactive]="false"` makes the panel `role="tooltip"` and references it from the trigger's `aria-describedby` while open, with no `aria-haspopup` — it never takes focus, and it renders no Close button even with `[showClose]`, because a tooltip must not hold controls (dev mode warns if you project a focusable element into one). `[interactive]="true"` keeps `role="dialog"`, moves focus to the first focusable element (or the panel, `tabindex="-1"`) on a click/manual open, and keeps Tab / Shift+Tab inside the panel.
Feedback on Popover
Spotted a gap in this page, or something that didn't work as described? Comments are GitHub Discussions in the public styloviz/community repo, so posting needs a GitHub account.