Search code examples
htmlcssvue.jstailwind-cssheadless-ui

How to add a pointer towards the text using the tailwind css for the PopoverPanel of the headlessui/vue?


I am developing a custom tooltip menu which shows some tooltips on the hover of the text. As per my requirement, I want to add a pointer to my tooltip which points to the text on which hovered when showing the tooltip information.

To build the tooltip menu I have made use of the @headlessui/vue within my Nuxt 3 application. Everything works fine but the only problem is that I am unable to add a pointer towards the text for my PopoverPanel. Can someone please let me know how to add a pointer towards the text?

Following is the code I have which shows the tooltip menu on hover over the text in nuxt 3 composition api:

<template>
  <Popover v-slot="{ open, close }" class="h-0">
    <PopoverButton class="focus:outline-none">
      <p
        @mouseover.native.stop.prevent="hoverPopover($event, open)"
        @mouseleave.native.stop.prevent="closePopover($event, close)"
      >
        Hover ME
      </p>
    </PopoverButton>

    <PopoverPanel
      class="absolute z-50 bg-gray-700 rounded-lg text-white px-3 py-2 text-sm font-normal inline-block ring-1 ring-black ring-opacity-5 focus:outline-none"
      @mouseover.native.stop.prevent="popoverHover = true"
      @mouseleave.native.stop.prevent="closePopover($event, close)"
    >
      <slot> Text to be shown on hover over </slot>
    </PopoverPanel>
  </Popover>
</template>

<script setup>
import { Popover, PopoverButton, PopoverPanel, Portal } from "@headlessui/vue";

const popoverHover = ref(false);
const popoverTimeout = ref();

//On hover show the tooltip with information
const hoverPopover = (e, open) => {
  popoverHover.value = true;
  if (!open) {
    e.target.parentNode.click();
  }
};

//On mouse leave close it
const closePopover = (e, close) => {
  popoverHover.value = false;
  if (popoverTimeout.value) clearTimeout(popoverTimeout.value);
  popoverTimeout.value = setTimeout(() => {
    if (!popoverHover.value) {
      close();
    }
  }, 100);
};
</script>

I want to add a pointer towards the text something similar to this:

enter image description here


Solution

  • in your PopoverPanel, you can use Tailwind to build a caret to indicate your desired pointer. I did a quick test on Tailwind Play to illustrate.

    The class you need is: after:content-[''] after:absolute after:w-0 after:h-0 after:border-4 after:border-gray-700 after:-bottom-1 after:left-1/2 after:-translate-x-1/2 after:rotate-45

    Essentially, your PopoverPanel will now look like:

    <PopoverPanel
      class="absolute z-50 bg-gray-700 rounded-lg text-white px-3 py-2 text-sm font-normal inline-block ring-1 ring-black ring-opacity-5 focus:outline-none after:content-[''] after:absolute after:w-0 after:h-0 after:border-4 after:border-gray-700 after:-bottom-1 after:left-1/2 after:-translate-x-1/2 after:rotate-45"
      @mouseover.native.stop.prevent="popoverHover = true"
      @mouseleave.native.stop.prevent="closePopover($event, close)"
    >
      <slot> Text to be shown on hover over </slot>
    </PopoverPanel>
    

    You can see my test on Tailwind Play.

    Hope this helps :)