0

I am trying to create a Vue component which wraps a Popoverfrom headlessui

I am trying to toggle open close using the slot binding as suggested in the popover docs. I cannot get this to work. Nothing appears in the UI, even if I had it working ok from within the element itself, granted that is neither a good place to put it because the elements render as many rows there are in the table.

Does anyone have any wisdom surrounding headless UI popovers in Vue3 on a table row?

EDIT: Ok adding static to the PopoverPanelmakes it render when open=true , the issue now being that multiple instances render based on the number of elements in the table. So this is a new issue.

enter image description here

<template>
  <div>
    <Popover :slot="{pop}">
      <transition
        enter-active-class="transition duration-200 ease-out"
        enter-from-class="translate-y-1 opacity-0"
        enter-to-class="translate-y-0 opacity-100"
        leave-active-class="transition duration-150 ease-in"
        leave-from-class="translate-y-0 opacity-100"
        leave-to-class="translate-y-1 opacity-0"
      >
        <PopoverPanel static class="absolute z-9 mt-3 max-w-sm -translate-x-1/2 transform sm:px-0 lg:max-w-3xl">
      <div class="rounded-lg shadow-lg w-full m-2">
        <div
          v-if="pop"
          ref="popover"
          class="flex flex-col p-2"
        >
          <ButtonTemp label="Send reminder" btn-type="m-0.5 bg-neutral-200 text-neutral-900 text-left text-caption hover:bg-neutral-900 hover:text-neutral-100" icon-left>
            <IconsMail />
          </ButtonTemp>
          <ButtonTemp label="Share candidate" btn-type="m-0.5 bg-neutral-200 text-neutral-900 text-caption hover:bg-neutral-900 hover:text-neutral-100" icon-left>
          <IconsExternalLink />
          </ButtonTemp>
          <ButtonTemp label="Remove from assignment" btn-type="m-0.5 bg-neutral-200 text-neutral-900 text-caption hover:bg-danger-100 hover:text-neutral-100" icon-left>
          <IconsUserMinus />
          </ButtonTemp>
        </div>
      </div>
    </PopoverPanel>
  </transition>
</Popover>
<script setup lang="ts">
import { Ref } from '@vue/runtime-core';
import { Popover, PopoverButton, PopoverPanel } from '@headlessui/vue';
import { ButtonTemp, IconsMail, IconsExternalLink, IconsUserMinus } from '@/.nuxt/components';

const pop: Ref<boolean> = ref(true);

interface IContextMenu {
  open: boolean;
}

const props = defineProps<IContextMenu>();
const isOpen = toRef(props, 'open');

watch(isOpen, (is) => {
  if (is) {
   console.log('open', is);
   pop.value = !pop.value;
 }
});

onMounted(() => {
  pop.value = true;
});

</script>

Component where it is to be used: ......

<td class="group-hover:text-neutral-100 rounded-r">
        <button
          class="m-auto h-8 w-8 rounded-sm flex justify-center items-center group-hover:bg-neutral-700 cursor-pointer"
          @click="handleClick(candidate.id, '')"
        >
          <ContextMenu :open="open" /> // Popover wrapped component

          <IconsVerticalMenu />
        </button>
      </td>
    </tr>
godhar
  • 1,128
  • 1
  • 14
  • 34

0 Answers0