Components
Back to catalog
Component detail entry
Overlay
@vean/ui
SPopover

Popover

Popover belongs to the Overlay category. Start with demos and usage, then use the API tables to finish integration and styling decisions.

Use the quick jump panel to reach overview, usage, demos, and API first, then continue through the full page.

Quick jump

Related components

If you are composing interactions in the same family, these components usually pair well together.

Popover

Overview

Displays rich content in a portal, triggered by a button. SPopover combines the Aria PopoverRoot/PopoverTrigger/PopoverPositioner/PopoverPopup/PopoverArrow/PopoverClose primitive family (built on the shared Popper + dialog-style dismissable/focus layers) with the popoverVariants style recipe (5 slots, 6 sizes).

Use a popover for contextual, non-critical rich content (menus of actions, settings, help). For navigation menus use dropdown-menu; for a small hover hint use tooltip; for a blocking confirmation use popconfirm or dialog.

Usage

Features

  • 🧩 Aria/styled split — PopoverCompact aggregates the popper positioner, popup, arrow and close; SPopover only injects styles and forwards slots/events
  • 🎯 Placement — full popper placement control (12 directions) with collision avoidance and side-aware slide animations
  • 🎭 Modal toggle — modal controls outside-pointer blocking, useHideOthers, body scroll lock and focus trapping
  • 🔽 Arrow — showArrow renders a positioned arrow; configurable via arrowProps
  • ❌ Closable — optional close slot with a built-in lucide:x icon; Escape and outside interaction dismiss
  • 📐 6 sizes — xs–2xl size; per-slot ui overrides
  • ♿ Accessible — role="dialog", focus trap + loop, aria-labeld close button, axe-core zero violations

Component family

  • SPopover (styled) — the entry wrapper; popoverVariants recipe with dynamic slot forwarding
  • PopoverRoot (Aria) — the state owner; open via useControllableState, dir/modal/disabled, provides the popper root
  • PopoverTrigger (Aria) — a Button that toggles the popover
  • PopoverPositioner / PopoverPositionerImpl (Aria) — the focus-trapped, dismissable, positioned surface (built on PopperPositioner)
  • PopoverPopup (Aria) — the popup body
  • PopoverArrow (Aria) — the popper arrow
  • PopoverClose (Aria) — the close <button>, emits close and toggles open
  • PopoverCompact (Aria) — the aggregated composite; composes positioner/popup/arrow/close and exposes the slots

Demos

Basic

API

Aria Layer

10

Popover

16 Props8 Emits3 Slots
Props
PropTypeDefaultDescription
class
ClassValue
—
class of popup
size
ThemeSize
—
Visual size of the component.
ui
Partial<PopoverUi>
—
Per-slot class overrides for the component.
placement
import("@/index").Placement
—
Placement.
showArrow
boolean
—
Whether to show an arrow.
triggerProps
PopoverTriggerProps
—
Properties forwarded to the trigger element.
portalProps
PopoverPortalProps
—
Properties forwarded to the portal element.
positionerProps
PopoverPositionerProps
—
Properties forwarded to the positioner element.
popupProps
PopoverPopupProps
—
Properties forwarded to the popup element.
arrowProps
PopoverArrowProps
—
Properties forwarded to the arrow element.
closeProps
PopoverCloseProps
—
Properties forwarded to the close element.
dir
Direction
—
—
open
boolean
—
—
defaultOpen
boolean
—
—
modal
boolean
—
—
disabled
boolean
—
—
Emits
Emit NameParametersDescription
update:open
boolean
Event handler called when the open state of the dialog changes.
escapeKeyDown
KeyboardEvent
Event handler called when the escape key is down. Can be prevented.
pointerDownOutside
PointerDownOutsideEvent
Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`. Can be prevented.
focusOutside
FocusOutsideEvent
Event handler called when the focus moves outside of the `DismissableLayer`. Can be prevented.
interactOutside
PointerDownOutsideEvent | FocusOutsideEvent
Event handler called when an interaction happens outside the `DismissableLayer`. Specifically, when a `pointerdown` event happens outside or focus moves outside of it. Can be prevented.
openAutoFocus
Event
Event handler called when auto-focusing on open. Can be prevented.
closeAutoFocus
Event
Event handler called when auto-focusing on close. Can be prevented.
placed
—
—
Slots
Slot NameParametersDescription
default
{ open: boolean; close: () => void; }
Custom content for the default slot.
trigger
—
Custom content for the trigger slot.
close
—
Custom content for the close slot.

PopoverAnchor

PopoverArrow

PopoverClose

4 Props1 Emits
Props
PropTypeDefaultDescription
type
ButtonType
'button'
The type of the button element. Can be one of 'button', 'submit', or 'reset'.
disabled
boolean
—
Whether the component is disabled.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`
Emits
Emit NameParametersDescription
close
PointerEvent
Emitted when close occurs.

