-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
What package within Headless UI are you using?
@headlessui/react
What version of that package are you using?
1.6.3
What browser are you using?
Chrome/Firefox
Reproduction URL
https://headlessui.dev/react/transition
Describe your issue
Many of the examples for Transition in playground-react, the headlessui documentation and Tailwind UI apply transition in the className or enter attributes to achieve an enter effect. Some of these do not seem to be working as intended.
For example, take the React playground peek-a-boo example below:
<Transition
show={isOpen}
enter="transition-colors ease-in duration-[5s]"
enterFrom="transform bg-red-500"
enterTo="transform bg-blue-500"
leave="transition-colors ease-in duration-[5s]"
leaveFrom="transform bg-blue-500"
leaveTo="transform bg-red-500"
entered="bg-blue-500"
className="h-64 rounded-md p-4 shadow"
>
Contents to show and hide
</Transition>Notice how the div starts off with a transparent background rather than a red background despite having enterFrom set to bg-red-500.
The same issue exists with the modal - it is supposed to be fading in but instead just pops in:
Setting unmount={false} fixes the problem.
Digger deeper, I think I can see why this is happening. Taking the example from the Transition documentation:
function MyComponent() {
const [isShowing, setIsShowing] = useState(false)
return (
<>
<button onClick={() => setIsShowing((isShowing) => !isShowing)}>
Toggle
</button>
<Transition
show={isShowing}
enter="transition-opacity duration-75"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition-opacity duration-150"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
I will fade in and out
</Transition>
</>
)
}At least in Chrome, this appears to have the following behaviour:
- The
Transitioncomponent applies theenterandenterFromclasses for 1 frame. The classesduration-75andopacity-0were just applied, but the existingopacityis100, so the browser starts animating fromopacity: 100toopacity: 0. - In the next frame the browser continues the opacity transition from
100to0(settingopacityto something like 0.97). TheTransitioncomponent then removes theenterFromclasses and applies theenterToclasses. This starts animating from the current opacity ofopacity: 0.97back toopacity: 1 - In the next frame the
opacityreaches 1 andtransitionendfires.
Applying a className of opacity-0 fixes this issue, because the opacity is already 0 when the enterFrom classes are applied. Alternatively, applying transition-opacity and duration-75 to enterTo rather than enter fixes the problem because the browser does not try to animate the enterFrom.
This behaviour is a little confusing, particularly given many of the examples suffer from this problem. Is there a way to improve this? For example, could transition-property be set to none when applying enterFrom?

