Refactor timeline and skill display with enhanced animations
This commit is contained in:
+138
-89
@@ -11,33 +11,65 @@ export default function About() {
|
|||||||
"I discovered my passion for technology by experimenting with Scratch and creating some simple Games.",
|
"I discovered my passion for technology by experimenting with Scratch and creating some simple Games.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
date: "2020",
|
date: "2022",
|
||||||
title: "Exploring Web & Scripting",
|
title: "Exploring Web & Scripting",
|
||||||
content:
|
content:
|
||||||
"Started creating small websites and got into JavaScript, CSS, and working with various scripting languages.",
|
"Started creating small websites and got into HTML, CSS",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
date: "2022",
|
date: "2022",
|
||||||
title: "Diving into Game Development",
|
title: "Raspberry Pi & Python",
|
||||||
content:
|
content:
|
||||||
"Tried Unity and C#, building small 2D and 3D prototypes to expand my skill set.",
|
"Created some simple Python scripts for my Raspberry Pi, experimenting with the Raspberry Pi OS",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
date: "2024",
|
date: "2024",
|
||||||
title: "Full Stack & Beyond",
|
title: "Full Stack & Beyond",
|
||||||
content:
|
content:
|
||||||
"Ventured into backend (SQL, Python) and continued refining my frontend abilities, always exploring new challenges.",
|
"Ventured into backend (SQL, Python, Javascript, Java) and continued refining my frontend abilities.",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const skills = [
|
const skills = [
|
||||||
{name: "JavaScript", level: 80, waveSpeed: "2s"},
|
{
|
||||||
{name: "Python", level: 75, waveSpeed: "2.5s"},
|
name: "JavaScript",
|
||||||
{name: "C#", level: 50, waveSpeed: "3s"},
|
level: 80,
|
||||||
{name: "SQL", level: 85, waveSpeed: "2.2s"},
|
waveSpeed: "2s",
|
||||||
{name: "HTML & CSS", level: 70, waveSpeed: "2.7s"},
|
progression: [0, 30, 60, 80],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Python",
|
||||||
|
level: 75,
|
||||||
|
waveSpeed: "2.5s",
|
||||||
|
progression: [10, 25, 50, 75],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Java",
|
||||||
|
level: 50,
|
||||||
|
waveSpeed: "3s",
|
||||||
|
progression: [0, 0, 0, 60],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "SQL",
|
||||||
|
level: 85,
|
||||||
|
waveSpeed: "2.2s",
|
||||||
|
progression: [0, 0, 0, 85],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "HTML & CSS",
|
||||||
|
level: 70,
|
||||||
|
waveSpeed: "2.7s",
|
||||||
|
progression: [0, 30, 50, 80],
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const getSkillLabel = (level) => {
|
||||||
|
if (level < 25) return "Beginner";
|
||||||
|
if (level < 50) return "Intermediate";
|
||||||
|
if (level < 75) return "Advanced";
|
||||||
|
return "Expert";
|
||||||
|
};
|
||||||
|
|
||||||
const sectionRefs = useRef([]);
|
const sectionRefs = useRef([]);
|
||||||
const aboutMeRef = useRef(null);
|
const aboutMeRef = useRef(null);
|
||||||
const scrollContainerRef = useRef(null);
|
const scrollContainerRef = useRef(null);
|
||||||
@@ -62,12 +94,16 @@ export default function About() {
|
|||||||
const observer = new IntersectionObserver(
|
const observer = new IntersectionObserver(
|
||||||
(entries) => {
|
(entries) => {
|
||||||
entries.forEach((entry) => {
|
entries.forEach((entry) => {
|
||||||
if (entry.isIntersecting) {
|
const index = sectionRefs.current.findIndex((el) => el === entry.target);
|
||||||
const index = sectionRefs.current.findIndex((el) => el === entry.target);
|
if (entry.isIntersecting && index !== -1) {
|
||||||
if (index !== -1) {
|
setCurrentSection(index);
|
||||||
setCurrentSection(index);
|
}
|
||||||
setTimelineFinished(index === timelineData.length - 1);
|
if (
|
||||||
}
|
entry.isIntersecting &&
|
||||||
|
index === timelineData.length - 1 &&
|
||||||
|
entry.intersectionRatio >= 0.8
|
||||||
|
) {
|
||||||
|
setTimelineFinished(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -150,98 +186,111 @@ export default function About() {
|
|||||||
width: "100%",
|
width: "100%",
|
||||||
height: "100%",
|
height: "100%",
|
||||||
scrollBehavior: "smooth",
|
scrollBehavior: "smooth",
|
||||||
scrollbarWidth: "none", // Firefox
|
scrollbarWidth: "none",
|
||||||
msOverflowStyle: "none", // IE/Edge
|
msOverflowStyle: "none",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{timelineData.map((item, index) => (
|
{timelineData.map((item, index) => {
|
||||||
<section
|
const adjustedSkills = skills.map((s) => {
|
||||||
key={index}
|
const stepLevel = s.progression?.[index] ?? 0;
|
||||||
ref={(el) => (sectionRefs.current[index] = el)}
|
return {
|
||||||
style={{
|
...s,
|
||||||
flex: "0 0 100%",
|
level: Math.floor((s.level * stepLevel) / 100),
|
||||||
scrollSnapAlign: "center",
|
};
|
||||||
display: "flex",
|
});
|
||||||
flexDirection: "column",
|
return (
|
||||||
alignItems: "center",
|
<section
|
||||||
justifyContent: "center",
|
key={index}
|
||||||
padding: "2rem",
|
ref={(el) => (sectionRefs.current[index] = el)}
|
||||||
boxSizing: "border-box",
|
style={{
|
||||||
}}
|
flex: "0 0 100%",
|
||||||
>
|
scrollSnapAlign: "center",
|
||||||
<h2 style={{marginBottom: "1rem"}}>{item.title}</h2>
|
display: "flex",
|
||||||
<h3 style={{marginBottom: "1rem"}}>{item.date}</h3>
|
flexDirection: "column",
|
||||||
<p style={{maxWidth: "600px", textAlign: "center"}}>{item.content}</p>
|
alignItems: "center",
|
||||||
</section>
|
justifyContent: "center",
|
||||||
))}
|
padding: "2rem",
|
||||||
</div>
|
boxSizing: "border-box",
|
||||||
</section>
|
}}
|
||||||
{/* Skills Section*/}
|
>
|
||||||
{timelineFinished && (
|
<h2 style={{marginBottom: "1rem"}}>{item.title}</h2>
|
||||||
<section
|
<h3 style={{marginBottom: "1rem"}}>{item.date}</h3>
|
||||||
style={{
|
<p style={{maxWidth: "600px", textAlign: "center", marginBottom: "2rem"}}>
|
||||||
minHeight: "100vh",
|
{item.content}
|
||||||
display: "flex",
|
</p>
|
||||||
flexDirection: "column",
|
|
||||||
alignItems: "center",
|
{/* SKILLS: show per stage */}
|
||||||
justifyContent: "center",
|
<div style={{display: "flex", gap: "2rem"}}>
|
||||||
padding: "2rem",
|
<div style={{
|
||||||
color: "#fff",
|
display: "flex",
|
||||||
}}
|
gap: "2rem",
|
||||||
>
|
flexWrap: "wrap",
|
||||||
<h2 style={{fontSize: "2rem", marginBottom: "2rem"}}>My Skills</h2>
|
justifyContent: "center"
|
||||||
<div style={{display: "flex", gap: "2rem"}}>
|
}}>
|
||||||
{skills.map((skill, index) => (
|
{adjustedSkills.filter((s) => s.level > 0).map((skill, sIndex) => (
|
||||||
<div key={index} style={{textAlign: "center"}}>
|
<div
|
||||||
<div
|
key={`${skill.name}-${index}`}
|
||||||
style={{
|
className={currentSection === index ? "skill-card animate-skill" : "skill-card"}
|
||||||
width: "60px",
|
style={{
|
||||||
height: "200px",
|
textAlign: "center",
|
||||||
backgroundColor: "#333",
|
width: "120px",
|
||||||
borderRadius: "10px",
|
animationDelay: `${sIndex * 100}ms`,
|
||||||
overflow: "hidden",
|
animationFillMode: "both",
|
||||||
position: "relative",
|
}}
|
||||||
border: "2px solid #555",
|
>
|
||||||
}}
|
<p style={{
|
||||||
>
|
fontSize: "1.1rem",
|
||||||
<div
|
fontWeight: "bold",
|
||||||
className="liquid"
|
marginBottom: "0.5rem"
|
||||||
style={{
|
}}>
|
||||||
width: "100%",
|
{skill.name}
|
||||||
height: `${skill.level}%`,
|
</p>
|
||||||
position: "absolute",
|
<div
|
||||||
bottom: 0,
|
style={{
|
||||||
background: "linear-gradient(45deg, #7400a9, #411357)",
|
padding: "0.5rem 1rem",
|
||||||
borderTop: "4px solid rgba(255, 255, 255, 0.6)",
|
backgroundColor: "#1a001a",
|
||||||
animation: `wave ${skill.waveSpeed} infinite ease-in-out`,
|
border: "2px solid #3d003d",
|
||||||
}}
|
borderRadius: "10px",
|
||||||
>
|
fontSize: "1rem",
|
||||||
<p style={{marginTop: "10px", fontSize: "1rem"}}>{skill.level}%</p>
|
color: "#fff",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{getSkillLabel(skill.level)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p style={{marginTop: "10px", fontSize: "1rem"}}>{skill.name}</p>
|
</section>
|
||||||
</div>
|
);
|
||||||
))}
|
})}
|
||||||
</div>
|
</div>
|
||||||
<div style={{marginTop: "3rem"}}>
|
{/* End of scroll container */}
|
||||||
|
{timelineFinished && (
|
||||||
|
<div style={{marginTop: "3rem", textAlign: "center", width: "100%"}}>
|
||||||
<Link href="/projects">
|
<Link href="/projects">
|
||||||
<button
|
<button
|
||||||
className="learnMoreButton"
|
className="learnMoreButton"
|
||||||
style={{
|
style={{
|
||||||
padding: "1rem 2rem",
|
padding: "1rem 2rem",
|
||||||
fontSize: "1.25rem",
|
fontSize: "1.25rem",
|
||||||
|
backgroundColor: "#3d003d",
|
||||||
border: "none",
|
border: "none",
|
||||||
borderRadius: "5px",
|
borderRadius: "5px",
|
||||||
color: "#fff",
|
color: "#fff",
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
|
transition: "background-color 0.3s ease",
|
||||||
}}
|
}}
|
||||||
|
onMouseOver={(e) => (e.currentTarget.style.backgroundColor = "#2e002e")}
|
||||||
|
onMouseOut={(e) => (e.currentTarget.style.backgroundColor = "#3d003d")}
|
||||||
>
|
>
|
||||||
View Projects
|
View Projects
|
||||||
</button>
|
</button>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
)}
|
||||||
)}
|
</section>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -276,3 +276,39 @@ body {
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes fadeInSkill {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(10px);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.skill-card {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(10px);
|
||||||
|
transition: opacity 0.3s ease-out, transform 0.3s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-skill {
|
||||||
|
animation: fadeInSkill 0.6s ease-out forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeInButton {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(10px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.learnMoreButton {
|
||||||
|
animation: fadeInButton 0.5s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user