Vue 3 Popper Component
vue3-popper is a lightweight and flexible popover component for Vue 3 applications, leveraging PopperJS v2 for accurate positioning. Currently at version 1.5.0, it follows semantic versioning strictly since its 1.0.0 release. The library offers features like configurable placement, offsets, hover triggers, arrows, and manual control of visibility. It is designed to be highly customizable, supporting both simple string content via props and complex HTML structures through slots. Recent updates have focused on improving SSR compatibility (especially with Nuxt 3), refactoring to modern Vue 3 `script setup` syntax, and enhancing type definitions. Its key differentiators include its tight integration with Vue 3's reactive system and its commitment to providing a robust wrapper around the proven PopperJS library, making it a reliable choice for tooltips and popovers in the Vue ecosystem.
Common errors
-
ReferenceError: window is not defined
cause This error typically occurs in a Server-Side Rendering (SSR) environment (like Nuxt 3) when `vue3-popper` attempts to access the `window` object during server compilation, before it's available in the browser.fixUpgrade `vue3-popper` to version 1.4.2 or higher, which includes a fix for this specific SSR issue. If using an older version is unavoidable, consider dynamically importing the component or rendering it only on the client-side. -
[Vue warn]: Component is missing template or render function.
cause This warning usually means the `Popper` component was imported or registered incorrectly, or Vue couldn't find its template. This can happen with incorrect default/named imports or CJS `require` in an ESM context.fixEnsure you are using `import Popper from 'vue3-popper';` (default import) and registering it correctly in your Vue component's `components` option or directly in `<script setup>`.
Warnings
- breaking The `offsetX` and `offsetY` props were renamed to `offsetSkid` and `offsetDistance` respectively. This change affects how positioning offsets are configured and was introduced in v0.6.0, becoming official in v1.0.0.
- breaking Version 1.4.0 introduced significant internal refactors, moving to Vue 3's `script setup` syntax and replacing the click-away directive with composables. While not strictly API-breaking for typical usage, custom implementations or reliance on the old directive might require adjustments.
- gotcha Prior to version 1.4.2, `vue3-popper` could encounter issues with `window` being undefined when rendering in a Nuxt 3 SSR (Server-Side Rendering) context, leading to hydration mismatches or server errors.
- deprecated Older versions (prior to v1.0.0) had less strict semantic versioning. From v1.0.0 onwards, the package strictly adheres to semantic versioning, meaning major versions will introduce breaking changes.
Install
-
npm install vue3-popper -
yarn add vue3-popper -
pnpm add vue3-popper
Imports
- Popper
import { Popper } from 'vue3-popper'; const Popper = require('vue3-popper');import Popper from 'vue3-popper';
- Popper (in Options API)
import { defineComponent } from 'vue'; import Popper from 'vue3-popper'; export default defineComponent({ components: { Popper }, // ... });import Popper from 'vue3-popper'; export default { components: { Popper }, // ... } - Popper (in Script Setup)
<script setup> import Popper from 'vue3-popper'; </script>
Quickstart
<template>
<section style="display: flex; gap: 20px; justify-content: center; padding: 50px;">
<Popper content="Hello, I am a simple string Popper!">
<button>Click for simple content</button>
</Popper>
<Popper placement="right" hover arrow :offset-distance="15">
<button>Hover for complex content</button>
<template #content>
<div style="padding: 10px; background-color: #333; color: white; border-radius: 5px;">
<h4>Interactive Popover</h4>
<p>This popover supports <b>HTML content</b> and is triggered on hover.</p>
<button style="background-color: lightblue; border: none; padding: 5px 10px; margin-top: 10px; cursor: pointer;">Action</button>
</div>
</template>
</Popper>
<Popper :show="showManualPopper" :offset-skid="10">
<button @click="showManualPopper = !showManualPopper">Toggle Manual Popper</button>
<template #content>
<div>Manually controlled popover!</div>
</template>
</Popper>
</section>
</template>
<script setup lang="ts">
import Popper from 'vue3-popper';
import { ref } from 'vue';
const showManualPopper = ref(false);
</script>
<style>
body { font-family: sans-serif; margin: 0; }
button { padding: 10px 15px; border: 1px solid #ccc; background-color: #f0f0f0; cursor: pointer; border-radius: 4px; }
</style>