Skip to content

Commit

Permalink
added Frozen router for framer motion exit animations to work
Browse files Browse the repository at this point in the history
  • Loading branch information
Gaurav4604 committed Sep 18, 2023
1 parent 43f206b commit 36304d3
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 13 deletions.
8 changes: 2 additions & 6 deletions Junior/newsletter-sign-up/src/app/ThemeRegistry.tsx
Expand Up @@ -199,7 +199,7 @@ const theme = createTheme({
variants: [
{
props: {
component: "main",
className: "main",
},
style: ({ theme }) =>
theme.unstable_sx({
Expand Down Expand Up @@ -237,10 +237,6 @@ const theme = createTheme({
maxWidth: "920px",
minWidth: 0,
overflow: "hidden",
position: "absolute",
left: "50%",
top: "50%",
transform: "translate(-50%, -50%)",
p: "1rem",
borderRadius: "1.5rem",
display: "flex",
Expand Down Expand Up @@ -268,7 +264,7 @@ const theme = createTheme({
},
{
props: {
component: "main",
className: "main",
id: "success",
},
style: ({ theme }) =>
Expand Down
40 changes: 40 additions & 0 deletions Junior/newsletter-sign-up/src/app/client.tsx
@@ -0,0 +1,40 @@
"use client";

import { motion, AnimatePresence } from "framer-motion";
import ThemeRegistry from "./ThemeRegistry";
import { PropsWithChildren } from "react";

import { useSelectedLayoutSegment } from "next/navigation";
import FrozenRouter from "@/components/FrozenRouter";

// Client wraps any client/rsc components with AnimatePresence
export default function Client({ children }: PropsWithChildren) {
const segment = useSelectedLayoutSegment();
return (
<AnimatePresence
initial
mode="wait"
onExitComplete={() => console.log("triggered")}
>
<ThemeRegistry options={{ key: "mui" }} key={segment}>
<motion.main
initial={{
opacity: 0,
y: -100,
}}
animate={{
opacity: 1,
y: 0,
}}
exit={{
opacity: 0,
y: 100,
}}
transition={{ duration: 0.6, ease: "easeInOut" }}
>
<FrozenRouter>{children}</FrozenRouter>
</motion.main>
</ThemeRegistry>
</AnimatePresence>
);
}
7 changes: 7 additions & 0 deletions Junior/newsletter-sign-up/src/app/globals.css
Expand Up @@ -3,3 +3,10 @@
margin: 0;
box-sizing: border-box;
}

body {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
6 changes: 3 additions & 3 deletions Junior/newsletter-sign-up/src/app/layout.tsx
@@ -1,8 +1,8 @@
import "./globals.css";
import type { Metadata } from "next";
import ThemeRegistry from "./ThemeRegistry";
import { Container } from "@mui/material";
import { usePathname } from "next/navigation";
import { AnimatePresence, motion } from "framer-motion";
import Client from "./client";

export const metadata: Metadata = {
title: "Newsletter Sign-up",
Expand Down Expand Up @@ -31,7 +31,7 @@ export default function RootLayout({
return (
<html lang="en">
<body>
<ThemeRegistry options={{ key: "mui" }}>{children}</ThemeRegistry>
<Client>{children}</Client>
</body>
</html>
);
Expand Down
5 changes: 4 additions & 1 deletion Junior/newsletter-sign-up/src/app/signup/page.tsx
@@ -1,12 +1,14 @@
/* eslint-disable jsx-a11y/alt-text */
"use client";
import Image from "@/components/Image";
import ListItem from "@/components/ListItem";
import TextField from "@/components/TextField";
import { Container, List, Typography } from "@mui/material";
import { AnimatePresence, motion } from "framer-motion";

export default function Home() {
return (
<Container component="main" disableGutters>
<Container component={"main"} disableGutters className="main">
<Image />
<Container component={"section"} disableGutters>
<Typography variant="h1">Stay updated!</Typography>
Expand All @@ -21,5 +23,6 @@ export default function Home() {
<TextField />
</Container>
</Container>
// </AnimatePresence>
);
}
9 changes: 7 additions & 2 deletions Junior/newsletter-sign-up/src/app/success/page.tsx
Expand Up @@ -4,6 +4,7 @@ import NextImage from "next/image";
import { Container, Typography } from "@mui/material";
import { useRouter, useSearchParams } from "next/navigation";
import Button from "@/components/Button";
import { AnimatePresence, motion } from "framer-motion";

const Page = () => {
const params = useSearchParams();
Expand All @@ -21,7 +22,7 @@ const Page = () => {
return (
<>
{params.get("mail") !== undefined && (
<Container component={"main"} id="success">
<Container component={"main"} id="success" className="main">
<NextImage
alt="success-illustration"
id="success-image"
Expand All @@ -41,7 +42,11 @@ const Page = () => {
<Button
text="Dismiss message"
id="success"
onClick={() => router.replace("/signup")}
onClick={() =>
router.replace("/signup", {
scroll: false,
})
}
/>
</Container>
)}
Expand Down
13 changes: 13 additions & 0 deletions Junior/newsletter-sign-up/src/components/FrozenRouter.tsx
@@ -0,0 +1,13 @@
import { LayoutRouterContext } from "next/dist/shared/lib/app-router-context";
import { useContext, useRef } from "react";

export default function FrozenRouter(props: { children: React.ReactNode }) {

This comment has been minimized.

Copy link
@woohyun1031

woohyun1031 Mar 27, 2024

Hello. I was impressed by your work that came over from the framer,nextjs issue/1850.
I had a similar issue myself, where an exit animation occurred after moving to a new page.
I have a question. What is the exact purpose of OuterLayoutRouter that led to the conception of FrozenRouter?
And how does FrozenRouter operate? Thank you if you could provide an answer.

const context = useContext(LayoutRouterContext);
const frozen = useRef(context).current;

return (
<LayoutRouterContext.Provider value={frozen}>
{props.children}
</LayoutRouterContext.Provider>
);
}
6 changes: 5 additions & 1 deletion Junior/newsletter-sign-up/src/components/TextField.tsx
Expand Up @@ -56,7 +56,11 @@ const TextField = () => {
/>
<Button
text={"Subscribe to monthly newsletter"}
onClick={() => router.push(`/success?mail=${mail}`)}
onClick={() =>
router.push(`/success?mail=${mail}`, {
scroll: false,
})
}
/>
</>
);
Expand Down

1 comment on commit 36304d3

@vercel
Copy link

@vercel vercel bot commented on 36304d3 Sep 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.