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:
@@ -1,40 +0,0 @@
|
||||
function calculateDuration(startDate, endDate) {
|
||||
const start = new Date(startDate);
|
||||
const end = endDate ? new Date(endDate) : new Date();
|
||||
|
||||
const years = end.getFullYear() - start.getFullYear();
|
||||
const months = end.getMonth() - start.getMonth();
|
||||
|
||||
let totalMonths = years * 12 + months;
|
||||
if (end.getDate() < start.getDate()) {
|
||||
totalMonths--;
|
||||
}
|
||||
|
||||
const finalYears = Math.floor(totalMonths / 12);
|
||||
const finalMonths = totalMonths % 12;
|
||||
|
||||
let duration = "";
|
||||
if (finalYears > 0) {
|
||||
duration += `${finalYears} year${finalYears > 1 ? "s" : ""}`;
|
||||
}
|
||||
if (finalMonths > 0) {
|
||||
if (duration) duration += " ";
|
||||
duration += `${finalMonths} month${finalMonths > 1 ? "s" : ""}`;
|
||||
}
|
||||
return duration;
|
||||
}
|
||||
|
||||
function formatDateRange(startDate, endDate) {
|
||||
const start = new Date(startDate);
|
||||
const end = endDate ? new Date(endDate) : new Date();
|
||||
|
||||
const formatDate = (date) => {
|
||||
return date.toLocaleDateString("en-US", {
|
||||
month: "short",
|
||||
year: "numeric",
|
||||
});
|
||||
};
|
||||
|
||||
const duration = calculateDuration(startDate, endDate);
|
||||
return `${formatDate(start)} - ${endDate ? formatDate(end) : "Present"} · ${duration}`;
|
||||
}
|
||||
2
assets/js/experiences.js
Normal file
2
assets/js/experiences.js
Normal file
@@ -0,0 +1,2 @@
|
||||
!function(){"use strict";const{animate:i,inView:t}=Motion;t("section div",(t=>(i(t,{opacity:1},{duration:.7}),()=>i(t,{opacity:0},{duration:.7}))),{some:.7,initial:!1})}();
|
||||
//# sourceMappingURL=experiences.js.map
|
||||
1
assets/js/experiences.js.map
Normal file
1
assets/js/experiences.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"experiences.js","sources":["../../ts/src/experiences.ts"],"sourcesContent":["const { animate, inView } = Motion;\n\ninView(\n \"section div\",\n (element) => {\n animate(\n element,\n { opacity: 1 },\n {\n duration: 0.7,\n },\n );\n return () => animate(element, { opacity: 0 }, { duration: 0.7 });\n },\n { some: 0.7, initial: false },\n);\n"],"names":["animate","inView","Motion","element","opacity","duration","some","initial"],"mappings":"yBAAA,MAAMA,QAAEA,EAAOC,OAAEA,GAAWC,OAE5BD,EACE,eACCE,IACCH,EACEG,EACA,CAAEC,QAAS,GACX,CACEC,SAAU,KAGP,IAAML,EAAQG,EAAS,CAAEC,QAAS,GAAK,CAAEC,SAAU,OAE5D,CAAEC,KAAM,GAAKC,SAAS"}
|
||||
@@ -1,23 +0,0 @@
|
||||
const { animate, scroll } = Motion;
|
||||
|
||||
const yearsExperience = document.getElementById("years-experience");
|
||||
const programmingLangues = document.getElementById("programming-languages");
|
||||
|
||||
const startDate = new Date("2019-01-01");
|
||||
years = Math.floor((new Date() - startDate) / 1000 / 60 / 60 / 24 / 365);
|
||||
|
||||
animate(0, years, {
|
||||
duration: 2,
|
||||
ease: "circOut",
|
||||
onUpdate: (latest) => {
|
||||
yearsExperience.innerHTML = Math.round(latest);
|
||||
},
|
||||
});
|
||||
|
||||
animate(0, 4, {
|
||||
duration: 2,
|
||||
ease: "circOut",
|
||||
onUpdate: (latest) => {
|
||||
programmingLangues.innerHTML = Math.round(latest);
|
||||
},
|
||||
});
|
||||
2
assets/js/landing.js
Normal file
2
assets/js/landing.js
Normal file
@@ -0,0 +1,2 @@
|
||||
!function(){"use strict";const{animate:e,stagger:n}=Motion,t=document.getElementById("years-experience");if(!t)throw new Error("years-experience Element not found");const o=document.getElementById("programming-languages");if(!o)throw new Error("languages Element not found");e(0,6,{duration:1.5,ease:"circOut",onUpdate:e=>{const n=Math.floor(e);t.innerHTML=String(n)}}),e(0,4,{duration:1.5,ease:"circOut",onUpdate:e=>{const n=Math.floor(e);o.innerHTML=String(n)}}),e("#years-experience",{count:5},{duration:1.5,delay:n(.1)}),e("#languages",{count:5},{duration:1.5,delay:n(.1)})}();
|
||||
//# sourceMappingURL=landing.js.map
|
||||
1
assets/js/landing.js.map
Normal file
1
assets/js/landing.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"landing.js","sources":["../../ts/src/landing.ts"],"sourcesContent":["const { animate, stagger } = Motion;\n\nconst experienceCountSelector = \"#years-experience\";\nconst languagesCountSelector = \"#languages\";\n\nconst yrsExpCount = document.getElementById(\"years-experience\");\nif (!yrsExpCount) {\n throw new Error(\"years-experience Element not found\");\n}\n\nconst langCount = document.getElementById(\"programming-languages\");\nif (!langCount) {\n throw new Error(\"languages Element not found\");\n}\n\nanimate(0, 6, {\n duration: 1.5,\n ease: \"circOut\",\n onUpdate: (latest) => {\n const yrs = Math.floor(latest);\n yrsExpCount.innerHTML = String(yrs);\n },\n});\n\nanimate(0, 4, {\n duration: 1.5,\n ease: \"circOut\",\n onUpdate: (latest) => {\n const languages = Math.floor(latest);\n langCount.innerHTML = String(languages);\n },\n});\n\nanimate(\n experienceCountSelector,\n { count: 5 },\n { duration: 1.5, delay: stagger(0.1) },\n);\nanimate(\n languagesCountSelector,\n { count: 5 },\n { duration: 1.5, delay: stagger(0.1) },\n);\n"],"names":["animate","stagger","Motion","yrsExpCount","document","getElementById","Error","langCount","duration","ease","onUpdate","latest","yrs","Math","floor","innerHTML","String","languages","count","delay"],"mappings":"yBAAA,MAAMA,QAAEA,EAAOC,QAAEA,GAAYC,OAKvBC,EAAcC,SAASC,eAAe,oBAC5C,IAAKF,EACH,MAAM,IAAIG,MAAM,sCAGlB,MAAMC,EAAYH,SAASC,eAAe,yBAC1C,IAAKE,EACH,MAAM,IAAID,MAAM,+BAGlBN,EAAQ,EAAG,EAAG,CACZQ,SAAU,IACVC,KAAM,UACNC,SAAWC,IACT,MAAMC,EAAMC,KAAKC,MAAMH,GACvBR,EAAYY,UAAYC,OAAOJ,EAAI,IAIvCZ,EAAQ,EAAG,EAAG,CACZQ,SAAU,IACVC,KAAM,UACNC,SAAWC,IACT,MAAMM,EAAYJ,KAAKC,MAAMH,GAC7BJ,EAAUQ,UAAYC,OAAOC,EAAU,IAI3CjB,EA/BgC,oBAiC9B,CAAEkB,MAAO,GACT,CAAEV,SAAU,IAAKW,MAAOlB,EAAQ,MAElCD,EAnC+B,aAqC7B,CAAEkB,MAAO,GACT,CAAEV,SAAU,IAAKW,MAAOlB,EAAQ"}
|
||||
2
assets/js/navigation.js
Normal file
2
assets/js/navigation.js
Normal file
@@ -0,0 +1,2 @@
|
||||
!function(){"use strict";const{animate:e,stagger:i}=Motion,t="#mobile-nav>li";document.addEventListener("alpine:init",(()=>{Alpine.data("navbar",(()=>({isOpen:!1,open(){this.isOpen=!0,e(t,{opacity:[0,1],x:[-50,0]},{delay:i(.1)})},toggle(){this.isOpen?this.close():this.open()},close(){setTimeout((()=>{this.isOpen=!1}),300),e(t,{opacity:[1,0],x:[0,50]},{delay:i(.1)})}})))}))}();
|
||||
//# sourceMappingURL=navigation.js.map
|
||||
1
assets/js/navigation.js.map
Normal file
1
assets/js/navigation.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"navigation.js","sources":["../../ts/src/navigation.ts"],"sourcesContent":["const { animate, stagger } = Motion;\n\nconst navItemSelector = \"#mobile-nav>li\";\n\ndocument.addEventListener(\"alpine:init\", () => {\n Alpine.data(\"navbar\", () => {\n return {\n isOpen: false,\n open() {\n this.isOpen = true;\n animate(\n navItemSelector,\n { opacity: [0, 1], x: [-50, 0] },\n { delay: stagger(0.1) },\n );\n },\n toggle() {\n this.isOpen ? this.close() : this.open();\n },\n close() {\n setTimeout(() => {\n this.isOpen = false;\n }, 300);\n animate(\n navItemSelector,\n { opacity: [1, 0], x: [0, 50] },\n { delay: stagger(0.1) },\n );\n },\n };\n });\n});\n"],"names":["animate","stagger","Motion","navItemSelector","document","addEventListener","Alpine","data","isOpen","open","this","opacity","x","delay","toggle","close","setTimeout"],"mappings":"yBAAA,MAAMA,QAAEA,EAAOC,QAAEA,GAAYC,OAEvBC,EAAkB,iBAExBC,SAASC,iBAAiB,eAAe,KACvCC,OAAOC,KAAK,UAAU,KACb,CACLC,QAAQ,EACR,IAAAC,GACEC,KAAKF,QAAS,EACdR,EACEG,EACA,CAAEQ,QAAS,CAAC,EAAG,GAAIC,EAAG,EAAC,GAAK,IAC5B,CAAEC,MAAOZ,EAAQ,KAEpB,EACD,MAAAa,GACEJ,KAAKF,OAASE,KAAKK,QAAUL,KAAKD,MACnC,EACD,KAAAM,GACEC,YAAW,KACTN,KAAKF,QAAS,CAAK,GAClB,KACHR,EACEG,EACA,CAAEQ,QAAS,CAAC,EAAG,GAAIC,EAAG,CAAC,EAAG,KAC1B,CAAEC,MAAOZ,EAAQ,KAEpB,KAEH"}
|
||||
Reference in New Issue
Block a user