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

Transition enterFrom classes not working as expected #1503

Closed
bentefay opened this issue May 26, 2022 · 12 comments · Fixed by #1519
Closed

Transition enterFrom classes not working as expected #1503

bentefay opened this issue May 26, 2022 · 12 comments · Fixed by #1519

Comments

@bentefay
Copy link

bentefay commented May 26, 2022

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://github.com/tailwindlabs/headlessui/blob/main/packages/playground-react/pages/transitions/component-examples/peek-a-boo.tsx

https://github.com/tailwindlabs/headlessui/blob/main/packages/playground-react/pages/transitions/component-examples/modal.tsx

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:

SimpleColor

<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:

Modal

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 Transition component applies the enter and enterFrom classes for 1 frame. The classes duration-75 and opacity-0 were just applied, but the existing opacity is 100, so the browser starts animating from opacity: 100 to opacity: 0.
  • In the next frame the browser continues the opacity transition from 100 to 0 (setting opacity to something like 0.97). The Transition component then removes the enterFrom classes and applies the enterTo classes. This starts animating from the current opacity of opacity: 0.97 back to opacity: 1
  • In the next frame the opacity reaches 1 and transitionend fires.

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?

@htmnk
Copy link

htmnk commented May 27, 2022

Same issue here, enter works as intended on 1.6.1.

Broken on 1.6.2+

@RobinMalfait
Copy link
Member

Hey! Thank you for your bug report!
Much appreciated! 🙏

This should be fixed by #1519, and will be available in the next release.

You can already try it using npm install @headlessui/react@insiders.

Can you verify that this works using the insiders build? Thanks!

@htmnk
Copy link

htmnk commented May 30, 2022

works for me on 1.6.4

@bentefay
Copy link
Author

Yup, me too. Thanks!

@tdesero
Copy link

tdesero commented Apr 4, 2023

I think there is a similar issue now on v1.7.13 as I did not get the "enter" transition to work. Going back to v1.7.11 fixed it for me.

@sgrund14
Copy link

sgrund14 commented Jun 1, 2023

seeing a similar issue with the enter transition not working. have a simple toast like this

<Transition
                show={showToast}
                appear
                as={Fragment}
                enter="transition ease-out duration-200"
                enterFrom="opacity-0"
                enterTo="opacity-100"
                leave="transition ease-in duration-200"
                leaveFrom="opacity-100"
                leaveTo="opacity-0"
            >
                <Dialog onClose={() => setShowToast(false)}>
                    <Dialog.Panel className="bottom-xs shadow-default p-xxs right-xs fixed z-[1000] flex w-[240px]">
                        Panel Content
                    </Dialog.Panel>
                </Dialog>
            </Transition>

the leaveFrom transition is working, but the enterTo is not. some added context: this is the sibling of another Transition in my React component/ I have a another Transitioning Dialog that opens the toast when it is closed. The problem is that when I trigger the toast, it doesn't animate in. But it does animate out...

Another strange thing is that on the dialog that is a sibling, the enterTo transition is working fine. Any thoughts ?

Broken on v1.7.11 and 1.17.15 (latest)

@WesleyKapow
Copy link

WesleyKapow commented Jul 4, 2023

Just hit this on latest 1.17.14 for vue. Solution was to use the separate transitions for backdrop and dialog as mentioned in the docs: https://headlessui.com/vue/dialog#transitions

@Ollynov
Copy link

Ollynov commented Apr 1, 2024

Still having this issue on @headlessui/react": "^1.7.18",

As an example:

<Transition
as={Fragment}
enter="transition ease-in duration-1000"
enterFrom="opacity-50 translate-y-1"
enterTo="opacity-10 translate-y-0"
leave="transition ease-in duration-500"
leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 translate-y-1"
>

It seems like the "enterFrom" classes are just not being applied. Right now enterFrom has opacity-50 but whether I remove that or add some other class it wouldn't change. So it always begins with the default opacity-100. So you can animate from 100 to 0 or any similar combo, but can't animate from opacity-0 to opacity-100 for example.

So this makes it so any child under this Transition component appears immediately, but the fade-away effect after you close it works as expected.

@thinkafterbefore
Copy link

Same here. Broken on @headlessui/react": "^1.7.18"

<Transition
  show={pasteMode}
  appear={true}
  enter="transition-all duration-[10s] ease-in-out"
  enterFrom="opacity-0"
  enterTo="opacity-100"
  leave="transition-all duration-[10s] ease-in-out"
  leaveFrom="opacity-100"
  leaveTo="opacity-0"
>

RobinMalfait added a commit that referenced this issue Jul 8, 2024
This was originally introduced in
#1519 to fix an issue
where some enter transitions where broken: #1503

However, since we refactored the `Transition` component to make use of
the `useTransition` hook, I can't seem to reproduce this issue anymore.

In fact, removing this code fixes an issue.

The bigger issue here is that when the component becomes hidden, that we
always set the state to hidden as well. But if it becomes visible again,
we don't show it again.

Right now, since I couldn't reproduce any of the other issue, I opted to
just removing the code entirely. But if we ever need it again, we
probably have to make sure that it becomes visible in the other scenario
as well.

Fixes: #3328
RobinMalfait added a commit that referenced this issue Jul 10, 2024
…dden (#3372)

* do not change visibility of `Transition` component

This was originally introduced in
#1519 to fix an issue
where some enter transitions where broken: #1503

However, since we refactored the `Transition` component to make use of
the `useTransition` hook, I can't seem to reproduce this issue anymore.

In fact, removing this code fixes an issue.

The bigger issue here is that when the component becomes hidden, that we
always set the state to hidden as well. But if it becomes visible again,
we don't show it again.

Right now, since I couldn't reproduce any of the other issue, I opted to
just removing the code entirely. But if we ever need it again, we
probably have to make sure that it becomes visible in the other scenario
as well.

Fixes: #3328

* update changelog
@rafalolszewski94
Copy link

This is still happening in version 1.7.22 for Vue, any plants to fix?

@Tchilly
Copy link

Tchilly commented Sep 6, 2024

+1 Yeah 1.7.16 works, but broken in 1.7.22

@JonasPardon
Copy link

JonasPardon commented Nov 6, 2024

+1 Yeah 1.7.16 works, but broken in 1.7.22

Can confirm, drawer from the Tailwind UI docs (https://tailwindui.com/components/application-ui/overlays/drawers#component-2036cb51318151226ce814d3e3efea91) has this issue on @headlessui/[email protected], downgrading to @headlessui/[email protected] fixes the issue.

Seems related to #3456

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.