Skip to content

Commit 534024d

Browse files
committed
UI improvements
1 parent be83303 commit 534024d

9 files changed

Lines changed: 147 additions & 261 deletions

File tree

bun.lock

Lines changed: 88 additions & 195 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,26 @@
1313
"@react-three/drei": "^10.7.7",
1414
"@react-three/fiber": "^9.5.0",
1515
"framer-motion": "^12.38.0",
16-
"lucide-react": "^0.577.0",
16+
"lucide-react": "^1.8.0",
1717
"react": "^19.2.4",
1818
"react-dom": "^19.2.4",
19-
"three": "^0.183.2",
19+
"three": "^0.184.0",
2020
"to-words": "^5.3.0"
2121
},
2222
"devDependencies": {
2323
"@eslint/js": "^10.0.1",
2424
"@types/react": "^19.2.14",
2525
"@types/react-dom": "^19.2.3",
2626
"@types/three": "^0.183.1",
27+
"@tailwindcss/vite": "^4.1.0",
2728
"@vitejs/plugin-react": "^6.0.1",
28-
"autoprefixer": "^10.4.27",
2929
"eslint": "^10.1.0",
3030
"eslint-plugin-react-hooks": "^7.0.1",
3131
"eslint-plugin-react-refresh": "^0.5.2",
3232
"globals": "^17.4.0",
33-
"postcss": "^8.4.35",
34-
"tailwindcss": "^3.4.1",
35-
"typescript": "^5.5.3",
33+
"tailwindcss": "^4.1.0",
34+
"typescript": "^6.0.3",
3635
"typescript-eslint": "^8.3.0",
37-
"vite": "^8.0.1"
36+
"vite": "^8.0.9"
3837
}
3938
}

postcss.config.js

Lines changed: 0 additions & 6 deletions
This file was deleted.

src/components/Hero.tsx

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { useState, useEffect } from "react";
2-
import { Linkedin, FileText, ChevronDown } from "lucide-react";
2+
import { FileText, ChevronDown } from "lucide-react";
33
import { personalInfo } from "../data/personalInfo";
44
import GitHubIcon from "./icons/GitHub";
5+
import LinkedInIcon from "./icons/LinkedInIcon";
56

