Jump to content
Search Community

Animating a RadixUI Dialog component with GSAP in React

henryb test
Moderator Tag

Go to solution Solved by Rodrigo,

Recommended Posts

Hello,

I'm attempting to animate a dialog component from RadixUI's component library in a NextJS 14 App router project.

 

I have converted the Radix component to a controlled component following their docs (and this useful video by Sam Selikoff), by not using the internal wiring from Radix that opens the dialog with the <Dialog.Trigger /> component and instead conditionally rendering the dialog with state isOpen and the use of forceMount prop on <Dialog.Portal />. I would expect to simply give the useGSAP() hook a dependency [isOpen] and trigger the timeline to play() or reverse() based on that state too. The forceMount prop is used to delegate the mounting and unmounting of children based on the animation state. But currently I have no GSAP animation playing. I realise there is some specificity to Radix with this question, but if anyone is willing to check my GSAP code I would be very grateful. In fact the logic described above may not be necessary; I noted another question in the forum animating a Radix component and from the code that was provided in that question it did not appear that the OP was using forceMount, indeed the conditional rendering appeared to follow a conventional approach.

 

My Stackblitz demo is here: Stackblitz


In the above demo there are two routes; one dialog animating with GSAP without a RadixUI dialog component, and another route with the RadixUI dialog component, but not currently animated with GSAP. The GSAP code is scaffolded out on that page, but is not animating the dialog into view. The animation I am aiming for would resemble the animation from the route currently without Radix.

Many thanks in advance :) 

Link to comment
Share on other sites

  • Solution

Hi,

 

Yeah the issue is not related to GSAP but simply the way these frameworks/libraries actually work. When you toggle the setOpen state, that tells radix to render the modal component, but it doesn't mean that the DOM has been updated.

 

When you create this:

useGSAP(
  () => {

    tlRef.current = gsap.timeline({
      paused: true,
      defaults: { ease: 'power1.inOut' },
    });

    tlRef.current
      .to('.modal', { autoAlpha: 1, duration: 0.7 })
      .to('.overlay', { autoAlpha: 1, duration: 0.5 }, '<')
      .to(
      '.menu-item',
      {
        autoAlpha: 1,
        stagger: 0.1,
        duration: 1,
      },
      '>'
    )
      .reverse();
  },
  {
    scope: containerRef,
  }
);

That runs when the component first mounts and the modal is not mounted so all those selectors come back null, so while the GSAP Timeline has been created, no DOM element will be animated. In fact if you remove all your GSAP code and leave just this:

const [isOpen, setIsOpen] = useState(false);
const [isMounted, setIsMounted] = useState(false);

const containerRef = useRef<HTMLDivElement | null>(null);

const toggle = () => {
  setIsOpen(!isOpen);
};

useEffect(() => {
  setIsMounted(true);
}, []);

And inspect the DOM there is nothing being added to it, so updating the isOpen state is not causing any effect in the DOM, the modal is not even being rendered, so you should first check that the modal is being rendered in the DOM before it can be animated with GSAP.

 

Happy Tweening!

  • Like 1
Link to comment
Share on other sites

Hi Rodrigo,

Thank you for your reply; that was very useful for me to realise those selectors of course had no elements to refer to in the DOM.

It seems that Radix's forceMount prop would force the modal portal to be present in the DOM on mount, and then it would be a matter of animating the visibility of the modal. I will test whether this works well for a modal (I would need to manage pointer events so that with visibility hidden the portal is not blocking other interactions). If all works well I will post the results here for others who might be interested in the future.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...