Before diving in, let me show you what we’re are going to build today 🔥
Smooth right? Let’s build it.
1. Setup
The page.tsx file exports a server component by default. If you have tried working with framer motion before, you’ll probably be familiar with the following error:
This is because framer-motion uses functionality that supports only in a client component. The solution is very simple. We make a client component where we import motion tags and the animation presence, and pass everything else as a children.
1.1 The ClientAnimatePresence Component
Make a client-animate-presence.tsx file inside your components folder with the following code:
// src/components/client-animate-presence.tsx
'use client';
import { AnimatePresence, AnimatePresenceProps } from 'framer-motion';
interface ClientAnimatePresenceProps extends AnimatePresenceProps {
children: React.ReactNode;
}
export default function ClientAnimatePresence(
props: ClientAnimatePresenceProps,
) {
return <AnimatePresence {...props}>{props.children}</AnimatePresence>;
}
Now instead of the AnimatePresence component we will use our custom client animate presence component.
1.2 The ClientMotionDiv Component
Similarly, make a client-motion-div.tsx file inside your components folder with the following code:
// src/components/client-motion-div.tsx
'use client';
import { motion, MotionProps } from 'framer-motion';
interface Props extends MotionProps {
children: React.ReactNode;
}
export default function ClientMotionDiv(props: Props) {
return <motion.div {...props}>{props.children}</motion.div>;
}
1.3 The PageAnimation component
// src/components/page-animation.tsx
import ClientAnimatePresence from './client-animate-presence';
import ClientMotionDiv from './client-motion-div';
const animation = {
transition: { duration: 0.2 },
initial: { opacity: 0, y: 20 },
animate: { opacity: 1, y: 0 },
exit: { opacity: 0, y: -20 },
};
export default function PageAnimation({
children,
}: {
children: React.ReactNode;
}) {
return (
<ClientAnimatePresence>
<ClientMotionDiv {...animation}>{children}</ClientMotionDiv>
</ClientAnimatePresence>
);
}
That’s it with the setup. It’s time to use animation to your pages.
2. Using the PageAnimation Component
The PageAnimation component now can be used in any server components inside the Nex.tjs (13 | 14) app folder. Here’s an example:
// src/app/poems/page.tsx
import PageAnimation from '@/components/page-animation';
export const metadata = {
title: 'Poems — Lines that I read and loved',
description: 'This is the poems page',
};
export default async function Poems() {
return (
<PageAnimation>
<div className='h-screen w-screen p-8 text-lg bg-blue-100 rounded-md'>Hello from my poems page!</div>
</PageAnimation>
);
}
And that’s it! Hope you’ve enjoyed reading the post ^^.
If it helped you, help others by sharing the article!
You can also check the implementation on my own portfolio in this github repo.