67
const Hero = () => {
78
const [typedText, setTypedText] = useState("");
@@ -27,7 +28,7 @@ const Hero = () => {
2728
if (typedText.length === 0) {
2829
setIsDeleting(false);
2930
setCurrentTextIndex(
30-
(currentTextIndex + 1) % personalInfo.roles.length
31+
(currentTextIndex + 1) % personalInfo.roles.length,
3132
);
3233
}
3334
}
@@ -38,7 +39,7 @@ const Hero = () => {
3839

3940
const handleNavClick = (
4041
e: React.MouseEvent<HTMLAnchorElement>,
41-
href: string
42+
href: string,
4243
) => {
4344
e.preventDefault();
4445
const element = document.querySelector(href);
@@ -55,34 +56,34 @@ const Hero = () => {
5556
>
5657
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
5758
<div className="flex flex-col items-center text-center">
58-
<div className="w-48 h-48 md:w-56 md:h-56 rounded-full overflow-hidden border-4 border-white dark:border-gray-800 shadow-xl mb-8">
59+
<div className="w-36 h-36 sm:w-48 sm:h-48 md:w-56 md:h-56 rounded-full overflow-hidden border-4 border-white dark:border-gray-800 shadow-xl mb-6 sm:mb-8">
5960
<img
6061
src={personalInfo.avatar}
6162
alt={personalInfo.name}
6263
className="w-full h-full object-cover"
6364
/>
6465
</div>
6566

66-
<h1 className="text-4xl md:text-5xl lg:text-6xl font-bold text-gray-900 dark:text-white mb-4">
67+
<h1 className="text-3xl sm:text-4xl md:text-5xl lg:text-6xl font-bold leading-tight text-gray-900 dark:text-white mb-3 sm:mb-4">
6768
Hello, I'm{" "}
6869
<span className="bg-gradient-to-r from-blue-600 to-teal-500 bg-clip-text text-transparent">
6970
{personalInfo.name}
7071
</span>
7172
</h1>
7273

73-
<div className="h-8 md:h-10 mb-6">
74-
<h2 className="text-xl md:text-2xl lg:text-3xl font-medium text-gray-700 dark:text-gray-300">
74+
<div className="h-8 md:h-10 mb-4 sm:mb-6">
75+
<h2 className="text-lg sm:text-xl md:text-2xl lg:text-3xl font-medium text-gray-700 dark:text-gray-300">
7576
{typedText}
7677
<span className="animate-blink">|</span>
7778
</h2>
7879
</div>
7980

80-
<p className="max-w-2xl text-lg text-gray-600 dark:text-gray-400 mb-10">
81+
<p className="max-w-2xl text-base sm:text-lg text-gray-600 dark:text-gray-400 mb-8 sm:mb-10">
8182
I enjoy seeking out creative solutions to complex problems and
8283
building things that empower others to do the same.
8384
</p>
8485

85-
<div className="flex flex-wrap justify-center gap-4 mb-12">
86+
<div className="flex flex-wrap justify-center gap-3 sm:gap-4 mb-8 sm:mb-12">
8687
<a
8788
href="#contact"
8889
onClick={(e) => handleNavClick(e, "#contact")}
@@ -99,7 +100,7 @@ const Hero = () => {
99100
</a>
100101
</div>
101102

102-
<div className="flex space-x-6 mb-12">
103+
<div className="flex space-x-6 mb-8 sm:mb-12">
103104
{personalInfo.socials.map((social) => (
104105
<a
105106
key={social.platform}
@@ -110,7 +111,7 @@ const Hero = () => {
110111
aria-label={`${social.platform} Profile`}
111112
>
112113
{social.platform === "GitHub" && <GitHubIcon size={24} />}
113-
{social.platform === "LinkedIn" && <Linkedin size={24} />}
114+
{social.platform === "LinkedIn" && <LinkedInIcon size={24} />}
114115
{social.platform === "Resume" && <FileText size={24} />}
115116
</a>
116117
))}

src/components/Navbar.tsx

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,31 @@
1-
import { useState, useEffect } from "react";
1+
import { useState, useEffect, useRef } from "react";
22
import { Menu, X, Moon, Sun } from "lucide-react";
33
import { useTheme } from "../context/ThemeContext";
44
import { personalInfo } from "../data/personalInfo";
55

66
const Navbar = () => {
77
const [isOpen, setIsOpen] = useState(false);
88
const [scrolled, setScrolled] = useState(false);
9+
const [hidden, setHidden] = useState(false);
10+
const lastScrollY = useRef(0);
911
const { isDarkMode, toggleTheme } = useTheme();
1012

1113
useEffect(() => {
1214
const handleScroll = () => {
13-
if (window.scrollY > 50) {
14-
setScrolled(true);
15-
} else {
16-
setScrolled(false);
15+
const y = window.scrollY;
16+
setScrolled(y > 50);
17+
const delta = y - lastScrollY.current;
18+
// Ignore tiny jitter from momentum / rubber-banding on mobile.
19+
if (Math.abs(delta) < 6) return;
20+
if (y > 80 && delta > 0) {
21+
setHidden(true);
22+
} else if (delta < 0) {
23+
setHidden(false);
1724
}
25+
lastScrollY.current = y;
1826
};
1927

20-
window.addEventListener("scroll", handleScroll);
28+
window.addEventListener("scroll", handleScroll, { passive: true });
2129
return () => window.removeEventListener("scroll", handleScroll);
2230
}, []);
2331

@@ -48,6 +56,8 @@ const Navbar = () => {
4856
return (
4957
<nav
5058
className={`fixed w-full z-50 transition-all duration-300 ${
59+
hidden && !isOpen ? "-translate-y-full" : "translate-y-0"
60+
} ${
5161
scrolled
5262
? "bg-white/90 dark:bg-gray-900/90 backdrop-blur-md shadow-md py-2"
5363
: "bg-transparent py-4"

src/components/icons/SocialIcon.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from "react";
2-
import { Linkedin } from "lucide-react";
32
import GitHubIcon from "./GitHub";
43
import TwitterIcon from "./TwitterIcon";
4+
import LinkedInIcon from "./LinkedInIcon";
55

66
interface SocialIconProps {
77
platform: string;
@@ -13,7 +13,7 @@ const SocialIcon: React.FC<SocialIconProps> = ({ platform, size = 20 }) => {
1313
case "GitHub":
1414
return <GitHubIcon size={size} />;
1515
case "LinkedIn":
16-
return <Linkedin size={size} />;
16+
return <LinkedInIcon size={size} />;
1717
case "Twitter":
1818
return <TwitterIcon size={size} />;
1919
default:

src/index.css

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,39 @@
1-
@tailwind base;
2-
@tailwind components;
3-
@tailwind utilities;
1+
@import "tailwindcss";
2+
3+
@custom-variant dark (&:where(.dark, .dark *));
4+
5+
@theme {
6+
--font-sans: Inter, ui-sans-serif, system-ui, sans-serif;
7+
8+
--animate-blink: blink 1s step-end infinite;
9+
--animate-sparkle: sparkle 1s forwards;
10+
11+
@keyframes blink {
12+
0%, 100% { opacity: 1; }
13+
50% { opacity: 0; }
14+
}
15+
16+
@keyframes sparkle {
17+
0% { transform: translate(-50%, -50%) scale(0); opacity: 1; }
18+
100% { transform: translate(-50%, -50%) scale(1); opacity: 0; }
19+
}
20+
}
421

522
html, body {
623
margin: 0;
724
padding: 0;
825
width: 100%;
9-
height: 100%;
1026
overflow-x: hidden;
1127
scroll-behavior: smooth;
1228
}
1329

1430
body {
1531
min-height: 100vh;
1632
position: relative;
17-
overflow-y: auto;
1833
}
1934

2035
#root {
2136
min-height: 100vh;
2237
display: flex;
2338
flex-direction: column;
24-
}
39+
}

tailwind.config.js

Lines changed: 0 additions & 27 deletions
This file was deleted.

vite.config.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { defineConfig } from 'vite';
22
import react from '@vitejs/plugin-react';
3+
import tailwindcss from '@tailwindcss/vite';
34

45
// https://vitejs.dev/config/
56
export default defineConfig({
6-
plugins: [react()],
7+
plugins: [react(), tailwindcss()],
78
optimizeDeps: {
89
exclude: ['lucide-react'],
910
},

0 commit comments

Comments
 (0)