Getting Started

Introduction

What VFloat is, what problem it solves, and how the pieces fit together.

What is VFloat?

VFloat is a Vue 3 library for building floating UI elements like tooltips, popovers, dropdown menus, and dialogs. It provides composable building blocks for positioning calculations, user interactions, focus management, and overlay coordination without imposing markup, styles, or prebuilt components.

Why you need VFloat

Building floating UI by hand requires solving geometric collisions, event timing, and focus management from scratch. A simple tooltip needs viewport detection to avoid clipping and hover delays to avoid flickering. A dropdown menu needs keyboard navigation, outside-click detection, and Escape key handling.

Pre-built component libraries solve these problems, but they force their markup, styles, and design tokens on you. VFloat handles the positioning math, DOM listeners, and state coordination behind the scenes, letting you build custom, fully accessible floating surfaces using your own templates and styles.

How it works

Every floating surface comes down to two questions: where should it appear, and when should it be visible? VFloat divides these responsibilities across dedicated composables connected by a shared floating node:

  • useFloatingNode holds the shared state and element references used by the various composables.
  • usePosition handles the positioning calculations. It computes where to place your floating element and automatically applies the computed positioning styles to your floating element.
  • useHover decides when the floating element should be visible and when it should hide based on hover behavior.

Here is a minimal tooltip that ties these three parts together:

<script setup lang="ts">
import { ref } from "vue";
import { useEscapeKey, useFloatingNode, usePosition, useHover } from "v-float";

const anchorEl = ref<HTMLElement | null>(null);
const floatingEl = ref<HTMLElement | null>(null);

// 1. Hold shared state and element refs
const node = useFloatingNode({ anchorEl, floatingEl });

// 2. WHERE: calculate coordinates and auto-apply styles
usePosition(node, {
  placement: "top",
  middlewares: { offset: 8 },
});

// 3. WHEN: manage visibility based on user input
useHover(node);
useEscapeKey(node);
</script>

<template>
  <button ref="anchorEl" type="button">Hover me</button>

  <div v-if="node.open.value" ref="floatingEl" role="tooltip">Tooltip content</div>
</template>

Because both composables plug into the same node, they work together automatically. When useHover opens the tooltip, usePosition computes its placement. The first tooltip guide walks through the full component step by step.

Building different surfaces

You won't find a <Menu> component or a useTooltip() composable in VFloat. That's intentional. Instead, you get a set of focused composables that you mix and match to build whatever you need.

Want to turn the tooltip from above into a popover? Swap hover for click, and add outside-click dismissal and Escape key handling:

useClick(node);
useOutsideClick(node);
useEscapeKey(node);

Building a dropdown menu? Keep the click trigger and add roving keyboard focus:

const itemEls = shallowRef<(HTMLElement | null)[]>([]);

useClick(node);
useOutsideClick(node);
useEscapeKey(node);
useRovingFocus(node, { elementsList: itemEls });

Need a modal dialog? Add focus management to trap focus inside the dialog while it's open:

useClick(node);
useFocusTrap(node, { modal: true });
useOutsideClick(node);
useEscapeKey(node);

Relationship to Floating UI

VFloat draws heavily from Floating UI. The middleware pipeline (offset, flip, shift, size, arrow, hide, autoPlacement) follows the same mental model, and some composable names will look familiar.

However, VFloat is a dedicated Vue 3 library with its own reactive API shape. If you are coming from Floating UI, the core concepts transfer, but the call sites and reactive state patterns do not.

Where to go next

If this is your first time with VFloat, build a tooltip step by step to see how all the pieces connect in a real component.

If you already know what you're building, pick the closest guide:

When you need exact signatures and defaults, the API Reference has every option and return value documented.

Released under the MIT License. Copyright © 2026