diff --git a/package-lock.json b/package-lock.json
index fd4da92..055a8ea 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,11 +10,13 @@
"license": "MIT",
"dependencies": {
"@emailjs/browser": "^4.3.3",
+ "clsx": "^2.1.1",
"framer-motion": "^11.1.9",
"next": "14.2.3",
"react": "^18",
"react-dom": "^18",
- "react-icons": "^5.2.1"
+ "react-icons": "^5.2.1",
+ "tailwind-merge": "^2.3.0"
},
"devDependencies": {
"@types/node": "^20",
@@ -46,7 +48,6 @@
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.5.tgz",
"integrity": "sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==",
- "dev": true,
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
@@ -1119,6 +1120,15 @@
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
},
+ "node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -3833,8 +3843,7 @@
"node_modules/regenerator-runtime": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
- "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
- "dev": true
+ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
},
"node_modules/regexp.prototype.flags": {
"version": "1.5.2",
@@ -4374,6 +4383,19 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/tailwind-merge": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.3.0.tgz",
+ "integrity": "sha512-vkYrLpIP+lgR0tQCG6AP7zZXCTLc1Lnv/CCRT3BqJ9CZ3ui2++GPaGb1x/ILsINIMSYqqvrpqjUFsMNLlW99EA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.24.1"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/dcastil"
+ }
+ },
"node_modules/tailwindcss": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz",
diff --git a/package.json b/package.json
index f075cbe..565728f 100644
--- a/package.json
+++ b/package.json
@@ -21,11 +21,13 @@
},
"dependencies": {
"@emailjs/browser": "^4.3.3",
+ "clsx": "^2.1.1",
"framer-motion": "^11.1.9",
"next": "14.2.3",
"react": "^18",
"react-dom": "^18",
- "react-icons": "^5.2.1"
+ "react-icons": "^5.2.1",
+ "tailwind-merge": "^2.3.0"
},
"devDependencies": {
"@types/node": "^20",
diff --git a/public/thumbnail.png b/public/thumbnail.png
index dfd344f..5f5b4e4 100644
Binary files a/public/thumbnail.png and b/public/thumbnail.png differ
diff --git a/public/ui/fonts/manrope.ttf b/public/ui/fonts/manrope.ttf
deleted file mode 100644
index f39ca39..0000000
Binary files a/public/ui/fonts/manrope.ttf and /dev/null differ
diff --git a/src/app/globals.css b/src/app/globals.css
index 1203f1a..faa1541 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -28,11 +28,6 @@
src: url(/ui/fonts/fezeline.otf) format("opentype");
}
- @font-face {
- font-family: --font-manrope;
- font-weight: 500;
- src: url(/ui/fonts/manrope.ttf) format("truetype");
- }
@font-face {
font-family: --font-nasalization;
font-weight: 500;
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 23d8d3d..4d561b3 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,6 +1,10 @@
import type { Metadata } from "next";
import "./globals.css";
+import { Inter } from "next/font/google";
+
+const inter = Inter({ subsets: ["latin"] });
+
export const metadata: Metadata = {
title: "Aarab Nishchal",
description:
@@ -19,6 +23,7 @@ export const metadata: Metadata = {
"Nishchal",
"aarabii",
"aarab",
+ "caya",
"portfolio",
"developer",
"web developer",
@@ -61,7 +66,7 @@ export default function RootLayout({
}>) {
return (
-
{children}
+ {children}
);
}
diff --git a/src/components/About.tsx b/src/components/About.tsx
index 282030f..6dfd3c1 100644
--- a/src/components/About.tsx
+++ b/src/components/About.tsx
@@ -6,6 +6,7 @@ import { toBase64, convertImage } from "@/util/BlurData";
import data from "@/constants/details.json";
import { Title } from "./common/Title";
+import { TextGenerateEffect } from "./ui/TextGenerateEffect";
export const About = () => {
return (
@@ -50,7 +51,7 @@ export const About = () => {
>
diff --git a/src/components/Hero.tsx b/src/components/Hero.tsx
index 4de8ed4..bf89ff5 100644
--- a/src/components/Hero.tsx
+++ b/src/components/Hero.tsx
@@ -5,6 +5,8 @@ import { Button } from "./common/Button";
import data from "@/constants/details.json";
import { useScreenSize } from "@/util/hook/useScreenSize";
+import { Meteors } from "./ui/Meteors";
+import { TextGenerateEffect } from "./ui/TextGenerateEffect";
const container = (delay: number) => ({
hidden: { x: -100, opacity: 0 },
@@ -43,7 +45,7 @@ export const Hero = () => {
animate="visible"
className="w-full lg:w-1/2 font-light text-sm lg:text-xl tracking-wider leading-relaxed"
>
- {data.bio}
+
+
);
diff --git a/src/components/common/ContactList.tsx b/src/components/common/ContactList.tsx
index 83e274e..81e54cf 100644
--- a/src/components/common/ContactList.tsx
+++ b/src/components/common/ContactList.tsx
@@ -30,9 +30,9 @@ export const ContactList: FC = ({
rel="noopener noreferrer"
className="flex items-center"
>
- {icon}
+ {icon}
- {text}
+ {text}
);
diff --git a/src/components/common/ProjectCard.tsx b/src/components/common/ProjectCard.tsx
index 9633282..b7c585c 100644
--- a/src/components/common/ProjectCard.tsx
+++ b/src/components/common/ProjectCard.tsx
@@ -1,10 +1,9 @@
import { FC } from "react";
import Link from "next/link";
-
import { motion } from "framer-motion";
-
import { TechClip } from "./TechClip";
import { FiExternalLink, FiGithub } from "react-icons/fi";
+import { Meteors } from "../ui/Meteors"; // Make sure this import is correct according to your project structure
interface ProjectCardProps {
title: string;
@@ -23,40 +22,39 @@ export const ProjectCard: FC = ({
}) => {
return (
-
-
- {title}
-
-
-
-
-
-
-
-
+
+
+
+
+ {title}
+
+
+
+
+
+
+
+
+
+
{desc}
+
+ {tech.map((tech, index) => (
+
+ ))}
+
-
-
{desc}
-
- {tech.map((tech, index) => (
-
- ))}
-
-
+
+
);
};
diff --git a/src/components/common/TechClip.tsx b/src/components/common/TechClip.tsx
index 9118392..1c4555b 100644
--- a/src/components/common/TechClip.tsx
+++ b/src/components/common/TechClip.tsx
@@ -1,4 +1,5 @@
import { FC } from "react";
+import { motion } from "framer-motion";
interface TechClipProps {
name: string;
@@ -7,11 +8,13 @@ interface TechClipProps {
export const TechClip: FC
= ({ keyValue, name }) => {
return (
-
- {name}
-
+ {name}
+
);
};
diff --git a/src/components/common/Title.tsx b/src/components/common/Title.tsx
index e7a994e..da1bd4b 100644
--- a/src/components/common/Title.tsx
+++ b/src/components/common/Title.tsx
@@ -1,4 +1,4 @@
-import { FC } from "react";
+import { FC, Fragment } from "react";
import { motion } from "framer-motion";
interface TitleProps {
@@ -8,17 +8,19 @@ interface TitleProps {
export const Title: FC = ({ title, subTitle }) => {
return (
-
- {title}
- {subTitle && Me}
-
+
+
+ {title}
+ {subTitle && Me}
+
+
);
};
diff --git a/src/components/ui/Meteors.tsx b/src/components/ui/Meteors.tsx
new file mode 100644
index 0000000..2b05533
--- /dev/null
+++ b/src/components/ui/Meteors.tsx
@@ -0,0 +1,32 @@
+import { cn } from "@/util/cn";
+import React from "react";
+
+export const Meteors = ({
+ number,
+ className,
+}: {
+ number?: number;
+ className?: string;
+}) => {
+ const meteors = new Array(number || 20).fill(true);
+ return (
+ <>
+ {meteors.map((el, idx) => (
+
+ ))}
+ >
+ );
+};
diff --git a/src/components/ui/TextGenerateEffect.tsx b/src/components/ui/TextGenerateEffect.tsx
new file mode 100644
index 0000000..8867283
--- /dev/null
+++ b/src/components/ui/TextGenerateEffect.tsx
@@ -0,0 +1,48 @@
+"use client";
+import { useEffect } from "react";
+import { motion, stagger, useAnimate } from "framer-motion";
+import { cn } from "@/util/cn";
+
+export const TextGenerateEffect = ({
+ words,
+ className,
+}: {
+ words: string;
+ className?: string;
+}) => {
+ const [scope, animate] = useAnimate();
+ let wordsArray = words.split(" ");
+ useEffect(() => {
+ animate(
+ "span",
+ {
+ opacity: 1,
+ },
+ {
+ duration: 2,
+ delay: stagger(0.2),
+ }
+ );
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [scope.current]);
+
+ const renderWords = () => {
+ return (
+
+ {wordsArray.map((word, idx) => {
+ return (
+
+ {word}{" "}
+
+ );
+ })}
+
+ );
+ };
+
+ return (
+
+ );
+};
diff --git a/src/util/cn.ts b/src/util/cn.ts
new file mode 100644
index 0000000..cec6ac9
--- /dev/null
+++ b/src/util/cn.ts
@@ -0,0 +1,6 @@
+import { ClassValue, clsx } from "clsx";
+import { twMerge } from "tailwind-merge";
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs));
+}
diff --git a/tailwind.config.ts b/tailwind.config.ts
index 931fc99..b0ecbb8 100644
--- a/tailwind.config.ts
+++ b/tailwind.config.ts
@@ -21,6 +21,28 @@ const config: Config = {
nasalization: ["--font-nasalization"],
manrope: ["--font-manrope"],
},
+ animation: {
+ "meteor-effect": "meteor 5s linear infinite",
+ shimmer: "shimmer 2s linear infinite",
+ },
+ keyframes: {
+ meteor: {
+ "0%": { transform: "rotate(215deg) translateX(0)", opacity: "1" },
+ "70%": { opacity: "1" },
+ "100%": {
+ transform: "rotate(215deg) translateX(-500px)",
+ opacity: "0",
+ },
+ },
+ shimmer: {
+ from: {
+ backgroundPosition: "0 0",
+ },
+ to: {
+ backgroundPosition: "-200% 0",
+ },
+ },
+ },
},
},
plugins: [],