diff --git a/package-lock.json b/package-lock.json index 4c6ec37..7f215d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,12 +14,14 @@ "@t3-oss/env-nextjs": "^0.8.0", "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", + "framer-motion": "^11.0.5", "lucide-react": "^0.312.0", "next": "14.1.0", "next-themes": "^0.2.1", "react": "^18", "react-dom": "^18", "react-hook-form": "^7.50.0", + "react-intersection-observer": "^9.8.0", "react-vertical-timeline-component": "^3.6.0", "resend": "^3.2.0", "sonner": "^1.4.0", @@ -1285,6 +1287,21 @@ "integrity": "sha512-N8uEMrMPL0cu/bdboEWpQYb/0i2K5Qn8eCsxzOmxSggJbbQte7ljMRoXm917AbntqTGOzdTu+vP3KOOzoC70HQ==", "dev": true }, + "node_modules/@emotion/is-prop-valid": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", + "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "optional": true, + "dependencies": { + "@emotion/memoize": "0.7.4" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", + "optional": true + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -5344,6 +5361,29 @@ "url": "https://github.com/sponsors/rawify" } }, + "node_modules/framer-motion": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.0.5.tgz", + "integrity": "sha512-Lb0EYbQcSK/pgyQUJm+KzsQrKrJRX9sFRyzl9hSr9gFG4Mk8yP7BjhuxvRXzblOM/+JxycrJdCDVmOQBsjpYlw==", + "dependencies": { + "tslib": "^2.4.0" + }, + "optionalDependencies": { + "@emotion/is-prop-valid": "^0.8.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -9230,11 +9270,17 @@ } }, "node_modules/react-intersection-observer": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-8.34.0.tgz", - "integrity": "sha512-TYKh52Zc0Uptp5/b4N91XydfSGKubEhgZRtcg1rhTKABXijc4Sdr1uTp5lJ8TN27jwUsdXxjHXtHa0kPj704sw==", + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.8.0.tgz", + "integrity": "sha512-wXHvMQUsTagh3X0Z6jDtGkIXc3VVCd2tjDRYR9kII3GKrZr0XF0xtpfdamo2n8BSF+zzfeeBVOTjxZWpBp9X0g==", "peerDependencies": { - "react": "^15.0.0 || ^16.0.0 || ^17.0.0|| ^18.0.0" + "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } } }, "node_modules/react-is": { @@ -9320,6 +9366,14 @@ "react-intersection-observer": "^8.26.2" } }, + "node_modules/react-vertical-timeline-component/node_modules/react-intersection-observer": { + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-8.34.0.tgz", + "integrity": "sha512-TYKh52Zc0Uptp5/b4N91XydfSGKubEhgZRtcg1rhTKABXijc4Sdr1uTp5lJ8TN27jwUsdXxjHXtHa0kPj704sw==", + "peerDependencies": { + "react": "^15.0.0 || ^16.0.0 || ^17.0.0|| ^18.0.0" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", diff --git a/package.json b/package.json index 5b8fd74..262dd52 100644 --- a/package.json +++ b/package.json @@ -33,12 +33,14 @@ "@t3-oss/env-nextjs": "^0.8.0", "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", + "framer-motion": "^11.0.5", "lucide-react": "^0.312.0", "next": "14.1.0", "next-themes": "^0.2.1", "react": "^18", "react-dom": "^18", "react-hook-form": "^7.50.0", + "react-intersection-observer": "^9.8.0", "react-vertical-timeline-component": "^3.6.0", "resend": "^3.2.0", "sonner": "^1.4.0", diff --git a/src/app/page.tsx b/src/app/page.tsx index f7154e7..91b5d7d 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -5,6 +5,8 @@ import { Footer } from '@/components/footer'; import { Header } from '@/components/header'; import { Intro } from '@/components/intro'; import { Projects } from '@/components/projects'; +import { SectionDivider } from '@/components/section-divider'; +import { Skills } from '@/components/skills'; import { ThemeToggle } from '@/components/theme-toggle'; const Home = () => { @@ -13,8 +15,9 @@ const Home = () => {
-
+ + diff --git a/src/components/about.tsx b/src/components/about.tsx index 7b295c9..5dadf19 100644 --- a/src/components/about.tsx +++ b/src/components/about.tsx @@ -1,11 +1,17 @@ -import { Icons } from '@/components/icons'; +'use client'; + +import { motion } from 'framer-motion'; + import { SectionHeading } from '@/components/section-heading'; export const About = () => { return ( -
@@ -26,20 +32,6 @@ export const About = () => { how to play the guitar.

-
- - - - - - - - - - - - -
-
+ ); }; diff --git a/src/components/contact.tsx b/src/components/contact.tsx index 0e11021..6794fde 100644 --- a/src/components/contact.tsx +++ b/src/components/contact.tsx @@ -2,6 +2,7 @@ import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; +import { motion } from 'framer-motion'; import { toast } from 'sonner'; import { z } from 'zod'; @@ -42,7 +43,22 @@ export const Contact = () => { }; return ( -
+ { Submit -
+ ); }; diff --git a/src/components/experience.tsx b/src/components/experience.tsx index 5ed4696..0223c57 100644 --- a/src/components/experience.tsx +++ b/src/components/experience.tsx @@ -3,6 +3,7 @@ import 'react-vertical-timeline-component/style.min.css'; import React from 'react'; +import { useInView } from 'react-intersection-observer'; import { VerticalTimeline, VerticalTimelineElement, @@ -13,6 +14,8 @@ import { SectionHeading } from '@/components/section-heading'; import { experiencesData } from '@/lib/data'; export const Experience = () => { + const { ref, inView } = useInView({ triggerOnce: true }); + return (
{ {experiencesData.map(({ title, description, location, date }) => ( { border: '2px solid hsl(var(--foreground)', }} > -

{title}

+

+ {title} +

{location}

{description} diff --git a/src/components/header.tsx b/src/components/header.tsx index f7376a3..9333de0 100644 --- a/src/components/header.tsx +++ b/src/components/header.tsx @@ -1,6 +1,7 @@ 'use client'; import { useState } from 'react'; +import { motion } from 'framer-motion'; import Link from 'next/link'; import { Button } from '@/components/button'; @@ -19,7 +20,11 @@ export const Header = () => { const [open, setOpen] = useState(false); return ( -

+
+ ); }; diff --git a/src/components/intro.tsx b/src/components/intro.tsx index ee93c99..db2b007 100644 --- a/src/components/intro.tsx +++ b/src/components/intro.tsx @@ -1,3 +1,6 @@ +'use client'; + +import { motion } from 'framer-motion'; import Link from 'next/link'; import { Button } from '@/components/button'; @@ -9,19 +12,46 @@ export const Intro = () => { id="home" className="my-8 flex scroll-mt-96 flex-col items-center gap-4 text-center sm:my-10" > - + 🎉 Check out my new project - -

+ + Software developer with a passion for design -

-

+ + Lorem ipsum dolor sit amet, consectetur adipisicing elit. Adipisci aliquid commodi consequatur culpa, delectus dolore esse, eum laborum nam nihil quaerat quas! -

-
+ + -
+
); }; diff --git a/src/components/project.tsx b/src/components/project.tsx index 435b431..c2bac37 100644 --- a/src/components/project.tsx +++ b/src/components/project.tsx @@ -1,3 +1,6 @@ +'use client'; + +import { motion } from 'framer-motion'; import Image from 'next/image'; import { Button } from '@/components/button'; @@ -6,11 +9,39 @@ import { projectsData } from '@/lib/data'; type TProject = (typeof projectsData)[number]; -export const Project = (project: TProject) => { +type TProps = { + project: TProject; + index: number; +}; + +const fadeInAnimationVariants = { + initial: { + opacity: 0, + y: 100, + }, + animate: (index: number) => ({ + opacity: 1, + y: 0, + transition: { + delay: 0.1 * index, + }, + }), +}; + +export const Project = ({ project, index }: TProps) => { const { image, title, description, technologies, links } = project; return ( -
+
{`${title}
@@ -33,6 +64,6 @@ export const Project = (project: TProject) => { -
+ ); }; diff --git a/src/components/projects.tsx b/src/components/projects.tsx index c1b0374..218b40c 100644 --- a/src/components/projects.tsx +++ b/src/components/projects.tsx @@ -1,3 +1,7 @@ +'use client'; + +import { motion } from 'framer-motion'; + import { Project } from '@/components/project'; import { SectionHeading } from '@/components/section-heading'; import { projectsData } from '@/lib/data'; @@ -5,13 +9,27 @@ import { projectsData } from '@/lib/data'; export const Projects = () => { return (
- + + +
- {projectsData.map((project) => ( - + {projectsData.map((project, index) => ( + ))}
diff --git a/src/components/section-divider.tsx b/src/components/section-divider.tsx new file mode 100644 index 0000000..1503528 --- /dev/null +++ b/src/components/section-divider.tsx @@ -0,0 +1,14 @@ +'use client'; + +import { motion } from 'framer-motion'; + +export const SectionDivider = () => { + return ( + + ); +}; diff --git a/src/components/skills.tsx b/src/components/skills.tsx new file mode 100644 index 0000000..96f2071 --- /dev/null +++ b/src/components/skills.tsx @@ -0,0 +1,40 @@ +'use client'; + +import { motion } from 'framer-motion'; + +import { skillsData } from '@/lib/data'; + +const fadeInAnimationVariants = { + initial: { + opacity: 0, + y: 100, + }, + animate: (index: number) => ({ + opacity: 1, + y: 0, + transition: { + delay: 0.05 * index, + }, + }), +}; + +export const Skills = () => { + return ( +
+ {skillsData.map(({ icon }, index) => ( + + {icon} + + ))} +
+ ); +}; diff --git a/src/lib/data.ts b/src/lib/data.tsx similarity index 75% rename from src/lib/data.ts rename to src/lib/data.tsx index 3487604..a92c113 100644 --- a/src/lib/data.ts +++ b/src/lib/data.tsx @@ -1,3 +1,5 @@ +import { Icons } from '@/components/icons'; + export const links = [ { name: 'Home', @@ -77,3 +79,18 @@ export const experiencesData = [ date: '2021 - present', }, ] as const; + +export const skillsData = [ + { icon: }, + { icon: }, + { icon: }, + { icon: }, + { icon: }, + { icon: }, + { icon: }, + { icon: }, + { icon: }, + { icon: }, + { icon: }, + { icon: }, +] as const;