From 493db7aa2eab3ad997f573382ebbbe3f3fbdd342 Mon Sep 17 00:00:00 2001 From: dragonwocky Date: Thu, 18 Jan 2024 16:01:46 +1100 Subject: [PATCH] fix(panel): debounce peek trigger e.g. do not show if mouse is moved quickly out of the window --- src/core/client.mjs | 1 + src/core/islands/Panel.mjs | 20 ++++++++++++++------ src/core/islands/TopbarButton.mjs | 2 +- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/core/client.mjs b/src/core/client.mjs index 9e92adf..c92197b 100644 --- a/src/core/client.mjs +++ b/src/core/client.mjs @@ -183,6 +183,7 @@ const insertPanel = async (api, db) => { appendToDom(); useState(["panelOpen"], ([panelOpen]) => { + console.log(panelOpen); if (panelOpen) $panelTopbarBtn.setAttribute("data-active", true); else $panelTopbarBtn.removeAttribute("data-active"); }); diff --git a/src/core/islands/Panel.mjs b/src/core/islands/Panel.mjs index b371bcd..0911918 100644 --- a/src/core/islands/Panel.mjs +++ b/src/core/islands/Panel.mjs @@ -136,7 +136,7 @@ function Panel({ `; - let preDragWidth, dragStartX; + let preDragWidth, dragStartX, _animatedAt; const getWidth = async (width) => { if (width && !isNaN(width)) { width = Math.max(width, minWidth); @@ -150,6 +150,10 @@ function Panel({ .querySelectorAll("[tabindex]") .forEach(($el) => ($el.tabIndex = interactive ? 1 : -1)); }, + isAnimated = () => { + if (!_animatedAt) return false; + return Date.now() - _animatedAt <= transitionDuration; + }, isDragging = () => !isNaN(preDragWidth) && !isNaN(dragStartX), isPinned = () => $panel.hasAttribute("data-pinned"), isPeeked = () => $panel.hasAttribute("data-peeked"), @@ -177,14 +181,14 @@ function Panel({ boxShadow: "none", }; - const animationState = {}, + const animationState = { ...closedWidth }, easing = "cubic-bezier(0.4, 0, 0.2, 1)", animate = ($target, keyframes) => { const opts = { fill: "forwards", duration: transitionDuration, easing }; $target.animate(keyframes, opts); - console.log($target, keyframes); }, animatePanel = (to) => { + _animatedAt = Date.now(); animate($panel.lastElementChild, [animationState, to]); Object.assign(animationState, to); }; @@ -243,18 +247,22 @@ function Panel({ // hovering over the peek trigger will temporarily // pop out an interactive preview of the panel + let _peekDebounce; const $peekTrigger = html`
`; $panel.prepend($peekTrigger); $panel.addEventListener("mouseout", () => { - if (isDragging() || isPinned()) return; + if (isDragging() || isAnimated() || isPinned()) return; if (!$panel.matches(":hover")) $panel.close(); }); $panel.addEventListener("mouseover", () => { - if (isClosed() && $panel.matches(":hover")) $panel.peek(); + _peekDebounce ??= setTimeout(() => { + if (isClosed() && $panel.matches(":hover")) $panel.peek(); + _peekDebounce = undefined; + }, 100); }); // moves help button out of the way of open panel. diff --git a/src/core/islands/TopbarButton.mjs b/src/core/islands/TopbarButton.mjs index 4c95ecf..6f4cd95 100644 --- a/src/core/islands/TopbarButton.mjs +++ b/src/core/islands/TopbarButton.mjs @@ -13,7 +13,7 @@ function TopbarButton({ icon, ...props }, ...children) { user-select-none h-[28px] w-[33px] duration-[20ms] transition inline-flex items-center justify-center mr-[2px] rounded-[3px] hover:bg-[color:var(--theme--bg-hover)] - [data-active]:bg-[color:var(--theme--bg-hover)]`, + &[data-active]:bg-[color:var(--theme--bg-hover)]`, }); return html`