Interactions

useFocus

Opens and closes floating content on keyboard focus.

useFocus opens and closes a floating node when the anchor gains or loses focus. By default, it activates only for keyboard focus (:focus-visible), preventing unwanted tooltips when clicking with a mouse.

Type

function useFocus(node: FloatingNode, options?: UseFocusOptions): UseFocusReturn;

interface UseFocusOptions {
  enabled?: MaybeRefOrGetter<boolean>;
  requireFocusVisible?: MaybeRefOrGetter<boolean>;
  ignoreFocusOut?: (target: EventTarget | null) => boolean;
}

interface UseFocusReturn {
  cleanup: () => void;
}

Options

NameTypeDefaultNotes
enabledMaybeRefOrGetter<boolean>trueReactive toggle. Disabling removes all focus listeners.
requireFocusVisibleMaybeRefOrGetter<boolean>trueWhen true, opens only for keyboard navigation, ignoring pointer clicks.
ignoreFocusOut(target: EventTarget | null) => booleanundefinedPredicate to prevent closing when focus transitions to selected elements.

Returns

NameTypeNotes
cleanup() => voidManually unregisters all focus listeners. Also executes on component unmount.

Details

Focus Visible Heuristic

Most browsers set focus on a button when clicked with a mouse or tapped on mobile. If focus listeners opened a tooltip unconditionally, clicking a button would leave a sticky tooltip floating on screen.

With requireFocusVisible: true (the default), useFocus inspects the browser's :focus-visible pseudo-class. Tabbing into a button opens the tooltip; clicking the button does not.

Deferred Blur and Family Awareness

When focus leaves the anchor, dismissal is deferred to the next tick to verify where focus landed:

  • If focus moved into the floating panel, the surface remains open.
  • If focus moved into a child submenu or descendant overlay, node.contains(activeEl) keeps the parent surface open.
  • Switching tabs in the browser and returning will not reopen a closed surface.

Accessibility Pairing

Combine useFocus with useHover and useRole(node, { role: "tooltip" }) to fulfill WCAG Success Criterion 1.4.13 (Content on Hover or Focus).

Example

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

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

const node = useFloatingNode({ anchorEl, floatingEl });
usePosition(node, {
  placement: "top",
  middlewares: {
    offset: 6,
    flip: true,
    shift: { padding: 8 },
  },
});

useHover(node);
useFocus(node);
useRole(node, { role: "tooltip" });
</script>

<template>
  <button ref="anchorEl">Tab to focus me</button>

  <div v-if="node.open.value" ref="floatingEl" role="tooltip">Helpful keyboard-accessible hint</div>
</template>

See Also

Released under the MIT License. Copyright © 2026