-
Notifications
You must be signed in to change notification settings - Fork 787
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
[BUG] Shared layout animations not working when rendered in React portal #1524
Comments
Hey @mattgperry 👋 Any chance you (or someone else collaborating on this project) are going to be able to take a look at this soon-ish ? Thank you! |
Hey @mattgperry , I would appreciate it if you (or any other contributors of this project) could reply with some feedback about this bug report — is it an actual bug? Do you know of a workaround? Are you planning on working on a fix, or can you at least give any pointers to what a fix could look like? I'm also happy to help to open a PR, with the right help and collaboration. Thank you |
We are experiencing the same bug when trying to use animations inside a modal rendered via portal. |
I have experienced another issue of shared element animation, when the parent motion node has set a translation via the Without a parent motion node – animation works fineThis setup has no parent motion node. The animation works great and the menu button morphs into the menu. // Pseudo code to show the basic setup
<div>
<MenuButton layoutId="menu"/>
<Portal>
<Menu layoutId="menu"/>
</Portal>
</div> With a parent motion node – animation brokenNow the setup with a motion node as a parent where When the menu is opened, the shared element animation completes immediately. This is the side-effect described by @ciampo. It happens always, with or without The second side-effect occurs when the menu re-renders, e.g. because of the menu item highlighting or content changes. It causes the position animation to start again. This side-effect only occurs, when Comparing to the working setup, the first level // Pseudo code to show the basic setup
<motion.div style={{x: 100}}>
<MenuButton layoutId="menu"/>
<Portal>
<Menu layoutId="menu"/>
</Portal>
</motion.div> I can reproduce the bug on Mac OS with Chrome Firefox and Safari (all latest versions) with framer-motion at |
An easy fix, at least in my case, is to reset the // Pseudo code to show the basic setup
<motion.div style={{x: 100}}>
<MotionContext.Provider value={{}}>
<MenuButton layoutId="menu"/>
<Portal>
<Menu layoutId="menu"/>
</Portal>
</MotionContext.Provider>
</motion.div> The This solution may has other implications. I haven't noticed any side-effects so far. |
Hey @birmitt , I tried to apply your tentative fix to a clone of the CodeSandbox link that I posted above, and the animations worked again! I'll try to test this change a bit more in depth in the next days, by applying it to this PR I was previously working on. |
I have the same problem. I have to avoid usage of layout animations in portals. |
the problem is when you need to make a modal kkkk |
As @birmitt mentioned, the problem seems to be indeed related to the motion context: that is because, when using react portals, the React tree and the DOM tree don't overlap. In particular, the contents of the portal would normally access the motion context of the react parent component, while they would instead need to access the motion context of where the portal is rendered (ie. the "slot"). I managed to fix this issue by reading the motion context around the "slot", passing it to the "fill", and recreating a new motion context with that same value — basically, manually "forwarding" the value of the motion context. Hope this can be of help to other folks. Feel free to reopen this issue in case that doesn't work for you |
@ciampo Do you have an example of how you fixed it? |
You can take a look at these 3 commits, part of a larger PR — although I appreciate that without much context on the project, it may be a bit overwhelming. Basically the idea is to forward the motion context through the react portal. |
1. Read the FAQs 👇
2. Describe the bug
Shared layout animations don't animate when:
Basically the combination of these two factors breaks the shared layout animation — instead, only the "first" and "last" states of the animation are rendered (without interpolation).
Initially reported in WordPress/gutenberg#40276
3. IMPORTANT: Provide a CodeSandbox reproduction of the bug
A CodeSandbox minimal reproduction will allow us to quickly follow the reproduction steps. Without one, this bug report won't be accepted.
https://codesandbox.io/s/framer-motion-and-portals-ozvlh3
4. Steps to reproduce
Steps to reproduce the behavior:
layoutId
propmotion.div
wrapper elements with a simplediv
After some time spent investigating, I believe that the
ProjectionNode
associated to the element participating in the shared layout animation keeps referencing the wrappermotion.div
as its root node, even after the component gets rendered in another part of the dom (via the portal). This could result in buggy behaviour, especially given howProjectionNode
s forward updates via their root nodes.5. Expected behavior
The shared layout animation works as expected, interpolating smoothly between the initial and final state of the animation.
6. Video or screenshots
framer-motion-portal-bug.mp4
7. Environment details
I don't think it's relevant, but I can reproduce the bug on Mac OS Chrome, Mac OS Firefox, Mac OS Safari (all latest versions).
The text was updated successfully, but these errors were encountered: