├── .eslintrc.json
├── styles
└── globals.css
├── public
├── favicon.ico
├── vercel.svg
├── thirteen.svg
└── next.svg
├── postcss.config.js
├── next.config.js
├── pages
├── _document.tsx
├── about.tsx
├── index.tsx
├── contact.tsx
└── _app.tsx
├── tailwind.config.js
├── animations.js
├── README.md
├── components
├── Title.tsx
├── PageTransition.tsx
└── Navbar.tsx
├── tsconfig.json
├── .gitignore
└── package.json
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "next/core-web-vitals"
3 | }
4 |
--------------------------------------------------------------------------------
/styles/globals.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/whitehorse21/next-page-transition/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {
3 | reactStrictMode: true,
4 | }
5 |
6 | module.exports = nextConfig
7 |
--------------------------------------------------------------------------------
/pages/_document.tsx:
--------------------------------------------------------------------------------
1 | import { Html, Head, Main, NextScript } from 'next/document'
2 |
3 | export default function Document() {
4 | return (
5 |
6 |
8 |
9 |
10 |
11 |
12 | )
13 | }
14 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | content: [
4 | "./pages/**/*.{js,ts,jsx,tsx}",
5 | "./components/**/*.{js,ts,jsx,tsx}",
6 | ],
7 | theme: {
8 | extend: {
9 | fontFamily: {
10 | lato: ["var(--font-lato)", "sans-serif"],
11 | },
12 | },
13 | },
14 | plugins: [],
15 | };
16 |
--------------------------------------------------------------------------------
/animations.js:
--------------------------------------------------------------------------------
1 | export const container = {
2 | hidden: {
3 | opacity: 0,
4 | },
5 | show: {
6 | opacity: 1,
7 | transition: {
8 | delayChildren: 0.6,
9 | staggerChildren: 0.25,
10 | },
11 | },
12 | };
13 |
14 | export const item = {
15 | hidden: {
16 | y: "100%",
17 | },
18 | show: {
19 | y: 0,
20 | transition: {
21 | duration: 0.6,
22 | },
23 | },
24 | };
25 |
--------------------------------------------------------------------------------
/pages/about.tsx:
--------------------------------------------------------------------------------
1 | import PageTransition from "../components/PageTransition";
2 | import Title from "../components/Title";
3 |
4 | export default function About({ bg }: { bg: string }) {
5 | return (
6 |
7 |
8 |
9 |
About Us
10 |
11 |
12 |
13 | );
14 | }
15 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ⚙️ Project
2 |
3 | Animation in the transition of pages using Next.js, Framer Motion and Tailwind CSS, with the implementation of responsive design and option to change the font color per page (which accompanies the transition animation).
4 |
5 | # ✈️ Technologies
6 |
7 | - Next.js
8 | - Tailwind CSS
9 | - Framer Motion
10 |
--------------------------------------------------------------------------------
/components/Title.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { motion } from "framer-motion";
3 |
4 | export default function Title({ children }: { children: React.ReactNode }) {
5 | return (
6 |
7 |
13 | {children}
14 |
15 |
16 | );
17 | }
18 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "noEmit": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "jsx": "preserve",
16 | "incremental": true
17 | },
18 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
19 | "exclude": ["node_modules"]
20 | }
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 |
15 | # production
16 | /build
17 |
18 | # misc
19 | .DS_Store
20 | *.pem
21 |
22 | # debug
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 | .pnpm-debug.log*
27 |
28 | # local env files
29 | .env*.local
30 |
31 | # vercel
32 | .vercel
33 |
34 | # typescript
35 | *.tsbuildinfo
36 | next-env.d.ts
37 |
38 | # Local Netlify folder
39 | .netlify
40 |
--------------------------------------------------------------------------------
/components/PageTransition.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { motion } from "framer-motion";
3 |
4 | interface Props {
5 | children: React.ReactNode;
6 | bg?: string;
7 | }
8 |
9 | export default function PageTransition({ children, bg = "bg-white" }: Props) {
10 | return (
11 |
18 | {children}
19 |
20 | );
21 | }
22 |
--------------------------------------------------------------------------------
/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "page-transition-nextjs",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint"
10 | },
11 | "dependencies": {
12 | "@next/font": "13.1.1",
13 | "@types/node": "18.11.18",
14 | "@types/react": "18.0.26",
15 | "@types/react-dom": "18.0.10",
16 | "eslint": "8.31.0",
17 | "eslint-config-next": "13.1.1",
18 | "framer-motion": "^8.1.5",
19 | "next": "13.1.1",
20 | "react": "18.2.0",
21 | "react-dom": "18.2.0",
22 | "typescript": "4.9.4"
23 | },
24 | "devDependencies": {
25 | "autoprefixer": "^10.4.13",
26 | "postcss": "^8.4.20",
27 | "tailwindcss": "^3.2.4"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/pages/index.tsx:
--------------------------------------------------------------------------------
1 | import PageTransition from "../components/PageTransition";
2 | import Title from "../components/Title";
3 |
4 | export default function Home({ bg }: { bg: string }) {
5 | return (
6 |
7 |
8 |
9 |
Happy Pickle
10 |
11 |
12 |
13 |
14 |
Design
15 | Company
16 | 2023
17 |
18 |
19 |
This pickle gonna make you smile.
20 | Scottish designs to make you happy.
21 | Click contact for cool transition.
22 |
23 |
24 |
25 |
26 | );
27 | }
28 |
--------------------------------------------------------------------------------
/components/Navbar.tsx:
--------------------------------------------------------------------------------
1 | import Link from "next/link";
2 | import { motion } from "framer-motion";
3 |
4 | const paths = [
5 | { name: "Home", path: "/" },
6 | { name: "Contact", path: "/contact" },
7 | { name: "About", path: "/about" },
8 | ];
9 |
10 | export default function Navbar({ currentPath }: { currentPath: string }) {
11 | return (
12 |
29 | );
30 | }
31 |
--------------------------------------------------------------------------------
/public/thirteen.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/next.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/pages/contact.tsx:
--------------------------------------------------------------------------------
1 | import { motion, AnimatePresence } from "framer-motion";
2 | import PageTransition from "../components/PageTransition";
3 | import Title from "../components/Title";
4 | import { container, item } from "../animations";
5 |
6 | export default function Contact({ bg }: { bg: string }) {
7 | return (
8 |
9 |
10 |
11 |
Let's Talk
12 |
13 |
14 |
15 |
16 |
Find me:
17 |
18 |
19 |
20 |
26 | {["Twitter", "Instagram", "LinkedIn", "Dribble"].map(
27 | (social) => (
28 |
29 |
30 | {social}
31 |
32 |
33 | )
34 | )}
35 |
36 |
37 |
38 |
39 |
40 |
41 | );
42 | }
43 |
--------------------------------------------------------------------------------
/pages/_app.tsx:
--------------------------------------------------------------------------------
1 | import type { AppProps } from "next/app";
2 | import { useEffect, useState } from "react";
3 | import { AnimatePresence } from "framer-motion";
4 | import Head from "next/head";
5 | import Navbar from "../components/Navbar";
6 | import "../styles/globals.css";
7 |
8 | import { Lato } from "@next/font/google";
9 |
10 | const lato = Lato({
11 | weight: ["300", "400", "700"],
12 | style: ["normal"],
13 | subsets: ["latin"],
14 | variable: "--font-lato",
15 | });
16 |
17 | const pathsPalette: {
18 | [key: string]: {
19 | bg?: string;
20 | text?: string;
21 | };
22 | } = {
23 | default: {
24 | bg: "bg-blue-500",
25 | text: "text-white",
26 | },
27 | "/contact": {
28 | bg: "bg-orange-300",
29 | text: "text-gray-900",
30 | },
31 | "/about": {
32 | bg: "bg-lime-600",
33 | },
34 | };
35 |
36 | export default function App({ Component, pageProps, router }: AppProps) {
37 | const { pathname } = router;
38 | const text = pathsPalette[pathname]?.text || pathsPalette.default.text;
39 | const bg = pathsPalette[pathname]?.bg || pathsPalette.default.bg;
40 | const [textColor, setTextColor] = useState(text);
41 |
42 | useEffect(() => {
43 | setTimeout(() => setTextColor(text), 390);
44 | }, [pathname]);
45 |
46 | console.log("render");
47 |
48 | return (
49 |
50 |
51 |
Page Transition - whitehorse21
52 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | );
67 | }
68 |
--------------------------------------------------------------------------------