Untitled

mail@pastecode.io avatar
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>