├── src ├── fonts │ └── moonhouse.woff2 ├── assets │ └── images │ │ ├── cloud.png │ │ └── noise.gif ├── components │ ├── CustomCursor.js │ ├── Home.js │ ├── SectionTitle.js │ ├── Bio.js │ ├── Footer.js │ ├── NotFound.js │ ├── Socials.js │ ├── Hero.js │ ├── About.js │ ├── Project.js │ ├── Skills.js │ ├── Navbar.js │ ├── Contact.js │ └── Projects.js ├── index.js ├── hooks │ ├── useHoverEffect.js │ ├── useSmoothScroll.js │ ├── useCustomCursor.js │ └── gsap.js ├── App.js └── index.css ├── tailwind.config.js ├── .gitignore ├── package.json ├── README.md └── public └── index.html /src/fonts/moonhouse.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/masudranashawon/personal-portfolio/HEAD/src/fonts/moonhouse.woff2 -------------------------------------------------------------------------------- /src/assets/images/cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/masudranashawon/personal-portfolio/HEAD/src/assets/images/cloud.png -------------------------------------------------------------------------------- /src/assets/images/noise.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/masudranashawon/personal-portfolio/HEAD/src/assets/images/noise.gif -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ["./src/**/*.{js,jsx,ts,tsx}"], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [], 8 | }; 9 | -------------------------------------------------------------------------------- /src/components/CustomCursor.js: -------------------------------------------------------------------------------- 1 | const CustomCursor = ({ innerCursorRef, outerCursorRef }) => { 2 | return ( 3 | <> 4 |
5 |
6 | 7 | ); 8 | }; 9 | 10 | export default CustomCursor; 11 | -------------------------------------------------------------------------------- /.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 | # misc 12 | .DS_Store 13 | .env 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | 19 | npm-debug.log* 20 | yarn-debug.log* 21 | yarn-error.log* 22 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import { BrowserRouter } from "react-router-dom"; 4 | import App from "./App"; 5 | import "./index.css"; 6 | 7 | const root = ReactDOM.createRoot(document.getElementById("root")); 8 | root.render( 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | -------------------------------------------------------------------------------- /src/hooks/useHoverEffect.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | import hoverEffect from "hover-effect"; 3 | import cloud from "../assets/images/cloud.png"; 4 | 5 | export const useHoverEffect = (el, img1, img2) => { 6 | useEffect(() => { 7 | new hoverEffect({ 8 | parent: el.current, 9 | image1: img1, 10 | image2: img2, 11 | displacementImage: cloud, 12 | intensity: 0.3, 13 | }); 14 | }, [el, img1, img2]); 15 | }; 16 | -------------------------------------------------------------------------------- /src/components/Home.js: -------------------------------------------------------------------------------- 1 | import Bio from "./Bio"; 2 | import Hero from "./Hero"; 3 | import Projects from "./Projects"; 4 | import Skills from "./Skills"; 5 | import About from "./About"; 6 | import Contact from "./Contact"; 7 | 8 | const Home = () => { 9 | return ( 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | ); 19 | }; 20 | 21 | export default Home; 22 | -------------------------------------------------------------------------------- /src/components/SectionTitle.js: -------------------------------------------------------------------------------- 1 | import { useRef } from "react"; 2 | import { useSectionTitleReveal } from "../hooks/gsap"; 3 | 4 | const SectionTitle = ({ title }) => { 5 | const sectionTitleRef = useRef(null); 6 | 7 | useSectionTitleReveal(sectionTitleRef); 8 | 9 | return ( 10 |
11 |

12 | {title} 13 |

