[Nuxt3] Combobox.Positioner incorrect position of content
bogdan0083 opened this issue · comments
Description
Hey guys! Thank you for creating such a beautiful library ❤️
I created nuxt3 project and installed @ark-ui/vue
library. Tried to use Combobox. It works, but position of content is calculated incorrectly. I expect it to be UNDER input field. Instead, it shows at the top left corner:
Link to Reproduction (or Detailed Explanation)
https://stackblitz.com/edit/nuxt-starter-fzamjd?file=components%2FComboboxArk.vue
Steps to Reproduce
- Create empty
Nuxt 3
project (in my case it's3.10.1
version) - Install
@ark-ui/vue
- Create
Combobox
component (I use UnoCSS for styling, but no styles added forCombobox.Positioner
orCombobox.Content
:
<script setup>
import { ref } from 'vue';
import { Combobox } from '@ark-ui/vue';
const advancedItems = ref([
{ label: 'React', value: 'react' },
{ label: 'Solid', value: 'solid' },
{ label: 'Vue', value: 'vue' },
{ label: 'Svelte', value: 'svelte', disabled: true },
]);
const inputValue = ref('');
const onInputValueChange = (details) => {
console.log(details);
inputValue.value = details.value;
};
const onValueChange = (details) => {
console.log(details);
inputValue.value = '';
};
</script>
<template>
<Combobox.Root
:items="advancedItems"
multiple
v-slot="api"
:onInputValueChange="onInputValueChange"
:onValueChange="onValueChange"
>
<Combobox.Label>Framework</Combobox.Label>
<Combobox.Control
class="flex items-center flex-wrap relative pr-12 gap-x-3"
>
<div
v-for="selectedItem in api.value"
:key="selectedItem"
class="inline-flex grow-0 shrink-0"
>
{{ selectedItem }}
</div>
<div class="min-w-10 w-[fit-content] inline-flex grow shrink">
<Combobox.Input
:value="inputValue"
class="text-gray-500 bg-transparent b-none w-full block"
/>
</div>
<Combobox.Trigger class="absolute w-12 top-0 right-0"
>Open</Combobox.Trigger
>
</Combobox.Control>
<Teleport to="body">
<Combobox.Positioner>
<Combobox.Content>
<Combobox.ItemGroup id="framework">
<Combobox.ItemGroupLabel htmlFor="framework"
>Frameworks</Combobox.ItemGroupLabel
>
<Combobox.Item
v-for="item in advancedItems"
:key="item.value"
:item="item"
>
<Combobox.ItemText>{{ item.label }}</Combobox.ItemText>
<Combobox.ItemIndicator>✓</Combobox.ItemIndicator>
</Combobox.Item>
</Combobox.ItemGroup>
</Combobox.Content>
</Combobox.Positioner>
</Teleport>
</Combobox.Root>
</template>
- Use your newly created component inside
app.vue
:
<template>
<div class="flex flex-col w-300px">
<h2>Combobox Ark example</h2>
<Combobox />
</div>
</template>
<script setup>
useHead({
bodyAttrs: {
class: 'text-gray-100 bg-gray-960 l:(text-gray-900 bg-white-100)',
},
});
</script>
- run
npm run dev
and see the result. Content has wrong position on open (it's in the top left corner. I expect it to be under input)
Ark UI Version
@ark-ui/vue: 0.11.0
Framework
- React
- Solid
- Vue
Browser
Firefox
Additional Information
No response
Here's the same example with Vue 3 and Vite, without SSR. You can see that the position of content is correct.
Thank you for opening this issue. I think it's similar to the problem with Portal
in React with SSR
@bogdan0083 I've also stumble upon this issue some weeks ago, it seems even though Nuxt has SSR support for Teleport sometimes it adds the div
above <div id="__nuxt">
during hydration. I had to wrap the teleport inside of <ClientOnly>
as they describe in the docs.
There is, though, an implement coming up that maybe will fix this 🤔
nuxt/nuxt#25041
nuxt/nuxt#25043
@bogdan0083 I've also stumble upon this issue some weeks ago, it seems even though Nuxt has SSR support for Teleport sometimes it adds the
div
above<div id="__nuxt">
during hydration. I had to wrap the teleport inside of as they describe in the docs.There is, though, an implement coming up that maybe will fix this 🤔 nuxt/nuxt#25041 nuxt/nuxt#25043
Hmm, I've just tried your solution with <ClientOnly>
wrapper of Teleport and it still doesn't work 🤔 . Tried it on my bug reproduction example (It doesn't have ClientOnly
wrapper now).
But I guess nuxt
is definitely to blame here, that's for sure.
But I guess nuxt is definitely to blame here, that's for sure.
Mostly Vue SSR behavior - we'd love to mimic the client-side Vue behavior but it'd lead to hydration errors. Nevertheless, with the linked PR it should work fine and follow the best practices 👍
@manniL @bogdan0083 @jeferson-sb
This should be fixed in 1.0.0-2
I've added an example in Nuxt here https://stackblitz.com/github/chakra-ui/ark/tree/main/templates/vue/nuxt?file=components%2Fcombobox.vue