diff --git a/bun.lockb b/bun.lockb index f0faeab..76bd8fb 100644 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 82ec4c1..6ab3ae2 100644 --- a/package.json +++ b/package.json @@ -18,9 +18,10 @@ "@radix-ui/react-tooltip": "^1.1.3", "@sanity/image-url": "^1.1.0", "@sanity/vision": "3", + "@studio-freight/lenis": "^1.0.42", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", - "framer-motion": "^11.11.11", + "framer-motion": "^11.11.13", "lucide-react": "^0.453.0", "next": "15.0.1", "next-sanity": "^9.8.8", diff --git a/src/app/(root)/page.tsx b/src/app/(root)/page.tsx index 54942d6..4f2ddfe 100644 --- a/src/app/(root)/page.tsx +++ b/src/app/(root)/page.tsx @@ -15,21 +15,25 @@ const info: InfoCardsProps[] = [ description: "Who am I? What do I do?", image: "/about.png", className: "pb-8", + href: "/about", }, { - title: "Notebook", + title: "Blogs", description: "My thoughts and ideas", image: "/notebook.png", + href: "/notebook", }, { title: "Bookshelf", description: "Books and pieces of wisdom I’ve enjoyed reading", image: "/bookshelf.png", + href: "/bookshelf", }, { title: "Tech Stack", description: "The dev tools, apps, devices, and games I use and play.", image: "/stack.png", + href: "/uses", }, ]; diff --git a/src/app/(root)/work/page.tsx b/src/app/(root)/work/page.tsx index adc2f4a..c934e04 100644 --- a/src/app/(root)/work/page.tsx +++ b/src/app/(root)/work/page.tsx @@ -22,8 +22,8 @@ const WorkPage = () => { /> - - + + Want to see more? I have more projects on my{" "} diff --git a/src/app/globals.css b/src/app/globals.css index c575162..29983bb 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -90,3 +90,19 @@ body { .bg-gradient { background: linear-gradient(180deg, #1a1a1a, #131313); } + +::-webkit-scrollbar { + @apply w-1.5 +} + +::-webkit-scrollbar-track { + @apply bg-accent rounded-full +} + +::-webkit-scrollbar-thumb { + @apply dark:bg-gray-400/30 bg-onyx/50 rounded-full +} + +::-webkit-scrollbar-thumb:hover { + background: #c0a0b9; +} \ No newline at end of file diff --git a/src/app/not-found.tsx b/src/app/not-found.tsx index 2dc523a..1f83b54 100644 --- a/src/app/not-found.tsx +++ b/src/app/not-found.tsx @@ -1,11 +1,31 @@ "use client"; -import HeaderGradient from "@/components/common/header-gradient"; -import { ThemeProvider } from "@/components/theme/theme-provider"; import clsx from "clsx"; +import { motion } from "framer-motion"; +import { ArrowLeft } from "lucide-react"; import Link from "next/link"; +import HeaderGradient from "@/components/common/header-gradient"; +import { ThemeProvider } from "@/components/theme/theme-provider"; + +const pageData = [ + { + title: "Oops! Looks like this page is on a coffee break.", + describe: "Don't worry, even the best developers get lost sometimes.", + footer: + "Error: 404 | Page Not Found | Stack Trace: Just kidding, we don't do that here.", + }, + { + title: "Oops! This page seems to have a bug :(", + describe: + "Don't worry, even the best developers encounter unexpected errors.", + footer: "Error: 404 | Page Not Found | Git blame: Probably the intern", + }, +]; + export default function Page404() { + const randomData = pageData[Math.floor(Math.random() * pageData.length)]; + return ( -

- 404 | Oops seems like a wrong page -

- - Go home - + +

404

+

{randomData.title}

+

{randomData.describe}

+ + + + Go Home + + +
+ +

{randomData.footer}

+
); diff --git a/src/components/common/header.tsx b/src/components/common/header.tsx index 3a605be..4173e89 100644 --- a/src/components/common/header.tsx +++ b/src/components/common/header.tsx @@ -1,12 +1,21 @@ -import { navLinks, socials } from "@/lib/constants"; +"use client" + import Link from "next/link"; +import { motion } from "framer-motion"; + +import { navLinks, socials } from "@/lib/constants"; import Logo from "./logo"; import MobileNav from "./mobile-nav"; const Header = () => { return ( <> -
+
@@ -50,7 +59,7 @@ const Header = () => {
-
+ { return ( -
+
@@ -49,7 +56,7 @@ const MobileNav = () => {
-
+ ); }; diff --git a/src/components/contact/contact-form.tsx b/src/components/contact/contact-form.tsx index 6fedca7..542d4dc 100644 --- a/src/components/contact/contact-form.tsx +++ b/src/components/contact/contact-form.tsx @@ -1,6 +1,7 @@ import { zodResolver } from "@hookform/resolvers/zod"; import { useForm } from "react-hook-form"; import { z } from "zod"; +import { motion } from "framer-motion"; import { Button } from "@/components/ui/button"; import { @@ -34,10 +35,10 @@ const ContactForm = ({ setSuccess }: ContactFormProps) => { const form = useForm>({ resolver: zodResolver(formSchema), defaultValues: { - name: "Vignesh", - email: "vighneshgupta32@gmail.com", - subject: "Test", - message: "Testing the form", + name: "", + email: "", + subject: "", + message: "", }, }); @@ -69,7 +70,12 @@ const ContactForm = ({ setSuccess }: ContactFormProps) => { } return ( -
+
@@ -179,7 +185,7 @@ const ContactForm = ({ setSuccess }: ContactFormProps) => { -
+ ); }; diff --git a/src/components/hero/hero-section.tsx b/src/components/hero/hero-section.tsx index b15d9bc..a02a7ca 100644 --- a/src/components/hero/hero-section.tsx +++ b/src/components/hero/hero-section.tsx @@ -1,24 +1,36 @@ import Link from "next/link"; import HeroImage from "./hero-image"; +import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip"; +import { calculateYearsFromNov2021 } from "@/lib/utils"; const HeroSection = () => { return ( -
+
- - Hey there 👋 + + Hey there 👋!

I'm Vignesh Gupta

-

- A Self-taught Developer, functioning in the industry for 2+ years now. - I'm a passionate learner who's always willing to learn and - work across technologies and domains. I love to explore new - technologies and leverage them to solve real-life problems. -

+
+ A Self-taught Developer, functioning in the industry for + + + {calculateYearsFromNov2021()} years. + + + Since Nov 2021 + + + + I'm a passionate learner who's always willing to learn and + work across technologies and domains. I love to explore new + technologies and leverage them to solve real-life problems. + +
{ return ( - - {title} - {description} - {title} - + + + {title} + {description} + {title} + + ); }; diff --git a/src/components/page/page-container.tsx b/src/components/page/page-container.tsx index b3f8712..498f61f 100644 --- a/src/components/page/page-container.tsx +++ b/src/components/page/page-container.tsx @@ -6,7 +6,7 @@ const PageContainer = ({ className, }: PropsWithChildren<{ className?: string }>) => { return ( -
+
{children}
); diff --git a/src/components/project/project-card.tsx b/src/components/project/project-card.tsx index bb6ffb3..891023d 100644 --- a/src/components/project/project-card.tsx +++ b/src/components/project/project-card.tsx @@ -1,3 +1,7 @@ +"use client"; + +import { useTransform, useScroll, motion, MotionValue } from "framer-motion"; +import { useRef } from "react"; import { MoveRightIcon } from "lucide-react"; import Image from "next/image"; import Link from "next/link"; @@ -12,6 +16,10 @@ type ProjectCardProps = { image: SanityImageSource; projectUrl: string; icon: SanityImageSource | null; + position: number; + progress: MotionValue; + range: number[]; + targetScale: number; }; const ProjectCard = ({ @@ -20,47 +28,76 @@ const ProjectCard = ({ projectUrl, title, icon, + position, + progress, + range, + targetScale, }: ProjectCardProps) => { + const container = useRef(null); + + const { scrollYProgress } = useScroll({ + target: container, + + offset: ["start end", "start start"], + }); + + const imageScale = useTransform(scrollYProgress, [0, 1], [1.4, 1]); + const scale = useTransform(progress, range, [1, targetScale]); + return ( - -
- {icon ? ( - Project Name - ) : null} - {title} - - {description} - + + +
+ {icon ? ( + Project Name + ) : null} + {title} + + {description} + - - View Project{" "} - - -
+ + View Project{" "} + + +
-
- Project Image -
-
+
+ + Project Image + +
+ + ); }; diff --git a/src/components/project/project-list.tsx b/src/components/project/project-list.tsx new file mode 100644 index 0000000..ae469f7 --- /dev/null +++ b/src/components/project/project-list.tsx @@ -0,0 +1,58 @@ +"use client"; + +import { useScroll } from "framer-motion"; +import { useRef } from "react"; +import { + FEATURED_PROJECTS_QUERYResult, + PROJECTS_QUERYResult, +} from "../../../sanity.types"; +import ProjectCard from "./project-card"; + +type ProjectListProps = { + projects: FEATURED_PROJECTS_QUERYResult | PROJECTS_QUERYResult; +}; + +const ProjectList = ({ projects }: ProjectListProps) => { + const container = useRef(null); + + const { scrollYProgress } = useScroll({ + target: container, + + offset: ["start start", "end end"], + }); + + return ( +
+ {projects.map( + ( + { _id, codeLink, description, imgUrl, projectLink, title, icon }, + idx + ) => { + const targetScale = 1 - (projects.length - idx) * 0.05; + + return _id && + codeLink && + description && + imgUrl && + projectLink && + title ? ( + + ) : null; + } + )} +
+ ); +}; + +export default ProjectList; diff --git a/src/components/project/project-section.tsx b/src/components/project/project-section.tsx index bd8e0bc..a6874d0 100644 --- a/src/components/project/project-section.tsx +++ b/src/components/project/project-section.tsx @@ -1,6 +1,6 @@ import { sanityFetch } from "@/sanity/lib/live"; -import ProjectCard from "./project-card"; import { FEATURED_PROJECTS_QUERY, PROJECTS_QUERY } from "@/sanity/lib/queries"; +import ProjectList from "./project-list"; type ProjectSectionProps = { showHeader?: boolean; @@ -20,21 +20,7 @@ const ProjectSection = async ({ {showHeader && (

Selected Work

)} -
- {projects.map( - ({ _id, codeLink, description, imgUrl, projectLink, title, icon }) => - _id && codeLink && description && imgUrl && projectLink && title ? ( - - ) : null - )} -
+
); }; diff --git a/src/lib/utils.ts b/src/lib/utils.ts index bd0c391..d190e9d 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -1,6 +1,18 @@ -import { clsx, type ClassValue } from "clsx" -import { twMerge } from "tailwind-merge" +import { clsx, type ClassValue } from "clsx"; +import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)) + return twMerge(clsx(inputs)); } + +export const calculateYearsFromNov2021 = () => { + const startDate = new Date("2021-11-01"); + const currentDate = new Date(); + const diff = currentDate.getTime() - startDate.getTime(); + + const years = diff / (1000 * 60 * 60 * 24 * 365); + + return Math.floor(years) < years + ? Math.floor(years) + "+" + : Math.floor(years).toString(); +}; diff --git a/tailwind.config.ts b/tailwind.config.ts index 8157458..55188e9 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,63 +1,79 @@ import type { Config } from "tailwindcss"; const config: Config = { - darkMode: ["class"], - content: [ + darkMode: ["class"], + content: [ "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", "./src/components/**/*.{js,ts,jsx,tsx,mdx}", "./src/app/**/*.{js,ts,jsx,tsx,mdx}", ], theme: { - extend: { - colors: { - background: 'hsl(var(--background))', - foreground: 'hsl(var(--foreground))', - onyx: "#181818", - card: { - DEFAULT: 'hsl(var(--card))', - foreground: 'hsl(var(--card-foreground))' - }, - popover: { - DEFAULT: 'hsl(var(--popover))', - foreground: 'hsl(var(--popover-foreground))' - }, - primary: { - DEFAULT: 'hsl(var(--primary))', - foreground: 'hsl(var(--primary-foreground))' - }, - secondary: { - DEFAULT: 'hsl(var(--secondary))', - foreground: 'hsl(var(--secondary-foreground))' - }, - muted: { - DEFAULT: 'hsl(var(--muted))', - foreground: 'hsl(var(--muted-foreground))' - }, - accent: { - DEFAULT: 'hsl(var(--accent))', - foreground: 'hsl(var(--accent-foreground))' - }, - destructive: { - DEFAULT: 'hsl(var(--destructive))', - foreground: 'hsl(var(--destructive-foreground))' - }, - border: 'hsl(var(--border))', - input: 'hsl(var(--input))', - ring: 'hsl(var(--ring))', - chart: { - '1': 'hsl(var(--chart-1))', - '2': 'hsl(var(--chart-2))', - '3': 'hsl(var(--chart-3))', - '4': 'hsl(var(--chart-4))', - '5': 'hsl(var(--chart-5))' - } - }, - borderRadius: { - lg: 'var(--radius)', - md: 'calc(var(--radius) - 2px)', - sm: 'calc(var(--radius) - 4px)' - } - }, + extend: { + colors: { + background: "hsl(var(--background))", + foreground: "hsl(var(--foreground))", + onyx: "#181818", + card: { + DEFAULT: "hsl(var(--card))", + foreground: "hsl(var(--card-foreground))", + }, + popover: { + DEFAULT: "hsl(var(--popover))", + foreground: "hsl(var(--popover-foreground))", + }, + primary: { + DEFAULT: "hsl(var(--primary))", + foreground: "hsl(var(--primary-foreground))", + }, + secondary: { + DEFAULT: "hsl(var(--secondary))", + foreground: "hsl(var(--secondary-foreground))", + }, + muted: { + DEFAULT: "hsl(var(--muted))", + foreground: "hsl(var(--muted-foreground))", + }, + accent: { + DEFAULT: "hsl(var(--accent))", + foreground: "hsl(var(--accent-foreground))", + }, + destructive: { + DEFAULT: "hsl(var(--destructive))", + foreground: "hsl(var(--destructive-foreground))", + }, + border: "hsl(var(--border))", + input: "hsl(var(--input))", + ring: "hsl(var(--ring))", + chart: { + "1": "hsl(var(--chart-1))", + "2": "hsl(var(--chart-2))", + "3": "hsl(var(--chart-3))", + "4": "hsl(var(--chart-4))", + "5": "hsl(var(--chart-5))", + }, + }, + borderRadius: { + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)", + }, + keyframes: { + "fade-in": { + from: { opacity: "0" }, + to: { opacity: "1" }, + }, + wave: { + "0%, 100%": { transform: "rotate(0deg)" }, + "20%, 60%": { transform: "rotate(-25deg)" }, + "40%, 80%": { transform: "rotate(10deg)" }, + }, + + }, + animation: { + "fade-in": "fade-in 0.5s ease-in-out", + wave: "wave 0.5s infinite", + }, + }, }, // eslint-disable-next-line @typescript-eslint/no-require-imports plugins: [require("tailwindcss-animate")],