Commit Graph

2 Commits

Author SHA1 Message Date
Robin Malfait 971ff6b67e Fix transition bug on Firefox, triggered by clicking the PopoverButton in rapid succession (#3452)
We recently landed a fix for `Popover`s not closing correctly when using
the `transition` prop (#3448). Once this fix was published, some users
still ran into issues using Firefox on Windows (see:
https://github.com/tailwindlabs/tailwindui-issues/issues/1625).

One fun thing I discovered is that transitions somehow behave
differently based on where they are triggered from (?). What I mean by
this is that holding down the <kbd>space</kbd> key on the button does
properly open/close the `Popover`. But if you rapidly click the button,
the `Popover` will eventually get stuck.

> Note: when testing this, I made sure that the handling of the `space`
key (in a `keydown` handler) and the clicking of the mouse (handled in a
`click` handler) called the exact same code. It still happened.

The debugging continues…

One thing I noticed is that when the `Popover` gets stuck, it meant that
a transition didn't properly complete.

The current implementation of the internal `useTransition(…)` hook has
to wait for all the transitions to finish. This is done using a
`waitForTransition(…)` helper. This helper sets up some event listeners
(`transitionstart`, `transitionend`, …) and waits for them to fire.

This seems to be unreliable on Firefox for some unknown reason.

I knew the code for waiting for transitions wasn't ideal, so I wanted to
see if using the native `node.getAnimations()` simplifies this and makes
it work in general.

Lo and behold, it did! 🎉

This now has multiple benefits:

1. It works as expected on Firefox
2. The code is much much simpler
3. Uses native features

The `getAnimations(…)` function is supported in all modern browsers
(since 2020). At the time it was too early to rely on it, but right now
it should be safe to use.

Fixes: https://github.com/tailwindlabs/tailwindui-issues/issues/1625
2024-09-04 16:09:33 +02:00
Robin Malfait 0162c57d88 add React 18 compatibility (#1326)
* bump dev dependencies to React 18

* setup Jest to include `IS_REACT_ACT_ENVIRONMENT`

* prefer `useId` from React 18 if it exists

In React 16 & 17, where `useId` doesn't exist, we will fallback to our
implementation we have been using up until now.

The `useId` exposed by React 18, ensures stable references even in SSR
environments.

* update expected events

React 18 now uses the proper events:
- `blur` -> `focusout`
- `focus` -> `focusin`

* ensure to wait a bit longer

This is a bit unfortunate, but since React 18 now does an extra
unmount/remount in `StrictMode` to ensure that your code is
ConcurrentMode ready, it takes a bit longer to settle what the DOM sees.

That said, this is a temporary "hack". We are going to experiment with
using tools like Puppeteer/Playwright to run our tests in an actual
browser instead to eliminate all the weird details that we have to keep
in mind.

* prefer `.focus()` over `fireEvent.focus(el)`

* abstract `microTask` polyfill code

* prefer our `focus(el)` function over `el.focus()`

Internally we would still use `el.focus()`, but this allows us to have
more control over that `focus` function.

* add React 18 to the React Playground

* improve hooks for React 18

- Improving the cleanup of useEffect hooks
- useIsoMorphicEffect instead of normal useEffect, so that we can use
  useLayoutEffect to be a bit quicker.

* improve disposables

- This allows us to add event listeners on a node, and get automatic
  cleanup once `dispose` gets called.
- We also return all the `d.add` calls, so that we can cleanup specific
  parts only instead of everything or nothing.

* reimplement the Transition component to be React 18 ready

* wait an additional frame for everything to settle

* update playground examples

* suppressConsoleLogs for RadioGroup components

* update changelog

* keep the `to` classes for a smoother transition

In the next transition we will remove _all_ classes provided and re-add
the once we need.

---

Some extra special thanks:

- Thanks @silvenon for your initial work on the `transition` events in #926
- Thanks @thecrypticace for doing late-night debugging sessions

Co-authored-by: =?UTF-8?q?Matija=20Marohni=C4=87?= <matija.marohnic@gmail.com>
Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2022-04-13 22:07:01 +02:00