headlessui: [BUG] Introduced in 1.6.2: Component inside renders non-element root node that cannot be animated.

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?

For example: Chrome, Safari, Firefox

Reproduction URL

https://codesandbox.io/s/sweet-bartik-5v3jt8

Please note that CodeSandbox does not contain the latest 1.6.2 version so this link will not really reproduce it. However, this is the quickest way to describe this. When it does, bumping the version is sure to reveal the bug.

Describe your issue

When running the PopoverPanel immediately after a transition, you get an error:

Screenshot 2022-05-21 at 09 02 01
<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 class="absolute z-10 w-screen max-w-md mt-3 -ml-4 transform lg:max-w-2xl lg:ml-0 lg:left-1/2 lg:-translate-x-1/2">
    <div class="overflow-hidden rounded-lg shadow-lg ring-1 ring-black ring-opacity-5">
      <div class="relative grid gap-6 px-5 py-6 bg-white sm:gap-8 sm:p-8 lg:grid-cols-2 dark:bg-slate-800">
        <a
          :key="f.name"
          :href="f.href"
          v-for="f in features"
          @click.prevent="scrollTo('feature-section', close)"
          class="flex items-start p-3 -m-3 rounded-lg hover:bg-slate-50 dark:hover:bg-slate-700"
        >
          <div class="popover-panel-icon">
            <component :is="f.icon" class="w-6 h-6" aria-hidden="true" />
          </div>
          <div class="ml-4">
            <p class="text-base font-medium text-slate-900 dark:text-slate-200">{{ f.name }}</p>
            <p class="mt-1 text-sm text-slate-500 dark:text-slate-300">{{ f.description }}</p>
          </div>
        </a>
      </div>
    </div>
  </PopoverPanel>
</transition>

This does not happen in v1.6.1. For now you can either use 1.6.1 or wrap the PopoverPanel with a div. The later will remove the warning, but also the transition.

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 23
  • Comments: 15

Commits related to this issue

Most upvoted comments

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

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

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

I’ve updated your CodeSandbox with the insiders version: https://codesandbox.io/s/musing-forest-8i859i

As a workaround, I am wrapping my PopoverPanel in an extra div:

<transition>
  <!--  wrapping PopoverPanel in an extra `div` so the component inside `Transaction` is always an element (even when closed)
  would otherwise emit warning from vue: "Component inside <Transition> renders non-element root node that cannot be animated." 
  -->
  <div>
    <PopoverPanel> </PopoverPanel>
  </div>
</transition>

I assume, this error is due to the PopoverPanel being unmounted when Popover is closed and thus the transition is empty - which then throws the error.

I’m seeing this error with 1.6.5 after pasting Tailwind UI page examples.

Wrapping the PopoverPanel fixes the error as @benkroeger said, and I’ve used the slot prop to restore transform to the wrapping div for now.

<Popover as="header" class="relative" v-slot="{ open }">
  <div v-if="open">
  ...
  </div>
</Popover>

I’m facing the same issue

Thanks @benkroeger and @adamndev, that workaround indeed helped and made the error disappear. Although i had to make the div relative as the popover panel i have inside it would otherwise jump around.

Not sure if this is related, but I also noticed this recently (using v1.6.4), that possibly because of the addition of extra hidden buttons for the focus behaviour fix, something else broke related to transitions. After the transition is complete, the elements inside the transition don’t actually unmount even after show is false.

So in my case:

  1. Transition.show becomes true
  2. my panel show correctly
  3. user closes panel and show gets set to false
  4. the leave transition starts and the panel fades away, but the surrounding div containing 2 hidden buttons and an inner div with my panel, now with opacity 0, is still there, blocking any user interaction on the page.

DOM tree:

<div id="headlessui-portal-root">
    <div> // outer div
        <button hidden/>
        <div>
            <aside />  // My panel on which the transition occurs
        </div>
        <button hidden/>
    </div>
</div>

And this seems to apply on every instance I have with a Transition > Dialog > Transition.Child > *

Edit: After reverting to previous releases, the above occurs since v1.6.0