Animated about
This commit is contained in:
+102
-69
@@ -1,3 +1,5 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Github,
|
Github,
|
||||||
Linkedin,
|
Linkedin,
|
||||||
@@ -21,6 +23,16 @@ import {
|
|||||||
SiLinux,
|
SiLinux,
|
||||||
} from "@icons-pack/react-simple-icons";
|
} from "@icons-pack/react-simple-icons";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
import { motion } from "framer-motion";
|
||||||
|
import {
|
||||||
|
staggerContainer,
|
||||||
|
fadeInUp,
|
||||||
|
fadeIn,
|
||||||
|
cardReveal,
|
||||||
|
timelineItemLeft,
|
||||||
|
timelineItemRight,
|
||||||
|
slowFloat,
|
||||||
|
} from "@/lib/animations";
|
||||||
|
|
||||||
const timeline = [
|
const timeline = [
|
||||||
{
|
{
|
||||||
@@ -122,11 +134,20 @@ export default function About() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* Hero */}
|
{/* Hero */}
|
||||||
<section className="pt-24 pb-16 bg-background relative overflow-hidden">
|
<motion.section
|
||||||
<div className="absolute top-1/4 right-1/4 w-96 h-96 bg-accent/5 rounded-full blur-3xl" />
|
className="pt-24 pb-16 bg-background relative overflow-hidden"
|
||||||
|
variants={staggerContainer}
|
||||||
|
initial="hidden"
|
||||||
|
animate="visible"
|
||||||
|
>
|
||||||
|
<motion.div
|
||||||
|
className="absolute top-1/4 right-1/4 w-96 h-96 bg-accent/5 rounded-full blur-3xl"
|
||||||
|
variants={slowFloat}
|
||||||
|
/>
|
||||||
<div className="container mx-auto px-6 relative z-10">
|
<div className="container mx-auto px-6 relative z-10">
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-16 items-center">
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-16 items-center">
|
||||||
{/* Image/Avatar */}
|
{/* Image/Avatar */}
|
||||||
|
<motion.div variants={fadeInUp}>
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<div className="aspect-square max-w-md mx-auto rounded-3xl overflow-hidden glass-card p-2">
|
<div className="aspect-square max-w-md mx-auto rounded-3xl overflow-hidden glass-card p-2">
|
||||||
<div className="w-full h-full rounded-2xl bg-gradient-to-br from-accent/20 to-accent/5 flex items-center justify-center">
|
<div className="w-full h-full rounded-2xl bg-gradient-to-br from-accent/20 to-accent/5 flex items-center justify-center">
|
||||||
@@ -138,36 +159,53 @@ export default function About() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/* Floating badges */}
|
{/* Floating badges */}
|
||||||
<div className="absolute -bottom-4 -right-4 glass-card rounded-xl px-4 py-2 flex items-center gap-2">
|
<motion.div
|
||||||
|
className="absolute -bottom-4 -right-4 glass-card rounded-xl px-4 py-2 flex items-center gap-2"
|
||||||
|
variants={fadeInUp}
|
||||||
|
transition={{ delay: 0.6, type: "spring" }}
|
||||||
|
>
|
||||||
<span className="w-2 h-2 rounded-full bg-accent animate-pulse" />
|
<span className="w-2 h-2 rounded-full bg-accent animate-pulse" />
|
||||||
<span className="text-sm text-foreground">Available</span>
|
<span className="text-sm text-foreground">Available</span>
|
||||||
|
</motion.div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</motion.div>
|
||||||
|
|
||||||
{/* Content */}
|
{/* Content */}
|
||||||
<div>
|
<motion.div variants={staggerContainer}>
|
||||||
<span className="text-accent text-sm font-medium uppercase tracking-wider">
|
<span className="text-accent text-sm font-medium uppercase tracking-wider">
|
||||||
About Me
|
About Me
|
||||||
</span>
|
</span>
|
||||||
<h1 className="text-4xl md:text-5xl font-bold text-foreground mt-2 mb-6">
|
<motion.h1
|
||||||
|
variants={fadeInUp}
|
||||||
|
className="text-4xl md:text-5xl font-bold text-foreground mt-2 mb-6"
|
||||||
|
>
|
||||||
Hey, I'm{" "}
|
Hey, I'm{" "}
|
||||||
<span className="text-gradient-gold">Klesti Selimaj</span>
|
<span className="text-gradient-gold">Klesti Selimaj</span>
|
||||||
</h1>
|
</motion.h1>
|
||||||
<p className="text-lg text-muted-foreground mb-6">
|
<motion.p
|
||||||
|
variants={fadeInUp}
|
||||||
|
className="text-lg text-muted-foreground mb-6"
|
||||||
|
>
|
||||||
A 16-year-old software engineer from Albania with 6+ years of
|
A 16-year-old software engineer from Albania with 6+ years of
|
||||||
experience. I'm passionate about building things that matter,
|
experience. I'm passionate about building things that matter,
|
||||||
from low-level systems to beautiful user interfaces.
|
from low-level systems to beautiful user interfaces.
|
||||||
</p>
|
</motion.p>
|
||||||
<p className="text-muted-foreground mb-8">
|
<motion.p
|
||||||
|
variants={fadeInUp}
|
||||||
|
className="text-muted-foreground mb-8"
|
||||||
|
>
|
||||||
My journey started at age 10 when I had my first laptop (a Asus
|
My journey started at age 10 when I had my first laptop (a Asus
|
||||||
with pre installed endless linux), and since then I've been
|
with pre installed endless linux), and since then I've been
|
||||||
hooked on computers, but i didn't exactly know what programming
|
hooked on computers, but i didn't exactly know what programming
|
||||||
was but i was doing it unconsciously, making winforms apps in c#
|
was but i was doing it unconsciously, making winforms apps in c#
|
||||||
with visual studio.
|
with visual studio.
|
||||||
</p>
|
</motion.p>
|
||||||
|
|
||||||
{/* Quick Info */}
|
{/* Quick Info */}
|
||||||
<div className="flex flex-wrap gap-4 mb-8">
|
<motion.div
|
||||||
|
variants={fadeInUp}
|
||||||
|
className="flex flex-wrap gap-4 mb-8"
|
||||||
|
>
|
||||||
<div className="flex items-center gap-2 text-muted-foreground">
|
<div className="flex items-center gap-2 text-muted-foreground">
|
||||||
<MapPin className="w-4 h-4 text-accent" />
|
<MapPin className="w-4 h-4 text-accent" />
|
||||||
<span>Albania</span>
|
<span>Albania</span>
|
||||||
@@ -180,55 +218,30 @@ export default function About() {
|
|||||||
<Crown className="w-4 h-4 text-accent" />
|
<Crown className="w-4 h-4 text-accent" />
|
||||||
<span>@orus-dev</span>
|
<span>@orus-dev</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</motion.div>
|
||||||
|
|
||||||
{/* Social Links */}
|
{/* Social Links */}
|
||||||
<div className="flex items-center gap-4">
|
<motion.div
|
||||||
<a
|
variants={fadeInUp}
|
||||||
href="https://github.com/selimaj-dev"
|
className="flex items-center gap-4"
|
||||||
target="_blank"
|
>
|
||||||
rel="noopener noreferrer"
|
{[Github, Linkedin, Youtube, Instagram, ExternalLink].map(
|
||||||
|
(Icon, i) => (
|
||||||
|
<motion.a
|
||||||
|
key={i}
|
||||||
|
whileHover={{ y: -4, scale: 1.05 }}
|
||||||
|
whileTap={{ scale: 0.95 }}
|
||||||
className="glass-card p-3 rounded-xl hover:ring-1 hover:ring-accent/30 transition-all"
|
className="glass-card p-3 rounded-xl hover:ring-1 hover:ring-accent/30 transition-all"
|
||||||
>
|
>
|
||||||
<Github className="w-5 h-5 text-foreground" />
|
<Icon className="w-5 h-5 text-foreground" />
|
||||||
</a>
|
</motion.a>
|
||||||
<a
|
),
|
||||||
href="https://www.linkedin.com/in/klesti-selimaj-7a0162343/"
|
)}
|
||||||
target="_blank"
|
</motion.div>
|
||||||
rel="noopener noreferrer"
|
</motion.div>
|
||||||
className="glass-card p-3 rounded-xl hover:ring-1 hover:ring-accent/30 transition-all"
|
|
||||||
>
|
|
||||||
<Linkedin className="w-5 h-5 text-foreground" />
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
href="https://www.youtube.com/@0xkleo"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="glass-card p-3 rounded-xl hover:ring-1 hover:ring-accent/30 transition-all"
|
|
||||||
>
|
|
||||||
<Youtube className="w-5 h-5 text-foreground" />
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
href="https://www.instagram.com/selimaj.dev/"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="glass-card p-3 rounded-xl hover:ring-1 hover:ring-accent/30 transition-all"
|
|
||||||
>
|
|
||||||
<Instagram className="w-5 h-5 text-foreground" />
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
href="https://dev.to/selimaj"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="glass-card p-3 rounded-xl hover:ring-1 hover:ring-accent/30 transition-all"
|
|
||||||
>
|
|
||||||
<ExternalLink className="w-5 h-5 text-foreground" />
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</motion.section>
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Tech Stack */}
|
{/* Tech Stack */}
|
||||||
<section className="py-24 bg-card/50">
|
<section className="py-24 bg-card/50">
|
||||||
@@ -246,12 +259,18 @@ export default function About() {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
<motion.div
|
||||||
|
className="grid grid-cols-2 md:grid-cols-4 gap-4"
|
||||||
|
variants={staggerContainer}
|
||||||
|
initial="hidden"
|
||||||
|
whileInView="visible"
|
||||||
|
viewport={{ once: true }}
|
||||||
|
>
|
||||||
{techStack.map((tech, index) => (
|
{techStack.map((tech, index) => (
|
||||||
<div
|
<motion.div
|
||||||
key={tech.name}
|
key={tech.name}
|
||||||
|
variants={cardReveal}
|
||||||
className="glass-card rounded-2xl p-6 text-center hover-lift group"
|
className="glass-card rounded-2xl p-6 text-center hover-lift group"
|
||||||
style={{ animationDelay: `${index * 50}ms` }}
|
|
||||||
>
|
>
|
||||||
<div className={cn("text-4xl mb-3 mx-auto w-max", tech.color)}>
|
<div className={cn("text-4xl mb-3 mx-auto w-max", tech.color)}>
|
||||||
{tech.icon}
|
{tech.icon}
|
||||||
@@ -259,9 +278,9 @@ export default function About() {
|
|||||||
<h3 className="font-semibold text-foreground group-hover:text-accent transition-colors">
|
<h3 className="font-semibold text-foreground group-hover:text-accent transition-colors">
|
||||||
{tech.name}
|
{tech.name}
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</motion.div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</motion.div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -280,12 +299,18 @@ export default function About() {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
<motion.div
|
||||||
|
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6"
|
||||||
|
variants={staggerContainer}
|
||||||
|
initial="hidden"
|
||||||
|
whileInView="visible"
|
||||||
|
viewport={{ once: true }}
|
||||||
|
>
|
||||||
{achievements.map((achievement, index) => (
|
{achievements.map((achievement, index) => (
|
||||||
<div
|
<motion.div
|
||||||
key={achievement.title}
|
key={achievement.title}
|
||||||
|
variants={cardReveal}
|
||||||
className="glass-card rounded-2xl p-6 text-center hover-lift"
|
className="glass-card rounded-2xl p-6 text-center hover-lift"
|
||||||
style={{ animationDelay: `${index * 100}ms` }}
|
|
||||||
>
|
>
|
||||||
<div className="text-4xl mb-4">{achievement.icon}</div>
|
<div className="text-4xl mb-4">{achievement.icon}</div>
|
||||||
<h3 className="font-semibold text-foreground mb-2">
|
<h3 className="font-semibold text-foreground mb-2">
|
||||||
@@ -294,9 +319,9 @@ export default function About() {
|
|||||||
<p className="text-sm text-muted-foreground">
|
<p className="text-sm text-muted-foreground">
|
||||||
{achievement.description}
|
{achievement.description}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</motion.div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</motion.div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -318,10 +343,15 @@ export default function About() {
|
|||||||
|
|
||||||
<div className="max-w-3xl mx-auto">
|
<div className="max-w-3xl mx-auto">
|
||||||
{timeline.map((item, index) => (
|
{timeline.map((item, index) => (
|
||||||
<div
|
<motion.div
|
||||||
key={item.year}
|
key={item.year}
|
||||||
|
variants={
|
||||||
|
index % 2 === 0 ? timelineItemLeft : timelineItemRight
|
||||||
|
}
|
||||||
|
initial="hidden"
|
||||||
|
whileInView="visible"
|
||||||
|
viewport={{ once: true }}
|
||||||
className="relative flex gap-6 pb-12 last:pb-0"
|
className="relative flex gap-6 pb-12 last:pb-0"
|
||||||
style={{ animationDelay: `${index * 100}ms` }}
|
|
||||||
>
|
>
|
||||||
{/* Line */}
|
{/* Line */}
|
||||||
{index !== timeline.length - 1 && (
|
{index !== timeline.length - 1 && (
|
||||||
@@ -351,7 +381,7 @@ export default function About() {
|
|||||||
{item.description}
|
{item.description}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</motion.div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -359,7 +389,10 @@ export default function About() {
|
|||||||
|
|
||||||
{/* Philosophy */}
|
{/* Philosophy */}
|
||||||
<section className="py-24 bg-background relative overflow-hidden">
|
<section className="py-24 bg-background relative overflow-hidden">
|
||||||
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[600px] h-[600px] bg-accent/5 rounded-full blur-3xl" />
|
<motion.div
|
||||||
|
className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[600px] h-[600px] bg-accent/5 rounded-full blur-3xl"
|
||||||
|
variants={slowFloat}
|
||||||
|
/>
|
||||||
<div className="container mx-auto px-6 relative z-10">
|
<div className="container mx-auto px-6 relative z-10">
|
||||||
<div className="max-w-3xl mx-auto text-center">
|
<div className="max-w-3xl mx-auto text-center">
|
||||||
<span className="text-accent text-sm font-medium uppercase tracking-wider">
|
<span className="text-accent text-sm font-medium uppercase tracking-wider">
|
||||||
|
|||||||
+87
-7
@@ -1,22 +1,102 @@
|
|||||||
import { Variant } from "framer-motion";
|
import { Variants } from "framer-motion";
|
||||||
|
|
||||||
type AnimationVariants = Record<string, Variant>;
|
/**
|
||||||
|
* Container
|
||||||
|
*/
|
||||||
|
export const staggerContainer: Variants = {
|
||||||
|
hidden: {},
|
||||||
|
visible: {
|
||||||
|
transition: {
|
||||||
|
staggerChildren: 0.15,
|
||||||
|
delayChildren: 0.05,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export const fadeInUp: AnimationVariants = {
|
/**
|
||||||
hidden: { opacity: 0, y: 30 },
|
* Basic entrances
|
||||||
|
*/
|
||||||
|
export const fadeInUp: Variants = {
|
||||||
|
hidden: { opacity: 0, y: 24 },
|
||||||
visible: {
|
visible: {
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
y: 0,
|
y: 0,
|
||||||
|
transition: {
|
||||||
|
duration: 0.6,
|
||||||
|
ease: [0.22, 1, 0.36, 1], // premium easeOut
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const fadeInDown: Variants = {
|
||||||
|
hidden: { opacity: 0, y: -24 },
|
||||||
|
visible: {
|
||||||
|
opacity: 1,
|
||||||
|
y: 0,
|
||||||
|
transition: {
|
||||||
|
duration: 0.6,
|
||||||
|
ease: [0.22, 1, 0.36, 1],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const fadeIn: Variants = {
|
||||||
|
hidden: { opacity: 0 },
|
||||||
|
visible: {
|
||||||
|
opacity: 1,
|
||||||
transition: { duration: 0.6, ease: "easeOut" },
|
transition: { duration: 0.6, ease: "easeOut" },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const staggerContainer: AnimationVariants = {
|
/**
|
||||||
hidden: { opacity: 0 },
|
* Cards
|
||||||
|
*/
|
||||||
|
export const cardReveal: Variants = {
|
||||||
|
hidden: { opacity: 0, y: 30, scale: 0.96 },
|
||||||
visible: {
|
visible: {
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
|
y: 0,
|
||||||
|
scale: 1,
|
||||||
transition: {
|
transition: {
|
||||||
staggerChildren: 0.15,
|
duration: 0.5,
|
||||||
|
ease: [0.22, 1, 0.36, 1],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timeline
|
||||||
|
*/
|
||||||
|
export const timelineItemLeft: Variants = {
|
||||||
|
hidden: { opacity: 0, x: -40 },
|
||||||
|
visible: {
|
||||||
|
opacity: 1,
|
||||||
|
x: 0,
|
||||||
|
transition: { duration: 0.5, ease: "easeOut" },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const timelineItemRight: Variants = {
|
||||||
|
hidden: { opacity: 0, x: 40 },
|
||||||
|
visible: {
|
||||||
|
opacity: 1,
|
||||||
|
x: 0,
|
||||||
|
transition: { duration: 0.5, ease: "easeOut" },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorative / ambient
|
||||||
|
*/
|
||||||
|
export const slowFloat: Variants = {
|
||||||
|
hidden: { opacity: 0 },
|
||||||
|
visible: {
|
||||||
|
opacity: 1,
|
||||||
|
y: [0, -10, 0],
|
||||||
|
transition: {
|
||||||
|
duration: 6,
|
||||||
|
repeat: Infinity,
|
||||||
|
ease: "easeInOut",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user