Skip to content

Popover

Popover is an anchored, non-modal floating bubble with a directional arrow tail, optional title and body, and optional action buttons. Use it for click-triggered, interactive content — for ephemeral hover hints reach for Tooltip, and for modal containment reach for Dialog.

Popover extends Panel so authors can compose freely via addComponent; the setTitle / setBody / addAction conveniences are sugar over the same container surface.

Positioning is anchor-relative. While the popover is open, window resize and each scrollable ancestor's scroll event trigger a reposition so the bubble follows the anchor. Fade-in / fade-out reuse the shared fadeShow / fadeHideAndDetach helpers so the entrance animation matches the rest of the floating-overlay family.

Usage

typescript
import { Event, Popover } from '@jimka/typescript-ui/core';
import { Button } from '@jimka/typescript-ui/component/button';

const popover = new Popover({
    placement: 'auto',
    dismissOn: 'click-outside',
    title:     'Confirm delete',
});

popover.setBody('This action cannot be undone.');
popover.addAction('Delete', () => doDelete());
popover.addAction('Cancel', () => popover.hide());

const trigger = new Button('Delete record');
Event.addListener(trigger, 'click', () => {
    popover.attachToComponent(trigger);
    popover.show();
});

Placement

setPlacement(side) accepts "top", "bottom", "left", "right", or "auto".

  • "auto" (default) picks the side with the most viewport space at show() time.
  • An explicit side is honoured unless it would overflow the viewport, in which case the opposite side is used and a console warning is logged.

The arrow tail always points at the anchor centre even when the popover body is shifted laterally to stay on-screen.

Dismiss modes

setDismissOn(mode) accepts:

ModeBehaviour
"click-outside"Default. Closes on a viewport mousedown outside both the popover and its anchor.
"blur"Closes when keyboard focus leaves the popover subtree. The popover root is made focusable and is focused on show() so focusout fires reliably.
"manual"Caller drives hide() explicitly. No listeners are wired.

In every mode the anchor element is excluded from the outside-dismiss check, so a second click on the trigger button does not immediately re-close the popover.

Convenience setters

MethodPurpose
setTitle(text) / clearTitle()Title row (bold Text) above the body.
setBody(text) / setBody(component)String content is wrapped in a Text; a component is used directly. Replaces the previous body.
addAction(label, onClick) / clearActions()Appends a Button to a horizontal actions row at the bottom.
setShowArrow(boolean)Hide the arrow tail (bubble keeps its standard radius).

Power users who need a complex composition skip the conveniences and call addComponent directly.

Theme tokens

CSS Custom PropertyLight DefaultDark DefaultPurpose
--ts-ui-popover-bgrgb(255, 255, 255)rgb(50, 50, 55)Bubble background
--ts-ui-popover-colorrgb(0, 0, 0)rgb(230, 230, 235)Body text colour
--ts-ui-popover-borderrgb(200, 200, 200)rgb(90, 90, 100)Bubble + arrow border
--ts-ui-popover-shadow2px 4px 12px rgba(0, 0, 0, 0.18)2px 4px 12px rgba(0, 0, 0, 0.55)Bubble drop shadow
--ts-ui-popover-radius6px6pxBubble corner radius
--ts-ui-popover-padding12px12pxBubble inner padding
--ts-ui-popover-arrow-size8px8pxArrow diamond side length

Reduced motion

prefers-reduced-motion: reduce short-circuits the fade transition through Animation.play — the popover appears instantly with no fade or translate.

See also