floating-vue
Vue 3 tooltips, dropdowns, and menus powered by Floating UI for smart, viewport-aware positioning.
Repository Health
Technical Analysis
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-tooltipdirective for simple string or HTML tooltips with zero markup overhead - Renderless
VDropdownandVMenucomponents with scoped slots for fully custom trigger/content markup - Floating UI middleware wired in automatically: offset, shift, flip, arrow, autoPlacement, and size
- A shared
Popperprimitive 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
$extendso 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.
Used by 4 apps in this directory
Chatwoot
Customer Support
Open-source omnichannel customer support platform with AI-powered agents, live chat, and self-hosting — a full Intercom and Zendesk alternative.
Enso
Analytics · Data Engineering · Low Code Platforms
A visual and textual programming platform for data prep and analysis where the node graph and the underlying Enso code are always perfectly in sync, built by an Alteryx co-founder on a GraalVM engine.
Mixpost
Marketing · Social Media
Self-host your own social media scheduler and publish to 11 platforms without subscriptions or data lock-in.
Vikunja
Project Management
Self-hosted task management with natural-language quick-add, multiple views, and a fully documented REST API — your tasks, your infrastructure, zero lock-in.