Closed ragulka closed 1 year ago
Hi @ragulka, can you provide a minimal reproducible question example (like github repo, codesandbox, stackblitz...) for me to debug 😅? I will refer to your suggestion and try to find a solution.
Hi @ragulka, I think this can be broken down into two parts.
First, regarding the change of Teleport to use the <Portal>
component of Headless UI, I have already modified it and released it to v0.11, thank you for your reminder.
Second, if you want to use Popover
and Combobox
, you don’t need to use the portal, here is an example for you to test:
<template>
<Popover v-slot="{ close }">
<Float
placement="bottom-start"
:offset="15"
:shift="6"
:flip="10"
arrow
enter="transition duration-200 ease-out"
enter-from="opacity-0 -translate-y-1"
enter-to="opacity-100 translate-y-0"
leave="transition duration-150 ease-in"
leave-from="opacity-100 translate-y-0"
leave-to="opacity-0 -translate-y-1"
>
<PopoverButton class="px-3 py-1.5 flex justify-center items-center bg-rose-50 hover:bg-rose-100 text-rose-500 rounded">
Open
</PopoverButton>
<PopoverPanel class="w-[240px] bg-white border border-gray-200 rounded-md shadow-lg focus:outline-none">
<FloatArrow class="absolute bg-white w-5 h-5 rotate-45 border border-gray-200" />
<div class="relative p-3 bg-white rounded-md">
<label class="inline-block mb-1">Combobox</label>
<Combobox v-model="selected">
<Float
as="div"
class="relative"
placement="bottom-start"
:offset="4"
leave="transition ease-in duration-100"
leave-from="opacity-100"
leave-to="opacity-0"
floating-as="template"
@hide="query = ''"
>
<div class="relative w-full text-left bg-white border border-gray-200 rounded-lg shadow-md cursor-default focus:outline-none sm:text-sm overflow-hidden">
<ComboboxInput
class="w-full border-none py-2 pl-3 pr-10 text-sm leading-5 text-gray-900 focus:outline-none focus:ring-0"
:display-value="person => person?.name"
@change="query = $event.target.value"
/>
<ComboboxButton class="absolute inset-y-0 right-0 flex items-center pr-2">
<HeroiconsChevronUpDown20Solid class="w-5 h-5 text-gray-400" aria-hidden="true" />
</ComboboxButton>
</div>
<ComboboxOptions class="absolute w-full py-1 overflow-auto text-base bg-white rounded-md shadow-lg max-h-60 ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
<div
v-if="filteredPeople.length === 0 && query !== ''"
class="relative py-2 px-4 text-gray-700 cursor-default select-none"
>
Nothing found.
</div>
<ComboboxOption
v-for="person in filteredPeople"
v-slot="{ selected, active }"
:key="person.id"
:value="person"
as="template"
>
<li
class="relative py-2 pl-10 pr-4 cursor-default select-none"
:class="active ? 'text-white bg-rose-600' : 'text-gray-900'"
>
<span class="block truncate" :class="selected ? 'font-medium' : 'font-normal'">
{{ person.name }}
</span>
<span
v-if="selected"
class="absolute inset-y-0 left-0 flex items-center pl-3"
:class="active ? 'text-white' : 'text-rose-600'"
>
<HeroiconsCheck20Solid class="w-5 h-5" aria-hidden="true" />
</span>
</li>
</ComboboxOption>
</ComboboxOptions>
</Float>
</Combobox>
<div class="mt-4 flex justify-end">
<button type="button" class="px-4 py-1 bg-rose-500 text-white text-sm rounded" @click="close">
Submit
</button>
</div>
</div>
</PopoverPanel>
</Float>
</Popover>
</template>
<script setup>
import { computed, ref } from 'vue'
import { Combobox, ComboboxButton, ComboboxInput, ComboboxOption, ComboboxOptions, Popover, PopoverButton, PopoverPanel } from '@headlessui/vue'
import { Float, FloatArrow } from '@headlessui-float/vue'
import HeroiconsCheck20Solid from '~icons/heroicons/check-20-solid'
import HeroiconsChevronUpDown20Solid from '~icons/heroicons/chevron-up-down-20-solid'
const people = [
{ id: 1, name: 'Wade Cooper' },
{ id: 2, name: 'Arlene Mccoy' },
{ id: 3, name: 'Devon Webb' },
{ id: 4, name: 'Tom Cook' },
{ id: 5, name: 'Tanya Fox' },
{ id: 6, name: 'Hellen Schmidt' },
]
const selected = ref(people[0])
const query = ref('')
const filteredPeople = computed(() =>
query.value === ''
? people
: people.filter(person =>
person.name
.toLowerCase()
.replace(/\s+/g, '')
.includes(query.value.toLowerCase().replace(/\s+/g, ''))
)
)
</script>
If you have other questions, open a new issue and attach your sample code or minimally reproducible GitHub project. Online demo is provided here to test <Float>
at any time.
Use Version Use version when question appear:
Describe the question I'm trying to render a HeadlessUI Combobox inside a Popover. For this, I need to teleport the combobox options to the body, so that the dropdown options can overflow the popover, and the popover won't show scrollbars.
However, there's an issue - when clicking any of the combobox options, the popover is immediately closed. I believe it is because of the click outside handler, which now sees the options as being rendered outside of the popover. I saw a mention in HeadlessUI repo that using the
Portal
from@headlessui/vue
instead of the regularTeleport
component should help with this. Unfortunately, I don't see that it's possible to customize the portal component forFloat
. Would you consider supporting something like that? Or perhaps there's another solution to the issue?Screenshots If applicable, add screenshots to help explain your problem.