tailwindlabs / headlessui

Completely unstyled, fully accessible UI components, designed to integrate beautifully with Tailwind CSS.
https://headlessui.com
MIT License
25.81k stars 1.07k forks source link

Fix components not properly closing when using the `transition` prop #3448

Closed RobinMalfait closed 4 weeks ago

RobinMalfait commented 4 weeks ago

This PR fixes a bug where the components don't always properly close when using the transition prop on those components.

The issue here is that the internal useTransition(…) hook relies on a DOM node. Whenever the DOM node changes, we need to re-run the useTransition(…). This is why we store the DOM element in state instead of relying on a useRef(…).

Let's say you have a Popover component, then the structure looks like this:

<Popover>
  <PopoverButton>Show</PopoverButton>
  <PopoverPanel>Contents</PopoverPanel>
</Popover>

We store a DOM reference to the button and the panel in state, and the state lives in the Popover component. The reason we do that is so that the button can reference the panel and the panel can reference the button. This is needed for some aria-* attributes for example:

<PopoverButton aria-controls={panelElement.id}>

For the transitions, we set some state to make sure that the panel is visible or hidden, then we wait for transitions to finish by listening to transition related events on the DOM node directly.

If you now say, "hey panel, please re-render because you have to become visible/hidden" then the component re-renders, the panel DOM node (stored in the Popover component) eventually updates and then the useTransition(…) hooks receives the new value (either the DOM node or null when the leave transition is complete).

The problem here is the round trip that it first has to go to the root <Popover/> component, re-render everything and provide the new DOM node to the useTransition(…) hook.

The solution? Local state so that the panel can re-render on its own and doesn't require the round trip via the parent.

Fixes: https://github.com/tailwindlabs/headlessui/issues/3438 Fixes: https://github.com/tailwindlabs/headlessui/issues/3437 Fixes: https://github.com/tailwindlabs/tailwindui-issues/issues/1625

vercel[bot] commented 4 weeks ago

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
headlessui-react ✅ Ready (Inspect) Visit Preview 💬 Add feedback Sep 3, 2024 3:15pm
headlessui-vue ✅ Ready (Inspect) Visit Preview 💬 Add feedback Sep 3, 2024 3:15pm