import { type MaybeRefOrGetter, toValue } from "@vueuse/core"; import { ref, watch } from "vue"; export function useAccessibleHover( elementRef: MaybeRefOrGetter, onHoverEnter?: () => void, onHoverExit?: () => void, ) { const isHovering = ref(false); let previousElement: HTMLElement | null = null; function enter() { if (!isHovering.value) { onHoverEnter?.(); isHovering.value = true; } } function exit() { if (isHovering.value) { onHoverExit?.(); isHovering.value = false; } } function keydown(event: KeyboardEvent) { if (event.key === "Escape") { exit(); } } watch( () => toValue(elementRef), (element) => { if (previousElement) { exit(); previousElement.removeEventListener("mouseenter", enter); previousElement.removeEventListener("focus", enter); previousElement.removeEventListener("mouseleave", exit); previousElement.removeEventListener("blur", exit); previousElement.removeEventListener("keydown", keydown); } if (element) { element.addEventListener("mouseenter", enter); element.addEventListener("focus", enter); element.addEventListener("mouseleave", exit); element.addEventListener("blur", exit); element.addEventListener("keydown", keydown); } previousElement = element; }, { immediate: true, }, ); return isHovering; }