Overlays

Popover

A trigger-activated floating panel of arbitrary content, positioned relative to its trigger.

vue
<UiPopover />

Options

One block per prop — what it does, and what it looks like set.

Mode

mode decides what opens the panel. click needs a deliberate press, which is right for a panel with controls in it; hover opens on approach, for a preview the reader shouldn't have to commit to.

mode="hover" closes as soon as the pointer leaves both the trigger and the content — there's no grace-period delay.

Dismissible

dismissible is on by default. Setting it false disables both Escape and the outside click, so the panel can only be closed from inside it.

Arrow

arrow is a pointer connecting the panel to its trigger. Worth adding when the panel sits far enough away that the link isn't obvious.

Content

content sets where the panel sits relative to the trigger — side, alignment and offset.

Open

Bind it with v-model:open when something outside the popover has to open or close it.

The #content slot receives a close function; you don't need to manage open state yourself just to add a close button.

Default open

defaultOpen starts the panel open when the popover manages its own state — reasonable for a one-off hint on first visit, disruptive as a standing default.

Trigger class

triggerClass styles the wrapper the popover puts around the trigger. It matters most for rounding: the wrapper is what receives the hover, and border-radius clips hit-testing, so a round trigger in a square wrapper opens from corners it doesn't visually occupy.

Panel class

panelClass replaces the panel's own padding, background, rounding and ring wholesale — reach for it when the content should run flush to the panel's edges.

When neither side has room for the panel's full height, it opens on the roomier side and exposes the space left as --bundy-popover-available-height (and --bundy-popover-available-width). A scrollable panel should cap itself with max-h-[min(32rem,var(--bundy-popover-available-height))] — without that, it's pinned to the viewport edge and can cover its trigger.


Examples

The component in real use: compositions that answer "how do I build X with this", rather than one prop at a time.

Form content

The panel is a normal slot, so a small form fits in it as well as a paragraph does.


API Reference

Generated from the component's source — props, slots and emits as the component actually declares them.

Props

Prop
Type
Default
Description
"click" | "hover"
'click'
Whether the popover opens on click or on hover.
boolean
true
Whether clicking outside or pressing Escape closes the popover.
boolean
false
PopoverContentProps
{ side: 'bottom', align: 'start', sideOffset: 8 }
Positioning options for the popover content (side, alignment, and offset from the trigger).
boolean
—
Controls the open state for external `v-model:open` usage.
boolean
false
Initial open state when uncontrolled.
any
—
Classes applied to the wrapper around the trigger slot. This wrapper is what receives the click or hover, so a rounded trigger needs a matching radius here — `border-radius` clips hit-testing, and a square wrapper otherwise reacts in corners the trigger itself doesn't.
any
'p-3 bg-foreground/95 backdrop-blur-lg shadow-lg rounded-md ring-1 ring-elevated/50 ring-inset font-sans'
Classes applied to the floating content panel, replacing its default padding/background/border appearance — use this to match another floating panel's chrome (e.g. `DropdownMenu`'s).

Slots

Slot
default
Receives `{ open }`.
content
Receives `{ close }`.

Emits

Event
Payload
Description
update:open
[value: boolean]
—

Types

ts
interface PopoverContentProps {
    side?: "top" | "right" | "bottom" | "left";
    align?: "start" | "center" | "end";
    sideOffset?: number;
}