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 = () => { >

- {data.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 ( +
+
{renderWords()}
+
+ ); +}; 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: [],