Untitled
unknown
plain_text
a year ago
2.4 kB
4
Indexable
Never
<template> <div> <slot name="activator" @click="toggleTooltip"></slot> <div v-if="showTooltip" ref="tooltip" :style="tooltipPosition" class="tooltip"> <slot></slot> </div> </div> </template> <script> import { ref, watch, onMounted, onBeforeUnmount } from 'vue'; export default { name: 'Tooltip', setup() { const showTooltip = ref(false); const toggleTooltip = () => { showTooltip.value = !showTooltip.value; }; const closeTooltip = (event) => { if (!event.target.closest('.tooltip')) { showTooltip.value = false; } }; const handleEscapeKey = (event) => { if (event.key === 'Escape') { showTooltip.value = false; } }; onMounted(() => { window.addEventListener('click', closeTooltip); window.addEventListener('keydown', handleEscapeKey); }); onBeforeUnmount(() => { window.removeEventListener('click', closeTooltip); window.removeEventListener('keydown', handleEscapeKey); }); const tooltipPosition = ref({}); watch(showTooltip, (newValue) => { if (newValue) { const tooltip = document.querySelector('.tooltip'); const activator = document.querySelector('.tooltip-activator'); const tooltipRect = tooltip.getBoundingClientRect(); const activatorRect = activator.getBoundingClientRect(); const viewportWidth = window.innerWidth; let left, top; if (activatorRect.left < tooltipRect.width) { left = `${activatorRect.right}px`; } else if (activatorRect.left + tooltipRect.width > viewportWidth) { left = `${activatorRect.left - tooltipRect.width}px`; } else { left = `${activatorRect.left}px`; } if (activatorRect.top < tooltipRect.height) { top = `${activatorRect.bottom}px`; } else { top = `${activatorRect.top - tooltipRect.height}px`; } tooltipPosition.value = { left, top }; } }); return { showTooltip, toggleTooltip, tooltipPosition, }; }, }; </script> <style scoped> .tooltip { position: absolute; z-index: 999; background-color: #f1f1f1; padding: 10px; border-radius: 4px; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); } </style>