floating-vue

Vue 3 tooltips, dropdowns, and menus powered by Floating UI for smart, viewport-aware positioning.

Library
npm
v5.2.2
3,464stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
56/100Fair
Development Activity32
Maintenance32
Community60
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
75/100Good
Architecture78
Code Quality52
Innovation80
Learning Curve90

Floating Vue (formerly v-tooltip) gives Vue applications tooltips, dropdowns, and menus that position themselves intelligently relative to their trigger element. It wraps Floating UI’s positioning engine in a set of renderless Vue components and a v-tooltip directive, so the same underlying popper logic powers three different levels of API complexity depending on how much control an app needs.

Under the hood, a single Popper primitive coordinates show/hide state, nested-popper awareness (so a submenu inside a dropdown behaves correctly), auto-hide on outside click or touch, hover-intent detection, and instant-move between adjacent poppers. Themes cascade through a $extend inheritance system, letting menu reuse and override dropdown’s defaults instead of redefining them. A first-party Nuxt module handles SSR directive transforms and CSS injection automatically.

What You Get

  • A v-tooltip directive for simple string or HTML tooltips with zero markup overhead
  • Renderless VDropdown and VMenu components with scoped slots for fully custom trigger/content markup
  • Floating UI middleware wired in automatically: offset, shift, flip, arrow, autoPlacement, and size
  • A shared Popper primitive that keeps nested poppers (submenus inside dropdowns) in sync
  • A Nuxt module (floating-vue/nuxt) that wires up SSR directive transforms and CSS injection
  • Theme inheritance via $extend so custom themes can build on the built-in tooltip/dropdown/menu presets

Common Use Cases

  • Adding hover/focus tooltips to icons, form fields, or truncated text without hand-rolling positioning math
  • Building click-triggered dropdown menus and context menus that auto-flip near viewport edges
  • Nested navigation menus where hovering a submenu item must not close its parent menu
  • Popover-style widgets (date pickers, color pickers, filter panels) anchored to a trigger element

Under The Hood

Architecture A single renderless Popper component (src/components/Popper.ts) is the foundation for Tooltip, Dropdown, and Menu — each just applies a different theme and prop set on top of it. Popper instances register with each other through Vue’s provide/inject (keyed on a private __floating-vue__popper symbol) so a child popper can tell its parent “stay open, I’m still shown,” enabling correct nested-menu behavior. The v-tooltip directive takes a different route entirely: it lazily mounts a hidden, dedicated Vue app whose render function maps a shared reactive array of directive instances to TooltipDirective components, letting the directive create and destroy floating elements without any host component in the user’s template. Global mutable state at module scope (an array of currently-shown poppers, tracked mouse coordinates for “is the user aiming at the popper” hover-intent detection, and document-level mousedown/click listeners for auto-hide) is shared across every Popper instance on the page — an unusual but deliberate choice for a cross-cutting UI concern like this. Tech Stack Written in TypeScript against Vue 3 (peer dependency ^3.2), with @floating-ui/dom (~1.1.1) supplying the actual positioning middleware (offset, shift, flip, arrow, autoPlacement, size) and vue-resize handling resize observation. The package builds with Vite plus vue-tsc for standalone type declarations, and lives in a pnpm workspace alongside a separate VitePress documentation site and demo app. Tests run through @peeky/test, a Vite-native test runner, combined with @vue/test-utils v1 and babel-jest for the transform pipeline. Code Quality Only a single spec file was found (src/directives/v-tooltip.spec.ts, 31 lines), covering the directive’s placement-resolution helpers — thin coverage for a library of this surface area, and there is no test or lint step wired into GitHub Actions (the only workflow present creates a GitHub Release when a version tag is pushed). ESLint is configured with typescript-eslint and eslint-plugin-vue, and the codebase follows a consistent $_-prefixed convention for private component methods. Type safety has a known gap: the exported FloatingVueConfig type is explicitly typed as any // @TODO in config.ts, and a few DOM-query calls swallow errors silently in empty catch blocks. API Design The library offers three ways to reach the same underlying behavior — a directive for the simplest case, and renderless components with scoped slots when the trigger/content markup needs full control — so an app can start with v-tooltip="'text'" and grow into custom dropdowns without switching libraries. Cascading theme inheritance (menu extends dropdown’s defaults via $extend) keeps configuration DRY. Deprecated props (autoMinSize, autoMaxSize) still work but emit console warnings pointing at their replacements, which is a considerate migration path. The Nuxt module removes the most common integration friction (SSR directive transforms, CSS injection) that would otherwise require manual setup.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search