@@ -10,40 +10,48 @@ import {
1010 FaLaptopCode ,
1111} from "react-icons/fa6" ;
1212import { IoLogoJavascript } from "react-icons/io5" ;
13- import { RiNextjsFill } from "react-icons/ri" ;
13+ import { RiNextjsFill , RiTailwindCssFill } from "react-icons/ri" ;
1414import { GiChessKing } from "react-icons/gi" ;
1515import { TbBrandRedux } from "react-icons/tb" ;
1616import { SiTypescript } from "react-icons/si" ;
17- import { RiTailwindCssFill } from "react-icons/ri" ;
17+ import GalaxyBackground from "./GalaxyBackgroundParallax" ; // <- our new galaxy background
1818
19+ // ===============================
20+ // Bio Component
21+ // ===============================
1922export default function Bio ( ) {
20- // List of skills with icons
23+ // ===== Skills Array =====
24+ // Each skill has a name and an icon component with optional color
2125 const skills = [
2226 { name : "HTML" , icon : < FaHtml5 className = "text-orange-400" /> } ,
2327 { name : "CSS" , icon : < FaCss3Alt className = "text-blue-500" /> } ,
2428 { name : "JavaScript" , icon : < IoLogoJavascript className = "text-amber-300" /> } ,
2529 { name : "React" , icon : < FaReact className = "text-blue-900" /> } ,
26- { name : "Next" , icon : < RiNextjsFill /> } ,
30+ { name : "Next.js " , icon : < RiNextjsFill /> } ,
2731 { name : "TypeScript" , icon : < SiTypescript className = "text-blue-500" /> } ,
2832 { name : "Zustand" , icon : < TbBrandRedux className = "text-purple-600" /> } ,
2933 { name : "Tailwind" , icon : < RiTailwindCssFill className = "text-blue-500" /> } ,
3034 ] ;
3135
32- // Mounted check for client-only rendering
36+ // ===== Mounted State =====
37+ // Used to ensure animations and motion values only run on the client
3338 const [ mounted , setMounted ] = useState ( false ) ;
3439 useEffect ( ( ) => setMounted ( true ) , [ ] ) ;
3540
36- // Motion values for parallax tilt effect
41+ // ===== Mouse Tilt Animation =====
42+ // motionX & motionY track mouse movement
3743 const motionX = useMotionValue ( 0 ) ;
3844 const motionY = useMotionValue ( 0 ) ;
45+ // rotateY & rotateX transform motion values into rotation degrees
3946 const rotateY = useTransform ( motionX , ( val ) => val ) ;
4047 const rotateX = useTransform ( motionY , ( val ) => - val ) ;
4148
42- // Track mouse position to update tilt
49+ // ===== Mouse Move Effect =====
50+ // Moves the profile image slightly based on mouse position
4351 useEffect ( ( ) => {
4452 if ( ! mounted ) return ;
4553 const handleMouseMove = ( e : MouseEvent ) => {
46- const x = ( e . clientX / window . innerWidth - 0.5 ) * 30 ;
54+ const x = ( e . clientX / window . innerWidth - 0.5 ) * 30 ; // Rotate up to 15 degrees
4755 const y = ( e . clientY / window . innerHeight - 0.5 ) * 30 ;
4856 motionX . set ( x ) ;
4957 motionY . set ( y ) ;
@@ -52,59 +60,51 @@ export default function Bio() {
5260 return ( ) => window . removeEventListener ( "mousemove" , handleMouseMove ) ;
5361 } , [ mounted , motionX , motionY ] ) ;
5462
55- // Generate floating particles once on client
56- const [ particles , setParticles ] = useState < { top : number ; left : number } [ ] > ( [ ] ) ;
57- useEffect ( ( ) => {
58- if ( ! mounted ) return ;
59- setParticles (
60- Array . from ( { length : 40 } ) . map ( ( ) => ( {
61- top : Math . random ( ) * 100 ,
62- left : Math . random ( ) * 100 ,
63- } ) )
64- ) ;
65- } , [ mounted ] ) ;
66-
6763 return (
6864 < div id = "about" className = "relative min-h-screen font-bricolage overflow-hidden" >
69- { /* Animated background gradient */ }
70- < div className = "absolute inset-0 -z-10 animate-bgGradient" > </ div >
65+ { /* ===== Galaxy Background Component ===== */ }
66+ < GalaxyBackground / >
7167
72- { /* Floating particles animation */ }
73- < div className = "absolute inset-0 -z-10 pointer-events-none" >
74- { particles . map ( ( p , i ) => (
75- < motion . div
76- key = { i }
77- className = "w-1 h-1 bg-white rounded-full opacity-30 absolute"
78- style = { { top : `${ p . top } %` , left : `${ p . left } %` } }
79- animate = { {
80- y : [ `0%` , `${ Math . random ( ) * 50 - 25 } %` , `0%` ] ,
81- x : [ `0%` , `${ Math . random ( ) * 50 - 25 } %` , `0%` ] ,
82- } }
83- transition = { {
84- duration : Math . random ( ) * 8 + 4 ,
85- repeat : Infinity ,
86- repeatType : "mirror" ,
87- ease : "easeInOut" ,
88- } }
68+ { /* ===============================
69+ Main Content
70+ =============================== */ }
71+ < div className = "flex flex-col lg:flex-row-reverse items-center justify-center mt-36 px-6 lg:px-0 gap-16" >
72+ { /* ===== Profile Image with Glow & Tilt ===== */ }
73+ < motion . div
74+ className = "relative w-80 h-80 lg:w-96 lg:h-96 perspective z-10"
75+ style = { { rotateX, rotateY } }
76+ animate = { { y : [ "0%" , "-3%" , "0%" ] } }
77+ transition = { { duration : 6 , repeat : Infinity , repeatType : "mirror" , ease : "easeInOut" } }
78+ >
79+ { /* Layered Gradient Glows */ }
80+ < div className = "absolute inset-0 rounded-2xl blur-3xl opacity-60 bg-gradient-to-r from-pink-500 via-purple-500 to-indigo-500 animate-glow1" > </ div >
81+ < div className = "absolute inset-0 rounded-2xl blur-2xl opacity-40 bg-gradient-to-r from-purple-400 via-pink-400 to-pink-600 animate-glow2" > </ div >
82+ < div className = "absolute inset-0 rounded-2xl blur-xl opacity-30 bg-gradient-to-r from-indigo-500 via-purple-500 to-pink-500 animate-glow3" > </ div >
83+
84+ < Image
85+ src = "https://i.ibb.co/h5pf15q/image.png"
86+ width = { 400 }
87+ height = { 400 }
88+ alt = "Hami Parsa"
89+ className = "relative rounded-2xl shadow-2xl border border-gray-800"
8990 />
90- ) ) }
91- </ div >
91+ </ motion . div >
9292
93- < div className = "flex flex-col lg:flex-row-reverse items-center justify-center mt-36 px-6 lg:px-0 gap-16" >
94- { /* Text section with intro and skills */ }
93+ { /* ===== Text Section ===== */ }
9594 < div className = "text-gray-100 max-w-lg flex flex-col gap-6 z-10 relative" >
95+ { /* Name with Gradient & Icon */ }
9696 < h1 className = "flex items-center gap-2 text-5xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-pink-500 via-purple-500 to-indigo-500 animate-textGradient" >
9797 Im Hami Parsa
9898 < GiChessKing className = "text-yellow-400 text-4xl animate-bounce" />
9999 </ h1 >
100100
101+ { /* Role */ }
101102 < h2 className = "text-2xl flex items-center gap-2 text-gray-300 hover:text-white transition-colors duration-300" >
102103 Front End Developer < FaLaptopCode className = "text-indigo-400 text-2xl" />
103104 </ h2 >
104-
105105 < hr className = "border-gray-800" />
106106
107- { /* Skills grid */ }
107+ { /* ===== Skills Grid ===== */ }
108108 < div className = "grid grid-cols-1 sm:grid-cols-2 gap-4 mt-4" >
109109 { skills . map ( ( skill ) => (
110110 < div
@@ -117,76 +117,27 @@ export default function Bio() {
117117 ) ) }
118118 </ div >
119119 </ div >
120-
121- { /* Profile image with parallax tilt and glowing layers */ }
122- < motion . div
123- className = "relative w-80 h-80 lg:w-96 lg:h-96 perspective z-10"
124- style = { { rotateX, rotateY } }
125- animate = { { y : [ "0%" , "-3%" , "0%" ] } }
126- transition = { { duration : 6 , repeat : Infinity , repeatType : "mirror" , ease : "easeInOut" } }
127- >
128- { /* Neon glow layers */ }
129- < div className = "absolute inset-0 rounded-2xl blur-3xl opacity-60 bg-gradient-to-r from-pink-500 via-purple-500 to-indigo-500 animate-glow1" > </ div >
130- < div className = "absolute inset-0 rounded-2xl blur-2xl opacity-40 bg-gradient-to-r from-purple-400 via-pink-400 to-pink-600 animate-glow2" > </ div >
131- < div className = "absolute inset-0 rounded-2xl blur-xl opacity-30 bg-gradient-to-r from-indigo-500 via-purple-500 to-pink-500 animate-glow3" > </ div >
132-
133- < Image
134- src = "https://i.ibb.co/h5pf15q/image.png"
135- width = { 400 }
136- height = { 400 }
137- alt = "Hami Parsa"
138- className = "relative rounded-2xl shadow-2xl border border-gray-800"
139- />
140- </ motion . div >
141120 </ div >
142121
143- { /* Bio paragraph */ }
122+ { /* ===== Bio Paragraph ===== */ }
144123 < p className = "text-white text-center mt-[300px] max-w-3xl mx-auto text-lg sm:text-xl leading-relaxed" >
145- Hi, Im < span className = "font-bold text-pink-500" > Hami Parsa</ span > — a < span className = "text-indigo-400 font-semibold" > passionate Front-End Developer</ span > dedicated to crafting < span className = "bg-clip-text text-transparent bg-gradient-to-r from-pink-500 via-purple-500 to-indigo-500 font-bold" > modern, interactive, and visually stunning</ span > web experiences.
146- < br /> < br />
147- I transform ideas into < span className = "text-purple-400 font-semibold" > user-friendly websites</ span > using < span className = "text-yellow-400 font-bold" > HTML, CSS, JavaScript</ span > , < span className = "text-blue-500 font-bold" > React</ span > , and < span className = "text-indigo-400 font-bold" > Next.js</ span > .
148- < br /> < br />
149- Always learning, always improving — I strive to build projects that combine < span className = "text-pink-400 font-semibold" > beautiful design</ span > with < span className = "text-purple-500 font-semibold" > high performance</ span > .
150- < br /> < br />
151- Lets collaborate and create < span className = "bg-clip-text text-transparent bg-gradient-to-r from-indigo-500 via-purple-500 to-pink-500 font-bold" > something extraordinary</ span > together!
124+ Hi, Im < span className = "font-bold text-pink-500" > Hami Parsa</ span > — a < span className = "text-indigo-400 font-semibold" > passionate Front-End Developer</ span > crafting < span className = "bg-clip-text text-transparent bg-gradient-to-r from-pink-500 via-purple-500 to-indigo-500 font-bold" > modern, interactive, and visually stunning</ span > web experiences.
152125 </ p >
153126
154- { /* Custom animations and styles */ }
127+ { /* ===== Custom Animations ===== */ }
155128 < style jsx > { `
156129 .perspective { perspective: 1000px; }
157130
158- @keyframes glow1 {
159- 0% { background-position: 0% 50%; }
160- 50% { background-position: 100% 50%; }
161- 100% { background-position: 0% 50%; }
162- }
163- @keyframes glow2 {
164- 0% { background-position: 100% 0%; }
165- 50% { background-position: 0% 100%; }
166- 100% { background-position: 100% 0%; }
167- }
168- @keyframes glow3 {
169- 0% { background-position: 50% 0%; }
170- 50% { background-position: 50% 100%; }
171- 100% { background-position: 50% 0%; }
172- }
173-
131+ /* Glow Animations for Profile Image */
132+ @keyframes glow1 { 0%{background-position:0% 50%}50%{background-position:100% 50%}100%{background-position:0% 50%} }
133+ @keyframes glow2 { 0%{background-position:100% 0%}50%{background-position:0% 100%}100%{background-position:100% 0%} }
134+ @keyframes glow3 { 0%{background-position:50% 0%}50%{background-position:50% 100%}100%{background-position:50% 0%} }
174135 .animate-glow1 { background-size: 200% 200%; animation: glow1 6s ease-in-out infinite; }
175136 .animate-glow2 { background-size: 200% 200%; animation: glow2 8s ease-in-out infinite; }
176137 .animate-glow3 { background-size: 200% 200%; animation: glow3 10s ease-in-out infinite; }
177138
178- @keyframes bgGradient {
179- 0% { background-position: 0% 50%; }
180- 50% { background-position: 100% 50%; }
181- 100% { background-position: 0% 50%; }
182- }
183- .animate-bgGradient { background-size: 200% 200%; animation: bgGradient 20s ease infinite; }
184-
185- @keyframes textGradient {
186- 0% { background-position: 0% 50%; }
187- 50% { background-position: 100% 50%; }
188- 100% { background-position: 0% 50%; }
189- }
139+ /* Gradient Text Animation */
140+ @keyframes textGradient { 0%{background-position:0% 50%}50%{background-position:100% 50%}100%{background-position:0% 50%} }
190141 .animate-textGradient { background-size: 200% 200%; animation: textGradient 6s ease-in-out infinite; }
191142 ` } </ style >
192143 </ div >
0 commit comments