headlessui icon indicating copy to clipboard operation
headlessui copied to clipboard

Tabs content not rendered in SSR context (Vue)

Open cyruscollier opened this issue 3 years ago • 1 comments

What package within Headless UI are you using?

@headlessui/vue

What version of that package are you using?

v1.6.2

What browser are you using?

Chrome

Reproduction URL

https://github.com/cyruscollier/nuxt3-demos/tree/headlessui

Describe your issue

Similar to what was recently addressed in the React package https://github.com/tailwindlabs/headlessui/issues/1086, the Tabs component in the Vue package does not render the default tab content in an SSR context (Nuxt v3 in this case). To replicate, clone the example repo above, run yarn, yarn dev, then open http://localhost:3000. View the page source and you can see that none of the tab panels are rendered in the page source.

Properly rendering the default tab (or ideally, all the tabs but hiding the rest) from the server will result in better SEO and web vital metrics (CLS and LCP, mainly)

cyruscollier avatar May 20 '22 00:05 cyruscollier

For anyone that comes across this ticket, I was able to find a workaround by adding the static prop to the default TabPanel, which isn't documented. Example:

<TabPanel v-slot="{ selected }" static as="template">
  <div v-show="selected"><!-- Content for default tab --></div>
</TabPanel>
<TabPanel v-slot="{ selected }" as="template">
   <div v-if="selected"><!-- Content for another tab not visible on page load --></div>
</TabPanel>

For the others beside the default, you could also add the static prop and use v-show instead of v-if if you think it would be a benefit to have SSR pre-render that content as well in your particular use case.

I still think it would be good to have default SSR support for this so there's feature parity with the React package. Looking at the Vue component code, it looks like the element ref-based indexing currently in place, which requires onMount() to resolve those refs, would need to get replaced with indexing by tab id instead, which it appears is what the React package is doing.

I'd be happy to work on a PR for the doc fix and also my proposed SSR fix if the maintainers think that's the right approach.

cyruscollier avatar May 20 '22 22:05 cyruscollier

Hey! Thank you for your bug report! Much appreciated! 🙏

This should be fixed by #2068, and will be available in the next release.

You can already try it using npm install @headlessui/vue@insiders.

RobinMalfait avatar Dec 06 '22 12:12 RobinMalfait