PopoverCompact

13 Props8 Emits3 Slots
Props
PropTypeDefaultDescription
placement
import("@/index").Placement
—
Placement.
showArrow
boolean
—
Whether to show an arrow.
triggerProps
PopoverTriggerProps
—
Properties forwarded to the trigger element.
portalProps
PopoverPortalProps
—
Properties forwarded to the portal element.
positionerProps
PopoverPositionerProps
—
Properties forwarded to the positioner element.
popupProps
PopoverPopupProps
—
Properties forwarded to the popup element.
arrowProps
PopoverArrowProps
—
Properties forwarded to the arrow element.
closeProps
PopoverCloseProps
—
Properties forwarded to the close element.
dir
Direction
—
—
open
boolean
—
—
defaultOpen
boolean
—
—
modal
boolean
—
—
disabled
boolean
—
—
Emits
Emit NameParametersDescription
update:open
boolean
Event handler called when the open state of the dialog changes.
escapeKeyDown
KeyboardEvent
Event handler called when the escape key is down. Can be prevented.
pointerDownOutside
PointerDownOutsideEvent
Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`. Can be prevented.
focusOutside
FocusOutsideEvent
Event handler called when the focus moves outside of the `DismissableLayer`. Can be prevented.
interactOutside
PointerDownOutsideEvent | FocusOutsideEvent
Event handler called when an interaction happens outside the `DismissableLayer`. Specifically, when a `pointerdown` event happens outside or focus moves outside of it. Can be prevented.
openAutoFocus
Event
Event handler called when auto-focusing on open. Can be prevented.
closeAutoFocus
Event
Event handler called when auto-focusing on close. Can be prevented.
placed
—
—
Slots
Slot NameParametersDescription
default
{ open: boolean; close: () => void; }
Custom content for the default slot.
trigger
—
Custom content for the trigger slot.
close
—
Custom content for the close slot.

PopoverPopup

PopoverPortal

PopoverPositioner

23 Props7 Emits
Props
PropTypeDefaultDescription
placement
Placement
undefined
The placement of the floating element. If used, it will override the `side` and `align` props.
side
Side
'bottom'
The preferred side of the trigger to render against when open. Will be reversed when collisions occur and avoidCollisions is enabled.
sideOffset
number
0
The distance in pixels from the trigger.
sideFlip
boolean
true
Flip to the opposite side when colliding with boundary.
align
Align
'center'
The preferred alignment against the trigger. May change when collisions occur.
alignOffset
number
0
An offset in pixels from the `start` or `end` alignment options.
alignFlip
boolean
true
Flip alignment when colliding with boundary. May only occur when `prioritizePosition` is true.
avoidCollisions
boolean
true
When `true`, overrides the side and align preferences to prevent collisions with boundary edges.
collisionBoundary
Element | (Element | null)[] | null
[ ]
The element used as the collision boundary. By default this is the viewport, though you can provide additional element(s) to be included in this check.
collisionPadding
Padding
0
The distance in pixels from the boundary edges where collision detection should occur. Accepts a number (same for all sides), or a partial padding object, for example: { top: 20, left: 20 }.
arrowPadding
number
0
The padding between the arrow and the edges of the content. If your content has border-radius, this will prevent it from overflowing the corners.
hideShiftedArrow
boolean
true
When `true`, hides the arrow when it cannot be centered to the reference element.
sticky
'partial' | 'always'
'partial'
The sticky behavior on the align axis. `partial` will keep the content in the boundary as long as the trigger is at least partially in the boundary whilst "always" will keep the content in the boundary regardless.
hideWhenDetached
boolean
false
Whether to hide the content when the trigger becomes fully occluded.
positionStrategy
'fixed' | 'absolute'
'fixed'
The type of CSS position property to use.
updatePositionStrategy
'always' | 'optimized'
'optimized'
Strategy to update the position of the floating element on every animation frame.
disableUpdateOnLayoutShift
boolean
false
Whether to disable the update position for the content when the layout shifted.
prioritizePosition
boolean
false
Force content to be position within the viewport. Might overlap the reference element, which may not be desired.
reference
ReferenceElement
—
The custom element or virtual element that will be set as the reference to position the floating element. If provided, it will replace the default anchor element.
trapFocus
boolean
modal
Whether focus is trapped inside the popup while open (Tab cycles within the layer and body scroll is locked for modal layers).
disableHoverableContent
boolean
false
When `true`, hovering the popup closes instead of keeping it open (the grace area is disabled, so leaving the trigger closes the layer immediately).
onGracePointerExit
(() => void)
—
Callback invoked when the pointer finally leaves the grace area. Lets an upper layer (e.g. Tooltip) run area-scoped close logic without registering its own second grace area.
forceMount
boolean
—
Used to force mounting when more control is needed. Useful when controlling animation with Vue animation libraries.
Emits
Emit NameParametersDescription
escapeKeyDown
KeyboardEvent
Event handler called when the escape key is down. Can be prevented.
pointerDownOutside
PointerDownOutsideEvent
Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`. Can be prevented.
focusOutside
FocusOutsideEvent
Event handler called when the focus moves outside of the `DismissableLayer`. Can be prevented.
interactOutside
PointerDownOutsideEvent | FocusOutsideEvent
Event handler called when an interaction happens outside the `DismissableLayer`. Specifically, when a `pointerdown` event happens outside or focus moves outside of it. Can be prevented.
openAutoFocus
Event
Event handler called when auto-focusing on open. Can be prevented.
closeAutoFocus
Event
Event handler called when auto-focusing on close. Can be prevented.
placed
—
—

