element-hover
Track whether the pointer hovers an element.
| Package | @vizejs/composable/element-hover |
| Own the source | vize lib pull composable:element-hover |
| Runtime exports | useElementHover |
| Gzip budget | 2048 B |
Minimal setup
Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).
vp install @vizejs/composable
Import the entry directly. Call lifecycle-bound utilities inside <script setup> so cleanup follows the component scope; consult the runtime contract for this entry's SSR and hydration behavior.
import { useElementHover } from "@vizejs/composable/element-hover";
Try it
Show delayed guidance for a selected card
Delay pointer guidance for a real reactive element while keeping the advice independently available to keyboard and tap users.
What to observe: Move over the selected guide card for 300 ms to reveal the advice. Departure retains it for 200 ms; returning cancels the pending departure. Choose the other card to remove the previous target's listeners and reset the delayed flag. Show persistent guidance keeps the same advice visible without hovering.
useElementHover receives a computed native section target, with explicit delayEnter and delayLeave. pointerenter/pointerleave ignore movement among descendants. Opposite events cancel pending delay, and reactive target replacement removes old listeners, cancels its timer, and resets the hover flag. The output deliberately says Delayed pointer hover rather than instantaneous pointer position. The persistent guidance button owns separate state and works with Enter, Space, or ordinary tapping. SSR starts false and no target exists; the template refs resolve on the client. Scope disposal removes listeners and pending timers. No advice depends exclusively on hover.
Compare the initial and interacted states


Copy the example
Save this complete SFC in your Vue project. Its public imports and source are the same ones executed in the preview.
<script setup lang="ts">
import { computed, ref, useId, useTemplateRef } from "vue";
import { useElementHover } from "@vizejs/composable/element-hover";
const cardsId = useId();
const first = useTemplateRef<HTMLElement>("first");
const second = useTemplateRef<HTMLElement>("second");
const selected = ref("first");
const target = computed(() => (selected.value === "first" ? first.value : second.value));
const hovered = useElementHover(target, { delayEnter: 300, delayLeave: 200 });
const pinned = ref(false);
const guidanceVisible = computed(() => hovered.value || pinned.value);
</script>
<template>
<div class="composable-example">
<label :for="cardsId">Guidance target</label>
<select :id="cardsId" v-model="selected">
<option value="first">Compiler guide card</option>
<option value="second">Keyboard guide card</option>
</select>
<div class="guide-cards">
<section ref="first" class="guide-card" aria-label="Compiler guide card">
<strong>Compiler guide</strong>
<p>Compile one representative component.</p>
</section>
<section ref="second" class="guide-card" aria-label="Keyboard guide card">
<strong>Keyboard guide</strong>
<p>Review native input and focus.</p>
</section>
</div>
<button type="button" :aria-pressed="pinned" @click="() => (pinned = !pinned)">
{{ pinned ? "Hide persistent guidance" : "Show persistent guidance" }}
</button>
<output aria-live="polite">
Delayed pointer hover: {{ hovered ? "yes" : "no" }} · Persistent guidance:
{{ pinned ? "yes" : "no" }}
</output>
<p v-if="guidanceVisible">
Review the selected card's behavior, diagnostics, and native controls.
</p>
<p>
Pointer guidance waits 300 ms on entry and 200 ms on departure. Switching the selected card
removes the previous listeners and pending delay. The native guidance button independently
keeps the same advice available to keyboard and tap users.
</p>
</div>
</template>
<style scoped>
.guide-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
gap: 12px;
}
.guide-card {
padding: 12px;
border: 1px solid currentColor;
border-radius: 8px;
}
</style>
Runtime contract
| Utility | Category | Stability | SSR | Hydration | Cleanup | Targets | Host globals | Uses |
|---|---|---|---|---|---|---|---|---|
useElementHover |
input | experimental | deterministic-fallback | stable | reactive-scope | web, desktop | globalThis |
resolveElement, tryOnScopeDispose |
API
useElementHover
Track whether the pointer hovers an element. Uses pointerenter/pointerleave (which ignore descendants) with optional enter/leave delays; a pending delay is cancelled by the opposite event. Server renders report false; listeners and timers are released with the owning reactive scope.
function useElementHover( target: MaybeElementTarget, options: UseElementHoverOptions = {}, ): Readonly<Ref<boolean>>
Types
UseElementHoverOptions
Options for useElementHover.
| Member | Type | Description |
|---|---|---|
delayEnter? |
number |
Milliseconds to wait before reporting hover. |
delayLeave? |
number |
Milliseconds to wait before reporting the end of hover. |
scheduler? |
TimeoutScheduler |
Owns the delay timer. |