Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix enter transitions for the Transition component #3074

Merged
merged 27 commits into from
Apr 5, 2024

Conversation

RobinMalfait
Copy link
Member

@RobinMalfait RobinMalfait commented Apr 2, 2024

This PR fixes the enter transitions when using the Transition component. We also simplify some internals such that it is easier to reason about.

A few fixes went into this PR:

  • Maintain target classes — we make sure that the enterTo or leaveTo classes are still present once the transition is complete. Otherwise it could happen that you transition from bg-red-500 to bg-blue-500 and once it's done, you end up with bg-red-500 again.
  • Flush classes to force an enter transition — we now ensure that when a transition starts, that we force cancel existing transitions (if they exist at all), then apply the necessary changes (adding enter enterFrom or leave leaveFrom) and last but not least, trigger a reflow to flush all the changes to the DOM at once which starts the transition.
  • Properly handle cancelling mid-flight transitions — when a transitions is mid-flight and you cancel the transition (e.g.: press escape while a <Menu /> component is opening) the leave leaveTo classes will be applied (as-if you are closing the <Menu />).

Fixes: #2914
Fixes: #2991

Copy link

vercel bot commented Apr 2, 2024

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 Apr 5, 2024 2:02pm
headlessui-vue ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 5, 2024 2:02pm

I spend a lot of time trying to debug this, and I'm not 100% sure that
I'm correct yet. However, what we used to do is apply the "before" set
of classes, wait a frame and then apply the "after" set of classes which
should trigger a transition.

However, for some reason, applying the "before" classes already start a
transition. My current thinking is that our component is doing a lot of
work and therfore prematurely applying the classes and actually
triggering the transition.

For example, if we want to go from `opacity-0` to `opacity-100`, it
looks like setting `opacity-0` is already transitioning (from 100%
because that's the default value). Then, we set `opacity-100`, but our
component was just going from 100 -> 0 and we were only at let's say 98%.
It looks like we cancelled the transition and only went from 98% ->
100%.

I can't fully explain it purely because I don't 100% get what's going
on.

However, this commit fixes it in a way where we first prepare the
transition by explicitly cancelling all in-flight transitions. Once that
is done, we can apply the "before" set of classes, then we can apply the
"after" set of classes.

This seems to work consistently (even though we have failing tests,
might be a JSDOM issue).

This tells me that at least parts of my initial thoughts are correct
where some transition is already happening (for some reason). I'm not
sure what the reason is exactly. Are we doing too much work and blocking
the main thread? That would be my guess...
Instead of always ensuring that there is an event, let's use the `?.`
operator and conditionally call the callbacks instead.
@RobinMalfait RobinMalfait force-pushed the fix/enter-transitions branch from b5c5652 to b905bf8 Compare April 3, 2024 22:34
@RobinMalfait RobinMalfait merged commit c8037fc into main Apr 5, 2024
8 checks passed
@RobinMalfait RobinMalfait deleted the fix/enter-transitions branch April 5, 2024 14:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants