dex/src/lib/sheet-drag.js
chris 5bce0f93f3 Fix swipe hijacking h-scroll; drag bottom sheets down to dismiss
- onSwipe: before claiming a horizontal page-swipe, walk up from the
  touch target for an overflow-x auto/scroll ancestor that can still
  scroll that way (tab strip, moves list, coverage grid) and bail if
  found — sliding those no longer flips to the next Pokémon.
- segThumb: retry placement until the seg is laid out, and observe it for
  resizes, so the sliding pill is positioned on first paint instead of
  only after the first click. Dropped the :has() selector for a
  JS-applied .seg--thumbed class.
- New lib/sheet-drag.js: drag the game sheet / Pokémon picker down by its
  header to dismiss (past ~110px or a flick), else it springs back.
  Header gets touch-action:none + a grab cursor.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ve7HLspzeG2xDPtJQ8vmu
2026-09-10 09:39:16 -04:00

44 lines
1.3 KiB
JavaScript

/**
* Drag a bottom sheet down by its handle to dismiss it. `panel` is the
* `.gsheet`, `handle` the grab area (its header), `close` the dismiss fn.
* Past ~110px (or a quick flick) it closes; otherwise it springs back.
*/
export function dragToClose(panel, handle, close) {
let y0 = 0;
let dy = 0;
let t0 = 0;
let dragging = false;
const start = (e) => {
if (e.touches.length !== 1) return;
y0 = e.touches[0].clientY;
dy = 0;
t0 = Date.now();
dragging = true;
panel.style.transition = 'none';
};
const move = (e) => {
if (!dragging) return;
dy = e.touches[0].clientY - y0;
// Rubber-band an upward pull; follow a downward one.
const shown = dy < 0 ? dy * 0.25 : dy;
panel.style.transform = `translateY(${shown}px)`;
if (dy > 0) e.preventDefault();
};
const end = () => {
if (!dragging) return;
dragging = false;
panel.style.transition = '';
panel.style.transform = '';
const flick = dy > 40 && Date.now() - t0 < 300;
if (dy > 110 || flick) close();
};
handle.addEventListener('touchstart', start, { passive: true });
handle.addEventListener('touchmove', move, { passive: false });
handle.addEventListener('touchend', end, { passive: true });
handle.addEventListener('touchcancel', end, { passive: true });
}