Floating Vue (v-tooltip)
Floating Vue, currently at version 5.x, is a robust and flexible library for creating tooltips, popovers, dropdowns, and menus in Vue 3 applications. It is the successor to the original `v-tooltip` package, having been rebranded from `floating-vue` v2.x to `v-tooltip` v5.x to streamline versioning and prevent confusion, while retaining the same underlying codebase and functionality. The library leverages `@floating-ui/dom` for efficient and precise anchor positioning, ensuring floating elements are always positioned optimally. It offers both directive-based (`v-tooltip`, `v-close-popper`) and component-based (`VDropdown`, `VTooltip`, `VMenu`) usage, supporting a wide range of interactive UI patterns. Releases are regular, with a focus on Vue 3 compatibility, performance, and improved TypeScript typings. Key differentiators include its extensive configuration options, powerful theming capabilities, and seamless integration with Vue 3's composition API.
Common errors
-
ReferenceError: Element is not defined
cause This error typically occurs when Floating Vue components or directives are used in a server-side rendering (SSR) environment without proper client-only rendering or SSR awareness. `floating-vue` v5.0.1 specifically fixed an issue related to this.fixEnsure that Floating Vue components are rendered client-side only during SSR, or integrate with your SSR framework (e.g., Nuxt) to handle DOM-dependent code. For Vue, wrap the component in `<ClientOnly>` or dynamically import it on the client. Upgrading to the latest v5.x might also resolve some edge cases. -
[Vue warn]: Failed to resolve component: VTooltip
cause This warning indicates that the `VTooltip` component (or `VDropdown`, `VMenu`) is not globally registered or correctly imported for local use. This often happens if `app.use(FloatingVue)` is missed or if the import path is incorrect.fixIf using globally, ensure `import FloatingVue from 'floating-vue'; app.use(FloatingVue);` is present in your app entry. If importing locally for `script setup`, ensure `import { VTooltip } from 'floating-vue';` is used in the component script. Remember the package name for import is `floating-vue`. -
TypeError: Cannot read properties of undefined (reading 'themes')
cause This error usually occurs when attempting to configure global `options.themes` or other global options without correctly importing `options` from the `floating-vue` package or before the plugin has been installed.fixEnsure `import { options } from 'floating-vue';` is at the top of your configuration file and that any modifications to `options` happen after `app.use(FloatingVue)` if you're modifying them post-installation.
Warnings
- breaking The `v-tooltip` package underwent a major rebranding and refactor in version 5.0.0. It is now essentially `floating-vue` v2.0.0, and primarily supports Vue 3. Previous versions (v2, v3, v4 of `v-tooltip`) were for Vue 2. Directly upgrading from `v-tooltip` v4 or earlier to v5 will cause breaking changes due to Vue version incompatibility and API changes.
- breaking The package name for imports has changed from `v-tooltip` to `floating-vue` in v5.0.0, even though the npm package name remains `v-tooltip`. This can lead to import errors if not updated.
- breaking In `floating-vue` (and thus `v-tooltip` v5), the positioning library changed from `Popper.js` 2 to `Floating UI`. This replaced the `modifiers` prop with new dedicated props like `preventOverflow`, `overflowPadding`, `shiftCrossAxis`, and `flip`. The `offset` prop also changed from an array `[skidding, distance]` to separate `distance` and `skidding` props.
- deprecated The components `VTooltip` and `VClosePopper` (when used as components) received deprecation notices in `v5.2.1` in favor of their directive counterparts, `v-tooltip` and `v-close-popper`, especially for `script setup` usage.
- gotcha Default CSS styles are not automatically included with the plugin installation. If you don't import the default styles, tooltips and popovers will appear unstyled.
- gotcha By default, HTML content is enabled in tooltips. If your tooltip content comes from user input, this can introduce Cross-Site Scripting (XSS) vulnerabilities.
Install
-
npm install v-tooltip -
yarn add v-tooltip -
pnpm add v-tooltip
Imports
- FloatingVue
import VTooltip from 'v-tooltip' Vue.use(VTooltip)
import FloatingVue from 'floating-vue' app.use(FloatingVue)
- vTooltip
import { vTooltip } from 'v-tooltip'import { vTooltip } from 'floating-vue' - VDropdown
import { VDropdown } from 'v-tooltip'import { VDropdown } from 'floating-vue' - options
import { options } from 'v-tooltip'import { options } from 'floating-vue' options.themes.myTheme = { /* ... */ }
Quickstart
<!-- App.vue -->
<script setup lang="ts">
import { ref } from 'vue';
import { VTooltip, VDropdown } from 'floating-vue';
import 'floating-vue/dist/style.css'; // Don't forget to import the CSS
const tooltipMessage = ref('Hello from v-tooltip directive!');
const dropdownContent = ref('This is a dropdown menu.');
</script>
<template>
<main class="container">
<h1>Floating Vue (v-tooltip) Demo</h1>
<p>Using the v-tooltip directive:</p>
<button v-tooltip="tooltipMessage" class="btn">
Hover me (Directive)
</button>
<p>Using the VDropdown component:</p>
<VDropdown>
<button class="btn">Click for Dropdown</button>
<template #popper>
<div class="dropdown-content">
{{ dropdownContent }}
<button class="btn">Action 1</button>
<button class="btn">Action 2</button>
</div>
</template>
</VDropdown>
</main>
</template>
<style>
body { font-family: sans-serif; margin: 20px; }
.container { display: flex; flex-direction: column; gap: 20px; align-items: flex-start; }
.btn { padding: 8px 15px; border: 1px solid #ccc; border-radius: 4px; background-color: #f0f0f0; cursor: pointer; }
.dropdown-content { padding: 10px; background: white; border: 1px solid #eee; border-radius: 4px; box-shadow: 0 2px 8px rgba(0,0,0,0.15); display: flex; flex-direction: column; gap: 5px; }
</style>
<!-- main.ts or main.js -->
<script type="module">
import { createApp } from 'vue';
import App from './App.vue';
import FloatingVue from 'floating-vue';
import 'floating-vue/dist/style.css';
const app = createApp(App);
app.use(FloatingVue);
app.mount('#app');
</script>