14 |
15 | ); 16 | }; 17 | 18 | export default SectionTitle; 19 | -------------------------------------------------------------------------------- /src/hooks/useSmoothScroll.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | import Lenis from "@studio-freight/lenis"; 3 | 4 | export const useSmoothScroll = () => { 5 | useEffect(() => { 6 | const lenis = new Lenis({ 7 | duration: 1.3, 8 | easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)), 9 | direction: "vertical", 10 | smooth: true, 11 | }); 12 | 13 | function raf(time) { 14 | lenis.raf(time); 15 | requestAnimationFrame(raf); 16 | } 17 | 18 | requestAnimationFrame(raf); 19 | }, []); 20 | }; 21 | -------------------------------------------------------------------------------- /src/components/Bio.js: -------------------------------------------------------------------------------- 1 | import { useRef } from "react"; 2 | import { useBioReveal } from "../hooks/gsap"; 3 | 4 | const Bio = () => { 5 | const bioRef = useRef(null); 6 | 7 | useBioReveal(bioRef, 2); 8 | 9 | return ( 10 |
11 |

12 | Passionate Full Stack developer based in Bangladesh, consistently 13 | pushing boundaries through impactful projects. I am dedicated to 14 | embracing new technologies and solving complex problems with a logical 15 | mindset. Committed to honest innovation, I strive to make a positive 16 | societal impact through my work. 17 |

18 |
19 | ); 20 | }; 21 | 22 | export default Bio; 23 | -------------------------------------------------------------------------------- /src/components/Footer.js: -------------------------------------------------------------------------------- 1 | import { useRef } from "react"; 2 | import { HashLink } from "react-router-hash-link"; 3 | import { useFooterReveal } from "../hooks/gsap"; 4 | 5 | const Footer = () => { 6 | const footerRef = useRef(null); 7 | 8 | useFooterReveal(footerRef); 9 | 10 | return ( 11 | 24 | ); 25 | }; 26 | 27 | export default Footer; 28 | -------------------------------------------------------------------------------- /src/hooks/useCustomCursor.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | 3 | export const useCustomCursor = (innerCursorRef, outerCursorRef) => { 4 | useEffect(() => { 5 | document.addEventListener("mousemove", moveCursor); 6 | 7 | function moveCursor(e) { 8 | let x = e.clientX; 9 | let y = e.clientY; 10 | 11 | innerCursorRef.current.style.left = `${x}px`; 12 | innerCursorRef.current.style.top = `${y}px`; 13 | outerCursorRef.current.style.left = `${x}px`; 14 | outerCursorRef.current.style.top = `${y}px`; 15 | 16 | let links = Array.from(document.querySelectorAll("a")); 17 | 18 | links.forEach((link) => { 19 | link.addEventListener("mouseover", () => { 20 | innerCursorRef.current.classList.add("grow"); 21 | }); 22 | 23 | link.addEventListener("mouseleave", () => { 24 | innerCursorRef.current.classList.remove("grow"); 25 | }); 26 | }); 27 | } 28 | }, [innerCursorRef, outerCursorRef]); 29 | }; 30 | -------------------------------------------------------------------------------- /src/components/NotFound.js: -------------------------------------------------------------------------------- 1 | import { useRef } from "react"; 2 | import { useGsapDownStagger } from "../hooks/gsap"; 3 | 4 | const NotFound = () => { 5 | const errorFirst4Ref = useRef(null); 6 | const bombImgRef = useRef(null); 7 | const errorLast4Ref = useRef(null); 8 | const pageNotFoundRef = useRef(null); 9 | const error404Arr = [errorFirst4Ref, bombImgRef, errorLast4Ref]; 10 | const pageNotFoundRefArr = [pageNotFoundRef]; 11 | 12 | useGsapDownStagger(error404Arr, 1.8); 13 | useGsapDownStagger(pageNotFoundRefArr, 2.7); 14 | 15 | return ( 16 |
17 |

18 | 4 19 | 20 | Black Bomb vector 26 | 4 27 |

28 |

page Not Found

29 |
30 | ); 31 | }; 32 | 33 | export default NotFound; 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "personal-portfolio", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@emailjs/browser": "^3.10.0", 7 | "@studio-freight/lenis": "^0.2.21", 8 | "@testing-library/jest-dom": "^5.16.5", 9 | "@testing-library/react": "^13.4.0", 10 | "@testing-library/user-event": "^13.5.0", 11 | "gsap": "^3.11.4", 12 | "hover-effect": "^1.1.0", 13 | "react": "^18.2.0", 14 | "react-dom": "^18.2.0", 15 | "react-router-dom": "^6.8.0", 16 | "react-router-hash-link": "^2.4.3", 17 | "react-scripts": "5.0.1", 18 | "react-toastify": "^9.1.1", 19 | "three": "^0.149.0", 20 | "web-vitals": "^2.1.4" 21 | }, 22 | "scripts": { 23 | "start": "react-scripts start", 24 | "build": "react-scripts build", 25 | "test": "react-scripts test", 26 | "eject": "react-scripts eject" 27 | }, 28 | "eslintConfig": { 29 | "extends": [ 30 | "react-app", 31 | "react-app/jest" 32 | ] 33 | }, 34 | "browserslist": { 35 | "production": [ 36 | ">0.2%", 37 | "not dead", 38 | "not op_mini all" 39 | ], 40 | "development": [ 41 | "last 1 chrome version", 42 | "last 1 firefox version", 43 | "last 1 safari version" 44 | ] 45 | }, 46 | "devDependencies": { 47 | "tailwindcss": "^3.2.4" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import { useRef } from "react"; 2 | import { Route, Routes } from "react-router-dom"; 3 | import { useSmoothScroll } from "./hooks/useSmoothScroll"; 4 | import { useCustomCursor } from "./hooks/useCustomCursor"; 5 | import { ToastContainer } from "react-toastify"; 6 | 7 | import Home from "./components/Home"; 8 | import Navbar from "./components/Navbar"; 9 | import Footer from "./components/Footer"; 10 | import Socials from "./components/Socials"; 11 | import CustomCursor from "./components/CustomCursor"; 12 | import NotFound from "./components/NotFound"; 13 | 14 | import "react-toastify/dist/ReactToastify.css"; 15 | 16 | const App = () => { 17 | const innerCursorRef = useRef(null); 18 | const outerCursorRef = useRef(null); 19 | 20 | useSmoothScroll(); 21 | useCustomCursor(innerCursorRef, outerCursorRef); 22 | 23 | return ( 24 |
25 | 26 |
27 | 31 | 32 | 33 | 34 | } /> 35 | } /> 36 | 37 | 38 |
40 | ); 41 | }; 42 | 43 | export default App; 44 | -------------------------------------------------------------------------------- /src/components/Socials.js: -------------------------------------------------------------------------------- 1 | import { useRef } from "react"; 2 | import { useSocialReveal } from "../hooks/gsap"; 3 | 4 | const data = [ 5 | { 6 | id: 1, 7 | title: "Facebook", 8 | url: "https://www.facebook.com/masudranashawon786", 9 | }, 10 | { 11 | id: 2, 12 | title: "Instagram", 13 | url: "https://instagram.com/masudranashawon786", 14 | }, 15 | { id: 3, title: "Twitter", url: "https://twitter.com/MasudRanaShawo1" }, 16 | { 17 | id: 4, 18 | title: "LinkedIn", 19 | url: "https://www.linkedin.com/in/masudranashawon1/", 20 | }, 21 | { id: 5, title: "GitHub", url: "https://github.com/masudranashawon" }, 22 | { id: 6, title: "LeetCode", url: "https://leetcode.com/masudranashawon" }, 23 | ]; 24 | 25 | const Socials = () => { 26 | const socialRef = useRef(null); 27 | 28 | useSocialReveal(socialRef, 2.5); 29 | 30 | return ( 31 |
35 | {data.map((social) => ( 36 | 43 | {social.title} 44 | 45 | ))} 46 |
47 | ); 48 | }; 49 | 50 | export default Socials; 51 | -------------------------------------------------------------------------------- /src/components/Hero.js: -------------------------------------------------------------------------------- 1 | import { useRef } from "react"; 2 | import { useHoverEffect } from "../hooks/useHoverEffect"; 3 | import { useImageReveal, useHeadlineReveal } from "../hooks/gsap"; 4 | 5 | const data = { 6 | img1: "https://res.cloudinary.com/drgxflcsb/image/upload/v1676030149/Personal%20Portfolio/masud-image2_xhvc03.jpg", 7 | img2: "https://res.cloudinary.com/drgxflcsb/image/upload/v1676030149/Personal%20Portfolio/masud-image1_rejzqv.jpg", 8 | }; 9 | 10 | const Hero = () => { 11 | const heroImageRef = useRef(null); 12 | const heroHeadline1Ref = useRef(null); 13 | const heroHeadline2Ref = useRef(null); 14 | 15 | const headlLines = [heroHeadline1Ref, heroHeadline2Ref]; 16 | 17 | useHoverEffect(heroImageRef, data.img1, data.img2); 18 | useImageReveal(heroImageRef, 0.5); 19 | useHeadlineReveal(headlLines, 1.5); 20 | 21 | return ( 22 |
26 |
27 |
28 |

Full Stack

29 |
30 |
31 |

Developer

32 |
33 |
34 |
35 |
36 | ); 37 | }; 38 | 39 | export default Hero; 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Personal Portfolio 2 | 3 | This repository contains code for a personal portfolio website built using React, GSAP, WebGL, Three.js, and Tailwind CSS. The website showcases the developer's skills and work in an interactive and engaging manner. 4 | 5 | ## Features 6 | The portfolio website comes with the following features: 7 | 8 | - **Creative artistic UI:** Interactive and engaging design using React, GSAP, WebGL, Three.js, and Tailwind CSS. 9 | - **Easy navigate:** Easy-to-navigate portfolio sections that showcase the developer's work. 10 | - **Dynamic Contact form:** Contact form for potential clients or collaborators. 11 | - **Intuitive and Streamlined UI:** User interface is designed to be both intuitive and streamlined, making project management a breeze. The clean and modern design of the interface allows users to easily navigate the app's many features, while also providing a visually pleasing and enjoyable user experience. 12 | 13 | ## Tools 14 | 15 | Personal Portfolio is built using the React, featuring the following powerful tools: 16 | 17 | - **React:** A powerful and popular frontend JavaScript library, ideal for building user interfaces. 18 | - **GSAP:** A powerful animation library for JavaScript. 19 | - **@studio-freight/lenis:** A lightweight and flexible library for creating scroll animations 20 | - **WebGL:** A JavaScript API for rendering interactive 2D and 3D graphics within any compatible web browser 21 | - **React Toastify:** A library for creating customizable toast notifications in React apps 22 | - **Tree.js:** A popular JavaScript library used for creating and rendering 3D animations and graphics in web browsers. It provides an easy-to-use API for building complex 3D scenes using WebGL, which allows for hardware-accelerated rendering. 23 | - **Tailwind CSS:** A highly customizable CSS framework, designed to make building sleek and intuitive user interfaces a breeze. 24 | 25 | ## Installation 26 | 27 | To install Personal portfolio, Follow the simple steps below: 28 | 29 | 1. Clone the repository using 30 | 31 | ``` 32 | git clone https://github.com/masudranashawon/proxima-client.git` 33 | ``` 34 | 35 | 2. Install the required dependencies in the directorie by running 36 | 37 | ``` 38 | npm install 39 | ``` 40 | 41 | **Or** 42 | 43 | ``` 44 | npm i 45 | ``` 46 | 47 | 3. Start the development server running 48 | 49 | ``` 50 | npm start 51 | ``` 52 | 53 | ## Link 54 | 55 | - [Live Demo](https://masudranashawon.netlify.app/) 56 | 57 | ## Thanks for visiting this repository! 58 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Masud Rana Shawon - Full Stack Developer 9 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 22 | 24 | 25 | 26 | 27 | 28 | 29 | 31 | 33 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
43 | 44 | 45 | -------------------------------------------------------------------------------- /src/components/About.js: -------------------------------------------------------------------------------- 1 | import { useRef } from "react"; 2 | import { useHoverEffect } from "../hooks/useHoverEffect"; 3 | import { useProjectLeftRightReveal } from "../hooks/gsap"; 4 | import SectionTitle from "./SectionTitle"; 5 | 6 | const data = { 7 | img1: "https://res.cloudinary.com/drgxflcsb/image/upload/v1676030150/Personal%20Portfolio/masud-image3_vxmpd0.jpg", 8 | img2: "https://res.cloudinary.com/drgxflcsb/image/upload/v1676030148/Personal%20Portfolio/masud-image4_cbbkzc.jpg", 9 | }; 10 | 11 | const About = () => { 12 | const aboutLeftRef = useRef(null); 13 | const aboutRightRef = useRef(null); 14 | 15 | const aboutRefs = [aboutLeftRef, aboutRightRef]; 16 | 17 | useHoverEffect(aboutLeftRef, data.img1, data.img2); 18 | useProjectLeftRightReveal(aboutRefs); 19 | 20 | return ( 21 |
22 | 23 |
24 |
25 |
26 |

27 | Welcome to my portfolio! I'm deeply passionate about JavaScript and 28 | its power in creating dynamic web applications. My journey into web 29 | development began in July 2022, and since then, I've immersed myself 30 | in Full Stack development. Constantly learning and pushing 31 | boundaries, I thrive on building innovative solutions. My insatiable 32 | curiosity drives me to stay updated with the latest developments, 33 | ensuring I contribute to technological advancement through impactful 34 | projects. 35 |

36 |

37 | As a Full Stack developer based in Bangladesh, I am committed to 38 | honing my skills and solving complex problems with logic. I approach 39 | every project with a dedication to honest innovation, aiming for a 40 | positive societal impact. My goal is to not only meet but exceed 41 | expectations, delivering excellence in every endeavor. 42 |

43 | 49 | View My Resume 50 | 51 |
52 |
53 |
54 | ); 55 | }; 56 | 57 | export default About; 58 | -------------------------------------------------------------------------------- /src/components/Project.js: -------------------------------------------------------------------------------- 1 | import { useRef } from "react"; 2 | import { useProjectLeftRightReveal } from "../hooks/gsap"; 3 | import { useHoverEffect } from "../hooks/useHoverEffect"; 4 | 5 | const Project = ({ project }) => { 6 | const projectRightRef = useRef(null); 7 | const projectLeftRef = useRef(null); 8 | 9 | const projetRefs = [projectRightRef, projectLeftRef]; 10 | 11 | useHoverEffect(projectRightRef, project.image1, project.image2); 12 | useProjectLeftRightReveal(projetRefs); 13 | 14 | return ( 15 |
16 |
20 | 21 | {String(project.id).padStart(2, 0)} 22 | 23 |

24 | {project.title} 25 |

26 |

{project.description}

27 | 28 | {project.tools.map((tool, i) => ( 29 | {tool} 30 | ))} 31 | 32 |
33 | 39 | Live Site 40 | 41 | 42 | {project.fullStackLink && ( 43 | 49 | Full Stack Code 50 | 51 | )} 52 | 53 | {project.frontEndLink && ( 54 | 60 | Front-End Code 61 | 62 | )} 63 | 64 | {project.backEndLink && ( 65 | 71 | Back-End Code 72 | 73 | )} 74 |
75 |
76 |
80 |
81 | ); 82 | }; 83 | 84 | export default Project; 85 | -------------------------------------------------------------------------------- /src/components/Skills.js: -------------------------------------------------------------------------------- 1 | import { useRef } from "react"; 2 | import { useSkillLineReveal, useSkillTextReveal } from "../hooks/gsap"; 3 | import SectionTitle from "./SectionTitle"; 4 | 5 | const data = [ 6 | { id: 1, title: "HTML" }, 7 | { id: 2, title: "CSS" }, 8 | { id: 3, title: "SCSS/SASS" }, 9 | { id: 4, title: "Bootstrap" }, 10 | { id: 5, title: "Tailwind CSS" }, 11 | { id: 6, title: "JavaScript" }, 12 | { id: 7, title: "jQuery" }, 13 | { id: 8, title: "TypeScript" }, 14 | { id: 9, title: "PHP" }, 15 | { id: 10, title: "React.js" }, 16 | { id: 11, title: "Next.js" }, 17 | { id: 12, title: "Redux.js/Redux Toolkit" }, 18 | { id: 13, title: "Firebase Auth" }, 19 | { id: 14, title: "Next Auth" }, 20 | { id: 15, title: "GSAP" }, 21 | { id: 16, title: "Framer Motion" }, 22 | { id: 17, title: "Node.js" }, 23 | { id: 18, title: "Express.js" }, 24 | { id: 19, title: "Laravel" }, 25 | { id: 20, title: "MySQL" }, 26 | { id: 21, title: "MongoDB" }, 27 | { id: 22, title: "Prisma" }, 28 | { id: 23, title: "Mongoose" }, 29 | { id: 24, title: "Stripe Payment" }, 30 | ]; 31 | 32 | const Skills = () => { 33 | const skillItemRef = useRef([]); 34 | const skillTextRef = useRef([]); 35 | const skillItem2Ref = useRef([]); 36 | const skillText2Ref = useRef([]); 37 | 38 | useSkillLineReveal(skillItemRef.current); 39 | useSkillLineReveal(skillItem2Ref.current); 40 | useSkillTextReveal(skillItemRef.current); 41 | useSkillTextReveal(skillItem2Ref.current); 42 | 43 | return ( 44 |
45 | 46 |
47 |
    48 | {data 49 | .filter((_, i) => i < Math.floor(data.length / 2)) 50 | .map((skill, i) => ( 51 |
  • (skillItemRef.current[i] = el)} 55 | > 56 |
    (skillTextRef.current[i] = el)} 59 | > 60 | 61 | {String(skill.id).padStart(2, 0).padEnd(3, ".")} 62 | 63 | {skill.title} 64 |
    65 |
  • 66 | ))} 67 |
