${escapeHtml(entry.label || entry.type)}
${formattedDate ? `${escapeHtml(formattedDate)}` : ""}
@@ -107,11 +108,83 @@
container.innerHTML = entries.map(createCard).join("");
};
+ const initProjectsToggle = (entries) => {
+ const projectsGrid = document.getElementById("projects-grid");
+ const toggleShell = document.getElementById("projects-toggle-shell");
+ const toggleButton = document.getElementById("projects-toggle");
+ const defaultVisibleCount = 6;
+
+ if (!projectsGrid || !toggleShell || !toggleButton) {
+ return;
+ }
+
+ const cards = Array.from(projectsGrid.querySelectorAll(".content-card"));
+ if (entries.length <= defaultVisibleCount || cards.length <= defaultVisibleCount) {
+ toggleShell.hidden = true;
+ return;
+ }
+
+ const setExpandedState = (expanded) => {
+ cards.forEach((card, index) => {
+ card.classList.toggle("is-hidden", !expanded && index >= defaultVisibleCount);
+ });
+
+ toggleButton.textContent = expanded ? "Show Fewer Projects" : "Show More Projects";
+ toggleButton.setAttribute("aria-expanded", String(expanded));
+ };
+
+ toggleShell.hidden = false;
+ setExpandedState(false);
+
+ toggleButton.addEventListener("click", () => {
+ const expanded = toggleButton.getAttribute("aria-expanded") === "true";
+ setExpandedState(!expanded);
+ });
+ };
+
+ const compareByNewestDate = (left, right) => {
+ const leftTime = left.date ? Date.parse(`${left.date}T00:00:00`) : Number.NEGATIVE_INFINITY;
+ const rightTime = right.date ? Date.parse(`${right.date}T00:00:00`) : Number.NEGATIVE_INFINITY;
+
+ if (leftTime !== rightTime) {
+ return rightTime - leftTime;
+ }
+
+ const leftOrder = Number.isFinite(left.order) ? left.order : Number.MAX_SAFE_INTEGER;
+ const rightOrder = Number.isFinite(right.order) ? right.order : Number.MAX_SAFE_INTEGER;
+
+ if (leftOrder !== rightOrder) {
+ return leftOrder - rightOrder;
+ }
+
+ return String(left.title || "").localeCompare(String(right.title || ""));
+ };
+
+ const compareByPriorityOrder = (left, right) => {
+ const leftOrder = Number.isFinite(left.order) ? left.order : Number.MAX_SAFE_INTEGER;
+ const rightOrder = Number.isFinite(right.order) ? right.order : Number.MAX_SAFE_INTEGER;
+
+ if (leftOrder !== rightOrder) {
+ return leftOrder - rightOrder;
+ }
+
+ const leftTime = left.date ? Date.parse(`${left.date}T00:00:00`) : Number.NEGATIVE_INFINITY;
+ const rightTime = right.date ? Date.parse(`${right.date}T00:00:00`) : Number.NEGATIVE_INFINITY;
+
+ if (leftTime !== rightTime) {
+ return rightTime - leftTime;
+ }
+
+ return String(left.title || "").localeCompare(String(right.title || ""));
+ };
+
const initListPage = async () => {
try {
const index = await getIndex();
- renderSection("projects-grid", index.projects || [], "No projects added yet.");
- renderSection("updates-grid", index.updates || [], "No updates added yet.");
+ const sortedProjects = [...(index.projects || [])].sort(compareByPriorityOrder);
+ renderSection("projects-grid", sortedProjects, "No projects added yet.");
+ initProjectsToggle(sortedProjects);
+ renderSection("updates-grid", [...(index.updates || [])].sort(compareByNewestDate), "No updates added yet.");
} catch (error) {
renderSection("projects-grid", [], error.message);
renderSection("updates-grid", [], error.message);
diff --git a/public/scripts/hero-effects.js b/public/scripts/hero-effects.js
index 1ef2258..ced719a 100644
--- a/public/scripts/hero-effects.js
+++ b/public/scripts/hero-effects.js
@@ -1,13 +1,7 @@
(function() {
- const hero = document.querySelector(".hero-main");
const heroShell = document.querySelector(".hero-main .hero-shell");
- const profile = document.querySelector(".hero-main .profile");
- const title = document.querySelector(".hero-main .svg-wrapper");
- const descriptions = document.querySelectorAll(
- ".hero-main .hero-description, .hero-main .hero-badges, .hero-main .hero-actions, .hero-main .social-icons"
- );
- if (!hero || !heroShell || !profile || !title) {
+ if (!heroShell) {
return;
}
@@ -25,10 +19,6 @@
const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
- const setTransform = (element, x, y) => {
- element.style.transform = `translate3d(${x}px, ${y}px, 0)`;
- };
-
const animate = () => {
currentX += (targetX - currentX) * 0.065;
currentY += (targetY - currentY) * 0.065;
@@ -51,16 +41,6 @@
heroShell.style.setProperty("--hero-shell-spot-x", `${50 + currentX * 14}%`);
heroShell.style.setProperty("--hero-shell-spot-y", `${28 + currentY * 10}%`);
- heroShell.style.setProperty("--hero-shell-tilt-x", `${currentY * -2.2}deg`);
- heroShell.style.setProperty("--hero-shell-tilt-y", `${currentX * 2.6}deg`);
-
- setTransform(profile, currentX * -4.5, currentY * -4.5);
- setTransform(title, currentX * 2.2, currentY * 2.2);
-
- descriptions.forEach((element, index) => {
- const strength = 1.3 + index * 0.35;
- setTransform(element, currentX * strength, currentY * strength);
- });
requestAnimationFrame(animate);
};