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 (
-
+
);
};
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 (
-
+
@@ -64,6 +69,6 @@ export const Header = () => {
))}
-
+
);
};
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!
-
-
+
+
Get in touch
@@ -47,7 +77,7 @@ export const Intro = () => {
-
+
);
};
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 (
-
+
@@ -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;