fix(panel): debounce peek trigger

e.g. do not show if mouse is moved quickly out of the window
This commit is contained in:
dragonwocky 2024-01-18 16:01:46 +11:00
parent c722c7f854
commit 493db7aa2e
Signed by: dragonwocky
GPG Key ID: 7998D08F7D7BD7A8
3 changed files with 16 additions and 7 deletions

View File

@ -183,6 +183,7 @@ const insertPanel = async (api, db) => {
appendToDom(); appendToDom();
useState(["panelOpen"], ([panelOpen]) => { useState(["panelOpen"], ([panelOpen]) => {
console.log(panelOpen);
if (panelOpen) $panelTopbarBtn.setAttribute("data-active", true); if (panelOpen) $panelTopbarBtn.setAttribute("data-active", true);
else $panelTopbarBtn.removeAttribute("data-active"); else $panelTopbarBtn.removeAttribute("data-active");
}); });

View File

@ -136,7 +136,7 @@ function Panel({
</aside> </aside>
</div>`; </div>`;
let preDragWidth, dragStartX; let preDragWidth, dragStartX, _animatedAt;
const getWidth = async (width) => { const getWidth = async (width) => {
if (width && !isNaN(width)) { if (width && !isNaN(width)) {
width = Math.max(width, minWidth); width = Math.max(width, minWidth);
@ -150,6 +150,10 @@ function Panel({
.querySelectorAll("[tabindex]") .querySelectorAll("[tabindex]")
.forEach(($el) => ($el.tabIndex = interactive ? 1 : -1)); .forEach(($el) => ($el.tabIndex = interactive ? 1 : -1));
}, },
isAnimated = () => {
if (!_animatedAt) return false;
return Date.now() - _animatedAt <= transitionDuration;
},
isDragging = () => !isNaN(preDragWidth) && !isNaN(dragStartX), isDragging = () => !isNaN(preDragWidth) && !isNaN(dragStartX),
isPinned = () => $panel.hasAttribute("data-pinned"), isPinned = () => $panel.hasAttribute("data-pinned"),
isPeeked = () => $panel.hasAttribute("data-peeked"), isPeeked = () => $panel.hasAttribute("data-peeked"),
@ -177,14 +181,14 @@ function Panel({
boxShadow: "none", boxShadow: "none",
}; };
const animationState = {}, const animationState = { ...closedWidth },
easing = "cubic-bezier(0.4, 0, 0.2, 1)", easing = "cubic-bezier(0.4, 0, 0.2, 1)",
animate = ($target, keyframes) => { animate = ($target, keyframes) => {
const opts = { fill: "forwards", duration: transitionDuration, easing }; const opts = { fill: "forwards", duration: transitionDuration, easing };
$target.animate(keyframes, opts); $target.animate(keyframes, opts);
console.log($target, keyframes);
}, },
animatePanel = (to) => { animatePanel = (to) => {
_animatedAt = Date.now();
animate($panel.lastElementChild, [animationState, to]); animate($panel.lastElementChild, [animationState, to]);
Object.assign(animationState, to); Object.assign(animationState, to);
}; };
@ -243,18 +247,22 @@ function Panel({
// hovering over the peek trigger will temporarily // hovering over the peek trigger will temporarily
// pop out an interactive preview of the panel // pop out an interactive preview of the panel
let _peekDebounce;
const $peekTrigger = html`<div const $peekTrigger = html`<div
class="absolute z-10 right-0 h-[calc(100vh-120px)] bottom-[60px] w-[64px] class="absolute z-10 right-0 h-[calc(100vh-120px)] bottom-[60px] w-[96px]
group-&[data-peeked]/panel:(w-[calc(var(--panel--width,0)+8px)]) group-&[data-peeked]/panel:(w-[calc(var(--panel--width,0)+8px)])
group-&[data-pinned]/panel:(w-[calc(var(--panel--width,0)+8px)])" group-&[data-pinned]/panel:(w-[calc(var(--panel--width,0)+8px)])"
></div>`; ></div>`;
$panel.prepend($peekTrigger); $panel.prepend($peekTrigger);
$panel.addEventListener("mouseout", () => { $panel.addEventListener("mouseout", () => {
if (isDragging() || isPinned()) return; if (isDragging() || isAnimated() || isPinned()) return;
if (!$panel.matches(":hover")) $panel.close(); if (!$panel.matches(":hover")) $panel.close();
}); });
$panel.addEventListener("mouseover", () => { $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. // moves help button out of the way of open panel.

View File

@ -13,7 +13,7 @@ function TopbarButton({ icon, ...props }, ...children) {
user-select-none h-[28px] w-[33px] duration-[20ms] user-select-none h-[28px] w-[33px] duration-[20ms]
transition inline-flex items-center justify-center mr-[2px] transition inline-flex items-center justify-center mr-[2px]
rounded-[3px] hover:bg-[color:var(--theme--bg-hover)] 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`<button ...${props}> return html`<button ...${props}>
<i <i