I am using the Field from vee-validate which displays the select dropdown options. I want to add a PopoverPanel/Popover from @headlessui/vue to display some tooltip information on hovering over the Field so I have created a generic component which wraps the vee-validate Field.
After adding Popover I cannot select an option from vee-validate Field. I want the feature to get the tooltip menu when I hover over the vee-validate Select Field but when I click on the vee-validate Field I want to select any options just like any other Select dropdown.
I have created a sample project to reproduce the issue in CodeSandBox.
Following is the code I have in my Nuxt 3 application:
components/GenericTooltip.vue:
<template>
<Popover v-slot="{ open, close }">
<PopoverButton
class="focus:outline-none mr-2"
@mouseover="hoverPopover($event, open)"
@mouseleave="closePopover($event, close)"
>
<slot />
</PopoverButton>
<PopoverPanel
class="mt-3 absolute z-50 dark:bg-gray-700 bg-gray-300 dark:text-white text-black rounded-lg p-2 inline-block after:absolute after:border-4 dark:after:border-gray-700 after:border-gray-300 after:-left-0 after:top-1/3 after:-translate-x-1/2 after:rotate-45 transform -translate-y-[30%]"
>
{{ tooltipInfo }}
</PopoverPanel>
</Popover>
</template>
<script setup>
import { Popover, PopoverButton, PopoverPanel } from "@headlessui/vue";
const popoverHover = ref(false);
const popoverTimeout = ref();
const tooltipInfo = ref("");
//On hover show the tooltip with information
const hoverPopover = (e, open) => {
console.log("1. Hover Pop Over");
console.log(e);
popoverHover.value = true;
if (!open) {
e.target.parentNode.click();
}
//Add tooltip information
tooltipInfo.value = "This is the ToolTip Sample Value";
};
//On mouse leave close it
const closePopover = (e, close) => {
console.log("3. Hover CLose Pop Over");
popoverHover.value = false;
if (popoverTimeout.value) clearTimeout(popoverTimeout.value);
popoverTimeout.value = setTimeout(() => {
if (!popoverHover.value) {
close();
}
}, 100);
};
</script>
Following is its usage and wrapping the vee-validate Field component:
components/HoverMenuTest.vue:
<template>
<div class="flex flex-col items-center w-full">
<GenericTooltip>
<div
class="relative w-full h-full bg-gray-50 dark:text-white dark:bg-gray-700 dark:border-gray-600 border-gray-300 border rounded text-center block overflow-hidden"
>
<Field
as="select"
:name="name"
v-model="item"
class="w-full h-full bg-transparent p-2 outline-none dark:bg-gray-700"
>
<option
v-for="option in options"
:value="option.value"
:key="option.value"
:selected="option.selected"
>
{{ option.text }}
</option>
</Field>
<Icon
icon="iconamoon:arrow-down-2-bold"
class="absolute right-2 top-1/2 transform -translate-y-1/2"
/>
</div>
<div class="text-center">
<ErrorMessage :name="name" class="text-red-500 mt-2 italic" />
</div>
</GenericTooltip>
</div>
</template>
<script setup>
import { Icon } from "@iconify/vue";
import { Field, ErrorMessage } from "vee-validate";
const props = defineProps({
options: {
type: Array,
required: false,
},
name: {
type: String,
required: false,
},
});
const item = ref(props.options[0].value);
</script>
<style>
select {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background-image: none;
}
</style>
Following is their usage in pages/Test.vue:
<template>
<HoverMenuTest v-model="type" :name="'type'" :options="options" />
</template>
<script setup>
const type = useState("type", () => ({}));
const options = [
{ value: "value1", text: "Option 1", selected: true },
{ value: "value2", text: "Option 2" },
{ value: "value3", text: "Option 3" },
];
</script>
The following GIF shows that when I hover over the Field I can get the tooltip information as I want but when clicking on the Field I cannot get any dropdown options.
If I remove the <GenericTooltip> wrapping in HoverMenuTest.vue for the vee-validate Field, it works fine and can select the required options. I want this GenericToolTip.vue component as I plan to reuse it in multiple places rather than copying the code.
I tried adding the @click.stop to my PopoverButton:
<PopoverButton
class="focus:outline-none mr-2"
@mouseover="hoverPopover($event, open)"
@mouseleave="closePopover($event, close)"
@click.stop="handleClick($event, open, close)"
>
<slot />
</PopoverButton>
// Handle click event to prevent Popover from capturing it when Field is clicked
const handleClick = (e, open, close) => {
console.log(e.target.tagName);
if (e.target.tagName === "SELECT") {
// If the Field is clicked, prevent the Popover from capturing the click event
e.stopPropagation();
e.preventDefault();
} else {
// Otherwise, handle the click event as usual
hoverPopover(e, open);
}
};
But this is also not working and I am still unable to see dropdown options.
