I'm having trouble figuring out how to set up page routing with the new layout.tsx feature in Next.js. I have an _app.tsx file that enables page transitions with Framer-Motion and AnimatePresence. I'm unsure about how to connect this with my layout.tsx
_app.tsx
import { AnimatePresence } from "framer-motion";
import { AppProps } from "next/app";
import { useRouter } from "next/router";
export default function App({ Component, pageProps }: AppProps) {
const router = useRouter();
const pageKey = router.asPath;
return (
<div>
<AnimatePresence initial={false} mode="popLayout">
<div className="flex flex-col min-h-screen">{pageKey}</div>
<Component key={pageKey} {...pageProps} />
</AnimatePresence>
</div>
);
}
layout.tsx
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import Header from "@/components/layout/header";
import Lines from "@/components/line/lines";
import Footer from "@/components/layout/footer";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "A website for gamers",
description: "A website for gamers is a website for gamers.",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={inter.className}>
<main className="min-h-screen grid grid-rows-[auto,1fr,auto]">
<Header />
<div className="relative overflow-hidden">
<Lines />
{children}
</div>
<Footer />
</main>
</body>
</html>
);
}
PageTransisiton
import React, { forwardRef, useMemo } from "react";
import { motion, HTMLMotionProps, AnimatePresence } from "framer-motion";
type PageTransitionProps = HTMLMotionProps<"div">;
type PageTransitionRef = React.ForwardedRef<HTMLDivElement>;
function PageTransition(
{ children, ...rest }: PageTransitionProps,
ref: PageTransitionRef
) {
const fromTheBottom = { y: "100%" };
const inTheMiddle = { y: 0 };
const toTheTop = { y: "-100%" };
const transition = { duration: 0.6, ease: "easeInOut" };
return (
<motion.section
className="relative flex-1 h-full flex flex-col"
ref={ref}
initial={fromTheBottom}
animate={inTheMiddle}
exit={toTheTop}
transition={transition}
{...rest}
>
{children}
</motion.section>
);
}
export default forwardRef(PageTransition);
Page.tsx
"use client";
import Hero from "@/components/hero/hero";
import PageTransition from "@/components/pageTransition";
import { forwardRef } from "react";
type IndexPageProps = {};
type IndexPageRef = React.ForwardedRef<HTMLDivElement>;
function IndexPage(props: IndexPageProps, ref: IndexPageRef) {
return (
<PageTransition ref={ref}>
<Hero />
</PageTransition>
);
}
export default forwardRef(IndexPage);
I'm not entirely sure if I understand your question correctly.
Why are your using page transitions with Framer Motion and AnimatePresence in the first place?
Page routing in Next.js 13 remains similar to the previous versions.
In previous versions, you would define pages like this:
In the "pages" folder you would define the pages:
pages/home.tsx => //https:www.mydomain.com/homepages/about.tsx => //https:www.mydomain.com/aboutWith the app router in Next.js 13, the structure is slightly different.
You create a folder with the name of your page in the "app" folder, and within that folder, you create a
page.tsxfile. For example:app/home/page.tsx => //https:www.mydomain.com/homeapp/about/page.tsx => //https:www.mydomain.com/aboutThe
layout.tsxfile is optional and is intended for UI components shared between routes.Here is the official documentation for the file conventionsin next 13.
https://nextjs.org/docs/app/api-reference/file-conventions