vael-ui v0.3.10

Overlays

Popover

A floating panel anchored to a trigger element, for menus, forms, or extra detail.

Install

import { Popover } from 'vael-ui'

Playground

import { Popover } from 'vael-ui'

<Popover side="bottom" align="center" :sideOffset="8" :alignOffset="0" closeOnEsc closeOnOutside :forceMount="false" scrollFade :openOnTriggerClick="false">Popover</Popover>

Props

NameTypeDefaultDescription
triggerElTriggerRefExternal ref (raw element or component with `.el`); use #trigger slot if the trigger can live here.
side"top" | "right" | "bottom" | "left""bottom"Which side of the trigger the panel opens on.
align"start" | "end" | "center""center"How the panel aligns against the trigger along that side.
sideOffsetnumber | undefined8Gap between the trigger and the panel, in pixels.
alignOffsetnumber | undefined0Shifts the panel along the alignment axis, in pixels.
closeOnEscboolean | undefinedtrueEscape key closes the panel.
closeOnOutsideboolean | undefinedtrueClicking outside the panel closes it.
beforeClose((done: () => void) => void) | undefinedCustom exit animation; call `done()` when it's complete. Delays the actual close/unmount until then.
forceMountboolean | undefinedfalseWhen true, presence is v-show-driven and owned by the consumer (e.g. AnimatePresence).
teleportTostring | HTMLElement | undefinedCSS selector or an actual DOM element — same contract as Vue's own Teleport `to`. Wins over `container` either way.
containerDOMTarget | undefinedScopes the popover to one element: it teleports there instead of `body`, positions against it, and Escape-key ownership is scoped to it too, so it doesn't contend with page-level layers. Omit for a page-level popover.
scrollFadeboolean | undefinedtrueMasks the panel's top/bottom edge as its content scrolls under it, signaling there's more.
openOnTriggerClickboolean | undefinedfalseWhen true, Popover manages opening itself — clicking the `#trigger` slot toggles `open` and the trigger element is auto-resolved for positioning, matching Menu's contract. Default `false` keeps the original positioning-only contract (drive `open`/`setTriggerEl` yourself).
uiPartial<{ positioner: UiPartValue; panel: UiPartValue; }> | undefinedPer-instance part-class/style overrides.
openboolean | undefinedfalseWhether the popover is open.

Slots

NameTypeDescription
default{ close: () => void; open: boolean; isClosing: boolean; cancelClose: () => void; panelEl: HTMLElement | null; placement: string; }
trigger{ open: boolean; setTriggerEl: (el: any) => void; }Co-located trigger markup — bind `:ref="setTriggerEl"` on whatever you render here. By default Popover only positions against it: clicking does nothing until you drive `open`/`@update:open` yourself. Pass `openOnTriggerClick` to get Menu's fully-managed contract instead (click-to-toggle, no manual ref needed).

Events

NameTypeDescription
open-change[value: boolean, details: PopoverOpenChangeDetails]
update:open[value: boolean]

Exposed

NameTypeDescription
panelElHTMLElement | null
positionerElHTMLElement | null
placementPlacement
positionerStyleRecord<string, string>
isClosingboolean
close() => void
cancelClose() => void