PopoverRoot

5 Props1 Emits
Props
PropTypeDefaultDescription
dir
Direction
—
—
open
boolean
—
—
defaultOpen
boolean
—
—
modal
boolean
—
—
disabled
boolean
—
—
Emits
Emit NameParametersDescription
update:open
boolean
Event handler called when the open state of the dialog changes.

PopoverTrigger

4 Props
Props
PropTypeDefaultDescription
type
ButtonType
'button'
The type of the button element. Can be one of 'button', 'submit', or 'reset'.
disabled
boolean
—
Whether the component is disabled.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`

Notes

Architecture and benchmark differences

PopoverCompact owns the positioner/popup/arrow/close composition while every primitive stays style-free and only the UI wrapper injects the popoverVariants classes. This mirrors radix-ui/shadcn-ui’s headless/styled split, built on the shared Popper primitives. Ant Design, Element Plus, Mantine and Naive UI ship a single styled popover with placement/trigger/width props; VeanUI additionally exposes per-slot *Props, a size scale, an arrow toggle, and a modal mode the single-package popovers generally lack.

CapabilityVeanUIshadcn/uiAnt Design PopoverElement Plus PopoverMantine PopoverNaive UI Popover
Aria/styled split✅✅————
Popper placement (12)✅✅✅✅✅✅
Arrow✅✅————
Modal mode✅✅————
Close button✅✅————
Sizes (6)✅—————
Focus trap + loop✅✅————

— = unsupported or a different interaction model.

Cautions

  • PopoverRoot defaults to modal (true): opening it blocks outside pointer events and locks body scroll. Pass modal={false} for a lightweight, non-blocking popover.
  • The popup is rendered through a Portal (teleported to document.body); position it inside a relatively-positioned ancestor only with portalProps: { disabled: true }.
  • showArrow renders an arrow; arrowProps can override its position/classes.
  • Provide a close slot to show the close control; it defaults to a lucide:x icon.
  • Unlike tooltip, the popover does not auto-dismiss on pointer-leave; it stays open until dismissed.

Roadmap

N/A — popover is feature-complete for the current parity set.

FAQ

How do I position the popover?

Use placement (from popper), e.g. top, bottom-start, right-end:

<SPopover placement="top">
  <template #trigger><SButton>Info</SButton></template>
</SPopover>

How do I add a close button?

Provide the close slot:

<SPopover>
  <template #trigger><SButton>More</SButton></template>
  <template #close>Dismiss</template>
</SPopover>

How do I make a non-blocking popover?

Set modal={false}:

<SPopover :modal="false">
  <template #trigger><SButton>Open</SButton></template>
</SPopover>

How do I control the open state?

Bind open with v-model or use defaultOpen:

<SPopover v-model:open="open">
  <template #trigger><SButton>Open</SButton></template>
</SPopover>

Changelog

Version history is grouped by release so you can quickly see what changed for this component across published versions.

v0.50.0

2026-10-02

Compare release

Feature

add default props for avoidCollisions and prioritizePosition

Scope: popoverAuthors: soybeanjsView commitf86de

Feature

add default props for avoidCollisions and prioritizePosition

Scope: popoverAuthors: soybeanjsView commitf86de

v0.19.0

2026-05-11

Compare release

Feature

add prioritizePosition prop for improved positioning control

Scope: popoverAuthors: soybeanfeView commit0bc99

Fix

bind slotProps to slots in PopoverCompact template

Scope: popoverAuthors: soybeanfeView commitba82c

Optimization

simplify popover component structure and enhance close functionality

Scope: popoverAuthors: soybeanfeView commitf9d63

Optimization

simplify component structure in PopoverTrigger

Scope: popoverAuthors: soybeanfeView commitf1764

v0.17.0

2026-05-03

Compare release

Optimization

enhance context and props for popover components

Scope: popoverAuthors: soybeanjsView commitf6666

v0.16.0

2026-05-01

Compare release

Feature

implement Compact components for Card, Popover, Editable, HoverCard, NavigationMenu, Pagination and Stepper

Scope: componentsAuthors: soybeanjsView commit6cbdc

v0.12.0

2026-03-07

Compare release

Feature

add PopoverCloseEmits and beforeClose prop; update PopoverPositioner default props

Scope: popoverAuthors: soybeanjsView commit08e1c

v0.0.17

2026-01-19

Compare release

Fix

add disable-outside-pointer-events binding to PopoverPositionerImpl

Scope: popoverAuthors: soybeanjsView commit1c945

v0.0.8

2026-01-01

Compare release

Optimization

remove PopoverPositioner context and update related components for improved clarity and functionality

Scope: popoverAuthors: soybeanjsView commitde4b4

Refactor

remove PopoverContent, introduce PopoverPositioner and PopoverPopup components, and enhance context management for improved structure and functionality

Scope: popoverAuthors: soybeanjsView commit2eb9c

v0.0.2

2025-11-18

Compare release

Feature

add Popover component with trigger, content, and context management for enhanced UI interactions

Scope: popoverAuthors: soybeanjsView commitb14c6

Feature

introduce SPopover component with customizable positioning and theming support

Scope: popoverAuthors: soybeanjsView commit902c0

Feature

add close method and pass it to slot for improved popover control

Scope: popoverAuthors: soybeanjsView commitd4520

Feature

add new props 'sideFlip' and 'alignFlip' to popper-content component

Scope: popoverAuthors: soybeanjsView commitd8115

Refactor

integrate useBodyScrollLock for improved modal behavior and enhance focus management

Scope: popoverAuthors: soybeanjsView commit2c757

Refactor

streamline component imports and enhance cleanup management with onWatcherCleanup

Scope: popoverAuthors: soybeanjsView commit78af9

Refactor

streamline element handling in popover context and components by replacing setElement functions with callback support

Scope: popoverAuthors: soybeanjsView commit4bba4

Feature

add Popover component with trigger, content, and context management for enhanced UI interactions

Scope: popoverAuthors: soybeanjsView commitb14c6

Feature

introduce SPopover component with customizable positioning and theming support

Scope: popoverAuthors: soybeanjsView commit902c0

Feature

add close method and pass it to slot for improved popover control

Scope: popoverAuthors: soybeanjsView commitd4520

Feature

add new props 'sideFlip' and 'alignFlip' to popper-content component

Scope: popoverAuthors: soybeanjsView commitd8115

Refactor

integrate useBodyScrollLock for improved modal behavior and enhance focus management

Scope: popoverAuthors: soybeanjsView commit2c757

Refactor

streamline component imports and enhance cleanup management with onWatcherCleanup

Scope: popoverAuthors: soybeanjsView commit78af9

Refactor

streamline element handling in popover context and components by replacing setElement functions with callback support

Scope: popoverAuthors: soybeanjsView commit4bba4