├── .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 | 7 | 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 | --------------------------------------------------------------------------------