Trying to use framer motion ("motion/react") with intercepted and parallel routes.
Answered
Austrian Black and Tan Hound posted this in #help-forum
Austrian Black and Tan HoundOP
We have a "aside" parallel route which is responsible for displaying any content on client side navigation within an aside.
The initial animations from framer work as intended when client side routing to the cart for the very first time. The motion components animate as intended. What's weird is if you use "router.back" and then go back to the cart route, no animation happens. Almost as if the aside route for "/cart" was never unmounted. I've tried manually unmounting it myself using:
But that doesn't seem to work either, does anyone know of a working solution for this in v16 of Nextjs or a potential solution? I feel like the initial animation from framer should always happen, even when going back and forth between the routes.
Any help here is greatly appreciated. Thank you so very much!
-app
---page.tsx
---layout.tsx
---@aside
-----default.tsx
-----(.cart)
-------page.tsx
---cart
-----page.tsxThe initial animations from framer work as intended when client side routing to the cart for the very first time. The motion components animate as intended. What's weird is if you use "router.back" and then go back to the cart route, no animation happens. Almost as if the aside route for "/cart" was never unmounted. I've tried manually unmounting it myself using:
const path = usePathname()
const inView === "/cart";
return inView && <motion.div>{/** other stuff here **/}</motion.div>But that doesn't seem to work either, does anyone know of a working solution for this in v16 of Nextjs or a potential solution? I feel like the initial animation from framer should always happen, even when going back and forth between the routes.
Any help here is greatly appreciated. Thank you so very much!
Answered by Austrian Black and Tan Hound
Ahhh, I found out a kind of janky solution, but it works flawlessly 🤓
"use client";
import { useRouter } from "next/navigation";
import { useState, useEffect, startTransition, useEffectEvent } from "react";
import { AnimatePresence, motion } from "motion/react";
import { Dialog } from "radix-ui";
export default function Sidecart() {
const [isOpen, setIsOpen] = useState(false);
const router = useRouter();
useEffect(() => {
setIsOpen(true);
}, []);
const onAnimationComplete = useEffectEvent(() => {
if (!isOpen) router.back();
});
return (
<Dialog.Root
open={isOpen}
onOpenChange={(open) => startTransition(() => setIsOpen(open))}
>
<AnimatePresence>
{isOpen && (
<motion.span
variants={{
initial: {},
enter: {},
exit: {},
}}
initial="initial"
animate="enter"
exit="exit"
className="absolute h-[1px]"
onAnimationComplete={onAnimationComplete}
>
<Dialog.Portal forceMount>
<Dialog.Overlay asChild>
<motion.div
variants={{
initial: { opacity: 0 },
enter: { opacity: 1 },
exit: { opacity: 0 },
}}
className="fixed inset-0 bg-neutral-900/30"
/>
</Dialog.Overlay>
<Dialog.Content asChild forceMount>
<motion.div
variants={{
initial: { scale: 0.5, y: "10%", opacity: 0 },
enter: { scale: 1, y: 0, opacity: 1 },
exit: { scale: 0.5, y: 0, opacity: 0 },
}}
className="fixed left-1/2 top-1/2 max-h-[85vh] w-[90vw] max-w-[500px] -translate-x-1/2 -translate-y-1/2 rounded-md bg-default-surface p-[25px] shadow-[var(--shadow-6)] focus:outline-none"
>
<Dialog.Title className="m-0 text-[17px] font-medium text-mauve12">
Edit profile
</Dialog.Title>
<Dialog.Description className="mb-5 mt-2.5 text-[15px] leading-normal text-mauve11">
Make changes to your profile here. Click save when you're
done.
</Dialog.Description>
<div className="mt-[25px] flex justify-end">
<Dialog.Close asChild>
<button className="inline-flex h-[35px] items-center justify-center rounded bg-green4 px-[15px] font-medium leading-none text-green11 outline-none outline-offset-1 hover:bg-green5 focus-visible:outline-2 focus-visible:outline-green6 select-none">
Save changes
</button>
</Dialog.Close>
</div>
<Dialog.Close asChild>
<button
className="absolute right-2.5 top-2.5 inline-flex size-[25px] appearance-none items-center justify-center rounded-full text-violet11 bg-gray3 hover:bg-violet4 focus:shadow-[0_0_0_2px] focus:shadow-violet7 focus:outline-none"
aria-label="Close"
></button>
</Dialog.Close>
</motion.div>
</Dialog.Content>
</Dialog.Portal>
</motion.span>
)}
</AnimatePresence>
</Dialog.Root>
);
}1 Reply
Austrian Black and Tan HoundOP
Ahhh, I found out a kind of janky solution, but it works flawlessly 🤓
"use client";
import { useRouter } from "next/navigation";
import { useState, useEffect, startTransition, useEffectEvent } from "react";
import { AnimatePresence, motion } from "motion/react";
import { Dialog } from "radix-ui";
export default function Sidecart() {
const [isOpen, setIsOpen] = useState(false);
const router = useRouter();
useEffect(() => {
setIsOpen(true);
}, []);
const onAnimationComplete = useEffectEvent(() => {
if (!isOpen) router.back();
});
return (
<Dialog.Root
open={isOpen}
onOpenChange={(open) => startTransition(() => setIsOpen(open))}
>
<AnimatePresence>
{isOpen && (
<motion.span
variants={{
initial: {},
enter: {},
exit: {},
}}
initial="initial"
animate="enter"
exit="exit"
className="absolute h-[1px]"
onAnimationComplete={onAnimationComplete}
>
<Dialog.Portal forceMount>
<Dialog.Overlay asChild>
<motion.div
variants={{
initial: { opacity: 0 },
enter: { opacity: 1 },
exit: { opacity: 0 },
}}
className="fixed inset-0 bg-neutral-900/30"
/>
</Dialog.Overlay>
<Dialog.Content asChild forceMount>
<motion.div
variants={{
initial: { scale: 0.5, y: "10%", opacity: 0 },
enter: { scale: 1, y: 0, opacity: 1 },
exit: { scale: 0.5, y: 0, opacity: 0 },
}}
className="fixed left-1/2 top-1/2 max-h-[85vh] w-[90vw] max-w-[500px] -translate-x-1/2 -translate-y-1/2 rounded-md bg-default-surface p-[25px] shadow-[var(--shadow-6)] focus:outline-none"
>
<Dialog.Title className="m-0 text-[17px] font-medium text-mauve12">
Edit profile
</Dialog.Title>
<Dialog.Description className="mb-5 mt-2.5 text-[15px] leading-normal text-mauve11">
Make changes to your profile here. Click save when you're
done.
</Dialog.Description>
<div className="mt-[25px] flex justify-end">
<Dialog.Close asChild>
<button className="inline-flex h-[35px] items-center justify-center rounded bg-green4 px-[15px] font-medium leading-none text-green11 outline-none outline-offset-1 hover:bg-green5 focus-visible:outline-2 focus-visible:outline-green6 select-none">
Save changes
</button>
</Dialog.Close>
</div>
<Dialog.Close asChild>
<button
className="absolute right-2.5 top-2.5 inline-flex size-[25px] appearance-none items-center justify-center rounded-full text-violet11 bg-gray3 hover:bg-violet4 focus:shadow-[0_0_0_2px] focus:shadow-violet7 focus:outline-none"
aria-label="Close"
></button>
</Dialog.Close>
</motion.div>
</Dialog.Content>
</Dialog.Portal>
</motion.span>
)}
</AnimatePresence>
</Dialog.Root>
);
}Answer