You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I've recently upgraded headlessui from v1 to v2 and noticed that certain transitions are stuttering in firefox. Its a bit "random" and certainly doesn't happen all the time, but its noticeable. I've added a video which shows what I mean. Please pay attention to the "leave" animation of the dialog, I'm opening the dialogin the minimal example 3 times. The first 2 times you can briefly observe the "stuttering" and the 3rd time the animation is smooth. The dialog is opened by the "trigger" button and closed with the esc key. (Please ignore all the audio in the video)
2024-10-09.21-29-36.mp4
After some digging I believe firefox is briefly rendering the styles from the "leaveTo" classNames only to then switch back to the "leaveFrom" classNames.. The classNames are applied to the DOM in the correct order though.
After some tests I've found that the following changes are fixing the behavior:
functiontransition(node: HTMLElement,{
prepare,
run,
done,
inFlight,}: {prepare: ()=>voidrun: ()=>voiddone: ()=>voidinFlight: MutableRefObject<boolean>}){letd=disposables()letoriginalTransition=node.style.transition;// same behavior as beforeif(inFlight?.current){prepare()}else{// prepare at the end of the current framed.requestAnimationFrame(()=>{node.style.transition="none";prepare();});}d.nextFrame(()=>{// reset the transition in the next framenode.offsetHeight;// maybe not needed?node.style.transition=originalTransition;// Initiate the transition by applying the new classes.run()// Wait for the transition, once the transition is complete we can cleanup.// We wait for a frame such that the browser has time to flush the changes// to the DOM.d.requestAnimationFrame(()=>{d.add(waitForTransition(node,done))})})returnd.dispose}
The main difference here is the node.style.transition value is modified accross mutlitple frames:
Before:
node.style.transition = "none"
prepare();
node.offsetHeight to trigger reflow
node.style.transition = original
After:
wait for the end of the current frame
node.style.transition = "none"
prepare();
wait for next frame
node.offsetHeight to trigger reflow (maybe not needed anymore)
node.style.transition = original
I've done some tests and found everything working properly, although I'm certainly not an expert in the codebase and don't know all the implications the changes could have.
The text was updated successfully, but these errors were encountered:
I'm also observing the "enter" transitions to be affected, so that they are instantly in the "enterTo" state without any transition happening. - Its also "random" in a way where it seems to depend on Firefox's mood or some internal state.. sometimes the transition works and sometimes not.
What package within Headless UI are you using?
@headlessui/react
What version of that package are you using?
v2.1.9
What browser are you using?
Firefox
Reproduction URL
https://stackblitz.com/edit/stackblitz-starters-wk4zwz?file=src%2Fstyle.css,src%2FApp.tsx,src%2Findex.tsx
Describe your issue
I've recently upgraded headlessui from
v1
tov2
and noticed that certain transitions are stuttering in firefox. Its a bit "random" and certainly doesn't happen all the time, but its noticeable. I've added a video which shows what I mean. Please pay attention to the "leave" animation of the dialog, I'm opening the dialogin the minimal example 3 times. The first 2 times you can briefly observe the "stuttering" and the 3rd time the animation is smooth. The dialog is opened by the "trigger" button and closed with theesc
key. (Please ignore all the audio in the video)2024-10-09.21-29-36.mp4
After some digging I believe firefox is briefly rendering the styles from the "leaveTo" classNames only to then switch back to the "leaveFrom" classNames.. The classNames are applied to the DOM in the correct order though.
To me it seems like the described behavior from the
use-Transition
hook workaround is still happening. (I could be wrong with that though)After some tests I've found that the following changes are fixing the behavior:
The main difference here is the
node.style.transition
value is modified accross mutlitple frames:Before:
node.style.transition = "none"
prepare();
node.offsetHeight
to trigger reflownode.style.transition = original
After:
node.style.transition = "none"
prepare();
node.offsetHeight
to trigger reflow (maybe not needed anymore)node.style.transition = original
I've done some tests and found everything working properly, although I'm certainly not an expert in the codebase and don't know all the implications the changes could have.
The text was updated successfully, but these errors were encountered: