feat: animations, responsive design

Animations
- added opacity animation for experience page
- added stagger animation for navbar items on mobile
- added animation for landing page for years and language indications

Pages
- About Page mockup

Redesign
- Navbar to include icons on desktop
This commit is contained in:
2025-02-21 00:07:25 +01:00
parent 32fea815f2
commit 5070f591d3
56 changed files with 2552 additions and 703 deletions

16
ts/src/experiences.ts Normal file
View File

@@ -0,0 +1,16 @@
const { animate, inView } = Motion;
inView(
"section div",
(element) => {
animate(
element,
{ opacity: 1 },
{
duration: 0.7,
},
);
return () => animate(element, { opacity: 0 }, { duration: 0.7 });
},
{ some: 0.7, initial: false },
);

43
ts/src/landing.ts Normal file
View File

@@ -0,0 +1,43 @@
const { animate, stagger } = Motion;
const experienceCountSelector = "#years-experience";
const languagesCountSelector = "#languages";
const yrsExpCount = document.getElementById("years-experience");
if (!yrsExpCount) {
throw new Error("years-experience Element not found");
}
const langCount = document.getElementById("programming-languages");
if (!langCount) {
throw new Error("languages Element not found");
}
animate(0, 6, {
duration: 1.5,
ease: "circOut",
onUpdate: (latest) => {
const yrs = Math.floor(latest);
yrsExpCount.innerHTML = String(yrs);
},
});
animate(0, 4, {
duration: 1.5,
ease: "circOut",
onUpdate: (latest) => {
const languages = Math.floor(latest);
langCount.innerHTML = String(languages);
},
});
animate(
experienceCountSelector,
{ count: 5 },
{ duration: 1.5, delay: stagger(0.1) },
);
animate(
languagesCountSelector,
{ count: 5 },
{ duration: 1.5, delay: stagger(0.1) },
);

32
ts/src/navigation.ts Normal file
View File

@@ -0,0 +1,32 @@
const { animate, stagger } = Motion;
const navItemSelector = "#mobile-nav>li";
document.addEventListener("alpine:init", () => {
Alpine.data("navbar", () => {
return {
isOpen: false,
open() {
this.isOpen = true;
animate(
navItemSelector,
{ opacity: [0, 1], x: [-50, 0] },
{ delay: stagger(0.1) },
);
},
toggle() {
this.isOpen ? this.close() : this.open();
},
close() {
setTimeout(() => {
this.isOpen = false;
}, 300);
animate(
navItemSelector,
{ opacity: [1, 0], x: [0, 50] },
{ delay: stagger(0.1) },
);
},
};
});
});

10
ts/src/types.d.ts vendored Normal file
View File

@@ -0,0 +1,10 @@
import type motionPkg from "motion";
import type alpine from "alpinejs";
declare global {
interface Window {
Motion: typeof motionPkg;
}
const Motion: typeof motionPkg;
const Alpine: typeof alpine;
}