68 |
    69 | {data 70 | .filter((_, i) => i >= Math.floor(data.length / 2)) 71 | .map((skill, i) => ( 72 |
  • (skillItem2Ref.current[i] = el)} 76 | > 77 |
    (skillText2Ref.current[i] = el)} 80 | > 81 | 82 | {String(skill.id).padStart(2, 0).padEnd(3, ".")} 83 | 84 | {skill.title} 85 |
    86 |
  • 87 | ))} 88 |
89 |
90 |
91 | ); 92 | }; 93 | 94 | export default Skills; 95 | -------------------------------------------------------------------------------- /src/components/Navbar.js: -------------------------------------------------------------------------------- 1 | import { useRef } from "react"; 2 | import { HashLink } from "react-router-hash-link"; 3 | import { useLinkReveal } from "../hooks/gsap"; 4 | 5 | const Navbar = ({ footerNav }) => { 6 | const link1Ref = useRef(null); 7 | const link2Ref = useRef(null); 8 | const link3Ref = useRef(null); 9 | const link4Ref = useRef(null); 10 | const link5Ref = useRef(null); 11 | const link6Ref = useRef(null); 12 | const link7Ref = useRef(null); 13 | const link8Ref = useRef(null); 14 | const link9Ref = useRef(null); 15 | 16 | const links = [ 17 | link1Ref, 18 | link2Ref, 19 | link3Ref, 20 | link4Ref, 21 | link5Ref, 22 | link6Ref, 23 | link7Ref, 24 | link8Ref, 25 | link9Ref, 26 | ]; 27 | 28 | useLinkReveal(links, 2); 29 | 30 | return ( 31 | 106 | ); 107 | }; 108 | 109 | export default Navbar; 110 | -------------------------------------------------------------------------------- /src/components/Contact.js: -------------------------------------------------------------------------------- 1 | import { useRef } from "react"; 2 | import { useInputReveal } from "../hooks/gsap"; 3 | import { toast } from "react-toastify"; 4 | import emailjs from "@emailjs/browser"; 5 | import SectionTitle from "./SectionTitle"; 6 | 7 | const Contact = () => { 8 | const formRef = useRef(null); 9 | const input1Ref = useRef(null); 10 | const input2Ref = useRef(null); 11 | const input3Ref = useRef(null); 12 | const input4Ref = useRef(null); 13 | 14 | const inputsRef = [input1Ref, input2Ref, input3Ref, input4Ref]; 15 | 16 | useInputReveal(inputsRef); 17 | 18 | const sendMail = (e) => { 19 | e.preventDefault(); 20 | 21 | //Email JS integration 22 | emailjs 23 | .sendForm( 24 | process.env.REACT_APP_SERVICE_ID, 25 | process.env.REACT_APP_TEMPLATE_ID, 26 | formRef.current, 27 | process.env.REACT_APP_PUBLIC_ID 28 | ) 29 | .then( 30 | () => { 31 | toast("Message send successfully!", { 32 | position: "bottom-left", 33 | autoClose: 5000, 34 | hideProgressBar: false, 35 | closeOnClick: true, 36 | pauseOnHover: true, 37 | draggable: true, 38 | progress: undefined, 39 | theme: "light", 40 | }); 41 | }, 42 | () => { 43 | toast.error("Message failed! Try again letter", { 44 | position: "bottom-left", 45 | autoClose: 5000, 46 | hideProgressBar: false, 47 | closeOnClick: true, 48 | pauseOnHover: true, 49 | draggable: true, 50 | progress: undefined, 51 | theme: "colored", 52 | }); 53 | } 54 | ); 55 | 56 | //Clear input 57 | e.target.querySelector(".fullname").value = ""; 58 | e.target.querySelector(".email").value = ""; 59 | e.target.querySelector(".massage").value = ""; 60 | }; 61 | 62 | return ( 63 |
64 | 65 | 66 |
71 | {/* Hidden field for project identifier */} 72 | 73 | 74 |
75 | 83 |
84 |
85 | 93 |
94 |
95 |