Closed nielseulink closed 1 year ago
Hi @nielseulink, I think you can change floating-as
to template
to fix it:
<Float floating-as="template">
Hi @nielseulink, I think you can change
floating-as
totemplate
to fix it:<Float floating-as="template">
Hi @ycs77, thank you for your response. When adding that the dropdown is visible but stretched out and out of sight. Any idea ?
Can you privide the code of the filter dropdown for me?
I think you can try to add the as="div"
and class="relative"
to <Float>
, to keep the <ComboboxOptions>
's with is same as root <Float>
.
<Combobox v-model="selected">
<Float
as="div"
class="relative"
floating-as="template"
...
>
<div class="relative w-full ...">
<ComboboxInput ... />
<ComboboxButton ... />
</div>
<ComboboxOptions class="absolute w-full ...">
...
</ComboboxOptions>
</Float>
</Combobox>
Edit 2023/02/27: change to vue example
This is an example of me trying to reproduce your dropdown:
<template>
<Popover>
<Float
placement="bottom-start"
:offset="8"
portal
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="inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 shadow-sm hover:bg-gray-50 focus:outline-none">
Filters
</PopoverButton>
<PopoverPanel v-slot="{ close }" class="bg-white p-4 border border-gray-200 rounded-md shadow-lg focus:outline-none">
<label class="text-sm text-gray-700 font-bold inline-block mb-2">Brand</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 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: any) => 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-indigo-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-indigo-600'"
>
<HeroiconsCheck20Solid class="w-5 h-5" aria-hidden="true" />
</span>
</li>
</ComboboxOption>
</ComboboxOptions>
</Float>
</Combobox>
<div class="flex justify-end mt-4">
<button
type="button"
class="px-2.5 py-2 bg-indigo-100 text-indigo-700 text-xs font-bold rounded"
@click="close"
>
Apply filters
</button>
</div>
</PopoverPanel>
</Float>
</Popover>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
import { Combobox, ComboboxButton, ComboboxInput, ComboboxOption, ComboboxOptions, Popover, PopoverButton, PopoverPanel } from '@headlessui/vue'
import { Float } 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>
Edit 2023/02/27: change to vue example
Yeah that seems to work, thank you for your time and help. Final code:
<template>
<Combobox as="div" v-model="selectedOption" @update="console.log('test')" @update:modelValue="value => $emit('update:modelValue', value)">
<ComboboxLabel v-if="label" :for="label" v-text="label" class="block text-sm font-medium text-gray-700 dark:text-gray-300" />
<div class="relative mt-1">
<Float
as="div"
floating-as="template"
className="relative"
placement="bottom-end"
enter="transition duration-200 ease-out"
enter-from="scale-95 opacity-0"
enter-to="scale-100 opacity-100"
leave="transition duration-150 ease-in"
leave-from="scale-100 opacity-100"
leave-to="scale-95 opacity-0">
<div>
<ComboboxInput class="w-full rounded-md border border-gray-300 bg-white py-2 pl-3 pr-10 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 sm:text-sm" @change="query = $event.target.value" @focus="$event.target.value = ''" @focusout="query = ''" :display-value="(selected) => (selected.id) ? selected.name : (props.options.filter(option => option.id == selected)[0].name)" />
<ComboboxButton class="absolute inset-y-0 right-0 flex items-center rounded-r-md px-2 focus:outline-none">
<ChevronDownIcon class="h-5 w-5 text-gray-400" aria-hidden="true" />
</ComboboxButton>
</div>
<ComboboxOptions v-if="filteredOptions.length > 0"
class="absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
<ComboboxOption v-for="option in filteredOptions" :key="option.id" :value="option.id" as="template" v-slot="{ active, selected }">
<li :class="['relative cursor-default select-none py-2 pl-3 pr-9', active ? 'bg-indigo-600 text-white' : 'text-gray-900']">
<span :class="['block truncate', selected && 'font-semibold']">
{{ option.name }}
</span>
<span v-if="selected"
:class="['absolute inset-y-0 right-0 flex items-center pr-4', active ? 'text-white' : 'text-indigo-600']">
<CheckIcon class="h-5 w-5" aria-hidden="true" />
</span>
</li>
</ComboboxOption>
</ComboboxOptions>
</Float>
</div>
<p v-if="error" v-text="error" class="mt-2 text-sm text-red-600 dark:text-red-400" />
</Combobox>
</template>
<script setup>
import { computed, ref, watch } from 'vue'
import { CheckIcon, ChevronDownIcon } from 'vue-tabler-icons'
import { Combobox, ComboboxButton, ComboboxInput, ComboboxLabel, ComboboxOption, ComboboxOptions } from '@headlessui/vue'
import { Float } from '@headlessui-float/vue'
let props = defineProps({
label: {
type: [String, Boolean],
default: false,
},
error: {
type: [String, Boolean],
default: false,
},
modelValue: {
type: Number,
default: null,
},
options: {
type: Object,
default: null,
}
});
const query = ref('')
const selectedOption = ref(props.options.filter(option => option.id == props.modelValue)[0])
const filteredOptions = computed(() =>
query.value === ''
? props.options
: props.options.filter((option) => {
return option.name.toLowerCase().includes(query.value.toLowerCase())
})
)
</script>
Sorry for the React example, I've changed it for Vue. For reference if necessary 😊.
Hi, sorry to reopen this. I've been playing with as="div" and other options you mention on the issue but I can't seem to make the combobox options as wide as the combobox input.
This is my implementation
<Combobox as="div" :disabled="disabled" v-model="selected" @update:modelValue="item => emit('selectedKeyChanged', item)"
v-if="props.items">
<Float floating-as="template" as="div" placement="bottom-start" :offset="2" leave="transition ease-in duration-100"
leave-from="opacity-100" leave-to="opacity-0" @hide="query = ''">
<div class="relative">
<ComboboxInput :disabled="disabled"
class="w-full rounded-md border border-gray-300 bg-white py-2 pl-3 pr-10 shadow-sm focus:border-[#fe428c] focus:outline-none focus:ring-1 focus:ring-[#fe428c]"
@change="query = $event.target.value" :displayValue="(key) => {
const matchingItem = props.items.find(item => item.key === key);
return matchingItem ? matchingItem.value : '';
}" />
<ComboboxButton class="absolute inset-y-0 right-0 flex items-center rounded-r-md px-2 focus:outline-none">
<ChevronUpDownIcon class="h-5 w-5 text-gray-400" aria-hidden="true" />
</ComboboxButton>
</div>
<ComboboxOptions :class="filteredItems.length === 0 ? 'hidden' : ''"
class="relative max-h-44 overflow-auto w-full rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
<div v-if="filteredItems.length === 0 && query !== ''"
class="relative cursor-default select-none py-2 px-4 text-gray-700">
Sin resultados
</div>
<ComboboxOption v-for="item in filteredItems" :key="item.key" :value="item.key" as="template"
v-slot="{ active, selected }">
<li
:class="['relative cursor-default select-none py-2 pl-8 pr-4', active ? 'bg-[#fe428c] text-white' : 'text-gray-900']">
<span :class="['block truncate', selected && 'font-semibold']">
{{ item.value }}
</span>
<span v-if="selected"
:class="['absolute inset-y-0 left-0 flex items-center pl-1.5', active ? 'text-white' : 'text-[#fe428c]']">
<CheckIcon class="h-5 w-5" aria-hidden="true" />
</span>
</li>
</ComboboxOption>
</ComboboxOptions>
</Float>
</Combobox>
If I add theclass "relative"
it's the correct with but it doesn't break the parent container overflow. So it's cut off:
So I can't make it both the correct with and keep the break overflow cappabilities
Hi @cxammar, I can't reproduce this bug, please open a new issue and provide a minimally reproducible repo using GitHub or stackblitz, Online demo provided the Headless UI Float stackblitz examples.
Owner
Hi, I filed a new Issue with a stacblitz as you request. https://github.com/ycs77/headlessui-float/issues/75
Use Version Use version when question appear:
Describe the question I tried to add this package to my project, it all seems to work fine besides the combobox. It only shows the shadows:
I got it fixed by modifieing the HTML in the browser (by adding display: contents; to one of the div's):
Any idea what i'm doing wrong and how to fix it ?
Kind regards, Niels