Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 168 additions & 0 deletions src/components/About.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import React, { useState, useEffect } from 'react';
import { motion } from 'framer-motion';
import { useInView } from 'react-intersection-observer';

const AnimatedCounter = ({ end, duration = 2, suffix = '' }: { end: number; duration?: number; suffix?: string }) => {
const [count, setCount] = useState(0);
const [ref, inView] = useInView({ triggerOnce: true });

useEffect(() => {
if (inView) {
let startTime = 0;
const startCount = 0;
const endCount = end;

const animate = (currentTime: number) => {
if (startTime === 0) startTime = currentTime;
const progress = Math.min((currentTime - startTime) / (duration * 1000), 1);
const current = startCount + (endCount - startCount) * progress;

setCount(Math.floor(current));

if (progress < 1) {
requestAnimationFrame(animate);
}
};

requestAnimationFrame(animate);
}
}, [inView, end, duration]);

return (
<span ref={ref}>
{count}{suffix}
</span>
);
};

const About = () => {
const [ref, inView] = useInView({
threshold: 0.3,
triggerOnce: true
});

const stats = [
{ number: 5, suffix: '+', label: 'Years Experience' },
{ number: 50, suffix: '+', label: 'Projects Completed' },
{ number: 20, suffix: '+', label: 'Technologies' },
{ number: 100, suffix: '%', label: 'Client Satisfaction' }
];

return (
<section id="about" ref={ref} className="py-20 bg-gradient-to-b from-gray-900 to-gray-800">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<motion.div
className="text-center mb-16"
initial={{ opacity: 0, y: 30 }}
animate={inView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6 }}
>
<h2 className="text-4xl md:text-5xl font-bold text-white mb-4">
About <span className="bg-gradient-to-r from-blue-400 to-purple-600 bg-clip-text text-transparent">Me</span>
</h2>
<p className="text-gray-400 text-lg max-w-2xl mx-auto">
Passionate developer with a love for creating innovative solutions
</p>
</motion.div>

<div className="grid lg:grid-cols-2 gap-12 items-center">
{/* Profile Image */}
<motion.div
className="relative group"
initial={{ opacity: 0, x: -50 }}
animate={inView ? { opacity: 1, x: 0 } : {}}
transition={{ duration: 0.8, delay: 0.2 }}
>
<div className="relative overflow-hidden rounded-2xl bg-gradient-to-br from-blue-600/20 to-purple-600/20 p-8">
<motion.div
className="w-full h-96 bg-gradient-to-br from-blue-500 to-purple-600 rounded-lg flex items-center justify-center text-white text-6xl font-bold"
whileHover={{
scale: 1.05,
rotateY: 10,
rotateX: 5
}}
transition={{ type: "spring", stiffness: 300 }}
style={{
boxShadow: '0 25px 50px -12px rgba(59, 130, 246, 0.25)'
}}
>
AJ
</motion.div>

{/* Floating particles */}
<div className="absolute inset-0 pointer-events-none">
{[...Array(6)].map((_, i) => (
<motion.div
key={i}
className="absolute w-2 h-2 bg-blue-400 rounded-full opacity-60"
style={{
left: `${20 + i * 15}%`,
top: `${30 + i * 10}%`
}}
animate={{
y: [0, -20, 0],
opacity: [0.6, 0.2, 0.6]
}}
transition={{
duration: 2 + i * 0.5,
repeat: Infinity,
delay: i * 0.3
}}
/>
))}
</div>
</div>
</motion.div>

{/* Content */}
<motion.div
className="space-y-6"
initial={{ opacity: 0, x: 50 }}
animate={inView ? { opacity: 1, x: 0 } : {}}
transition={{ duration: 0.8, delay: 0.4 }}
>
<div className="prose prose-invert prose-lg">
<p className="text-gray-300 text-lg leading-relaxed mb-6">
I'm a passionate full-stack developer with over 5 years of experience creating
innovative web applications and digital experiences. My journey started with a
curiosity for how things work, which evolved into a love for crafting elegant
solutions to complex problems.
</p>

<p className="text-gray-300 text-lg leading-relaxed mb-8">
I specialize in modern technologies like React, Node.js, and cloud platforms,
always staying up-to-date with the latest industry trends. When I'm not coding,
you'll find me exploring new technologies, contributing to open source, or
mentoring aspiring developers.
</p>
</div>

{/* Stats */}
<div className="grid grid-cols-2 md:grid-cols-4 gap-6">
{stats.map((stat, index) => (
<motion.div
key={index}
className="text-center p-4 rounded-lg bg-gray-800/50 backdrop-blur-sm border border-gray-700/50 hover:border-blue-500/50 transition-all duration-300"
initial={{ opacity: 0, y: 20 }}
animate={inView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6, delay: 0.6 + index * 0.1 }}
whileHover={{
scale: 1.05,
boxShadow: '0 10px 25px -3px rgba(59, 130, 246, 0.1)'
}}
>
<div className="text-2xl md:text-3xl font-bold text-blue-400 mb-2">
<AnimatedCounter end={stat.number} suffix={stat.suffix} />
</div>
<div className="text-sm text-gray-400">{stat.label}</div>
</motion.div>
))}
</div>
</motion.div>
</div>
</div>
</section>
);
};

export default About;
Loading