88 lines
2.7 KiB
JavaScript
88 lines
2.7 KiB
JavaScript
(() => {
|
|
const OPENING_MS = 420;
|
|
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
const dashboardGrid = document.querySelector(".dashboard-grid");
|
|
const dashboardLinks = document.querySelectorAll(".dashboard-link-card[href]");
|
|
|
|
if (dashboardGrid) {
|
|
dashboardLinks.forEach((link, index) => {
|
|
link.style.setProperty("--stagger-delay", `${index * 55}ms`);
|
|
});
|
|
|
|
dashboardGrid.classList.add("is-ready");
|
|
window.requestAnimationFrame(() => {
|
|
dashboardGrid.classList.add("is-animated");
|
|
});
|
|
}
|
|
|
|
dashboardLinks.forEach((link) => {
|
|
link.addEventListener("click", (event) => {
|
|
if (link.classList.contains("is-opening")) {
|
|
event.preventDefault();
|
|
return;
|
|
}
|
|
|
|
if (
|
|
event.defaultPrevented ||
|
|
event.button !== 0 ||
|
|
event.metaKey ||
|
|
event.ctrlKey ||
|
|
event.shiftKey ||
|
|
event.altKey
|
|
) {
|
|
return;
|
|
}
|
|
|
|
const href = link.getAttribute("href");
|
|
if (!href || href.startsWith("http")) {
|
|
return;
|
|
}
|
|
|
|
event.preventDefault();
|
|
if (dashboardGrid) {
|
|
dashboardGrid.classList.add("is-focusing");
|
|
}
|
|
link.classList.add("is-opening");
|
|
|
|
// Force layout before running the exit animation for consistent playback.
|
|
void link.offsetWidth;
|
|
|
|
let hasNavigated = false;
|
|
const navigate = () => {
|
|
if (hasNavigated) {
|
|
return;
|
|
}
|
|
hasNavigated = true;
|
|
window.location.href = href;
|
|
};
|
|
|
|
if (typeof link.animate === "function") {
|
|
const animation = link.animate(
|
|
[
|
|
{ opacity: 1, transform: "translateY(-6px) scale(1)", filter: "blur(0px)" },
|
|
{ opacity: 0, transform: "translateY(-42px) scale(0.982)", filter: "blur(2px)" },
|
|
],
|
|
{
|
|
duration: OPENING_MS,
|
|
easing: "cubic-bezier(0.22, 0.61, 0.36, 1)",
|
|
fill: "forwards",
|
|
}
|
|
);
|
|
animation.finished.then(navigate).catch(navigate);
|
|
} else {
|
|
// Fallback if WAAPI is unavailable.
|
|
link.style.transition = `transform ${OPENING_MS}ms cubic-bezier(0.22, 0.61, 0.36, 1), opacity ${OPENING_MS}ms cubic-bezier(0.22, 0.61, 0.36, 1), filter ${OPENING_MS}ms cubic-bezier(0.22, 0.61, 0.36, 1)`;
|
|
requestAnimationFrame(() => {
|
|
link.style.transform = "translateY(-42px) scale(0.982)";
|
|
link.style.opacity = "0";
|
|
link.style.filter = "blur(2px)";
|
|
});
|
|
}
|
|
|
|
window.setTimeout(navigate, OPENING_MS + 240);
|
|
});
|
|
});
|
|
});
|
|
})();
|