80 lines
2.0 KiB
Vue
80 lines
2.0 KiB
Vue
<template>
|
|
<div class="inline-block" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave" @mousemove="handleMouseMove">
|
|
<slot />
|
|
<Teleport to="body">
|
|
<div v-if="show && text" ref="tooltipRef" class="fixed px-2.5 py-1.5 text-xs font-medium text-white bg-gray-900 dark:bg-gray-700 rounded-md shadow-lg whitespace-nowrap pointer-events-none" :style="tooltipStyle">
|
|
{{ text }}
|
|
</div>
|
|
</Teleport>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, computed } from 'vue';
|
|
|
|
defineProps<{
|
|
text: string;
|
|
}>();
|
|
|
|
const show = ref(false);
|
|
const mouseX = ref(0);
|
|
const mouseY = ref(0);
|
|
const tooltipRef = ref<HTMLElement | null>(null);
|
|
|
|
const handleMouseEnter = () => {
|
|
show.value = true;
|
|
};
|
|
|
|
const handleMouseLeave = () => {
|
|
show.value = false;
|
|
};
|
|
|
|
const handleMouseMove = (e: MouseEvent) => {
|
|
mouseX.value = e.clientX;
|
|
mouseY.value = e.clientY;
|
|
};
|
|
|
|
const tooltipStyle = computed(() => {
|
|
const offsetX = 12;
|
|
const offsetY = 16;
|
|
const padding = 8;
|
|
|
|
let x = mouseX.value + offsetX;
|
|
let y = mouseY.value + offsetY;
|
|
|
|
// Get tooltip dimensions (estimate if not mounted yet)
|
|
const tooltipWidth = tooltipRef.value?.offsetWidth || 200;
|
|
const tooltipHeight = tooltipRef.value?.offsetHeight || 30;
|
|
|
|
// Screen boundaries
|
|
const screenWidth = window.innerWidth;
|
|
const screenHeight = window.innerHeight;
|
|
|
|
// Adjust horizontal position if too close to right edge
|
|
if (x + tooltipWidth + padding > screenWidth) {
|
|
x = mouseX.value - tooltipWidth - offsetX;
|
|
}
|
|
|
|
// Adjust horizontal position if too close to left edge
|
|
if (x < padding) {
|
|
x = padding;
|
|
}
|
|
|
|
// Adjust vertical position if too close to bottom edge
|
|
if (y + tooltipHeight + padding > screenHeight) {
|
|
y = mouseY.value - tooltipHeight - offsetY;
|
|
}
|
|
|
|
// Adjust vertical position if too close to top edge
|
|
if (y < padding) {
|
|
y = padding;
|
|
}
|
|
|
|
return {
|
|
left: `${x}px`,
|
|
top: `${y}px`,
|
|
zIndex: 99999,
|
|
};
|
|
});
|
|
</script>
|