A Vue 3 popover component with flexible positioning, drag-to-move, and customizable styling. Uses Floating UI for viewport-aware positioning.
- Flexible positioning — Place popovers top, bottom, left, right, or any side with
-start/-endvariants. Automatically flips and shifts to stay in view. - Draggable — Popovers with a header (title slot) can be dragged by the header and stay within the viewport.
- Passthrough API — Apply custom attributes, classes, and styles to internal elements via the
ptprop. - Teleported — Renders in
bodyto avoid overflow and stacking-context issues.
npm install vue-popover- Vue 3.3+
- @floating-ui/vue 1.1+
npm install @floating-ui/vue<script setup>
import { ref } from 'vue';
import { VPopover } from 'vue-popover';
import 'vue-popover/style.css';
const open = ref(false);
</script>
<template>
<VPopover v-model:open="open" placement="bottom" :width="250">
<template #activator="{ props }">
<button v-bind="props">Open popover</button>
</template>
<template #title>My Popover</template>
<p>Popover content goes here.</p>
</VPopover>
</template>| Prop | Type | Default | Description |
|---|---|---|---|
open |
boolean |
false |
Controls visibility (use with v-model:open). |
placement |
Placement |
'bottom' |
Preferred placement. Values: 'top', 'bottom', 'left', 'right', 'top-start', 'top-end', 'bottom-start', 'bottom-end', 'left-start', 'left-end', 'right-start', 'right-end'. |
width |
string | number |
— | Popover width (CSS value, e.g. 250 or '20rem'). |
height |
string | number |
— | Popover height. |
offset |
number |
8 |
Gap in pixels between popover and activator. |
closeOnClickOutside |
boolean |
true |
Close when clicking outside the popover. |
closeOnClick |
boolean |
false |
Close when clicking inside the popover. |
pt |
PassthroughOptions |
— | Passthrough attributes/classes/styles for root, activator, header, close, content. |
| Slot | Description |
|---|---|
activator |
Element that toggles the popover (required). |
title |
Header content. When present, the header is shown and the popover becomes draggable by the header. |
close |
Close button content (default: ×). |
default |
Main popover content (required). |
Import the default styles:
import 'vue-popover/style.css';Use the pt prop for inline customization:
<VPopover
:pt="{
root: { class: 'my-popover', style: 'background: white; border-radius: 8px;' },
header: { class: 'my-header' },
content: { style: 'padding: 16px;' },
}"
>
<!-- slots -->
</VPopover>npm install
npm run dev # Demo at http://localhost:5173
npm run build