From 965b0e143cb94f52fb41ee6b01bae04643c2e9a1 Mon Sep 17 00:00:00 2001 From: pewdiepie-archdaemon Date: Wed, 10 Jun 2026 23:00:29 +0900 Subject: [PATCH] Email accounts strip: wheel + grab-drag horizontal scroll MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The single-row chip strip relied on native horizontal scroll, which is hard to reach without a horizontal wheel. Wire two scroll mechanisms on the strip once it's rendered: - Vertical wheel → horizontal scroll (intercept only when overflow exists and the wheel motion is primarily vertical, so normal page scroll still works elsewhere). - Mouse grab-and-drag: cursor goes grab/grabbing, mousedown→move bumps scrollLeft by the cursor delta. A 5px drag threshold cancels the chip click so the user can drag-scroll without accidentally switching accounts. --- static/js/emailLibrary.js | 47 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/static/js/emailLibrary.js b/static/js/emailLibrary.js index 7638224b1..25c2498d3 100644 --- a/static/js/emailLibrary.js +++ b/static/js/emailLibrary.js @@ -1344,6 +1344,53 @@ function _renderAccountsStrip() { _loadEmails({ force: true, useCache: false }); }); }); + // Idempotent — wire wheel + grab-drag scroll once per strip element. + if (!strip._scrollWired) { + strip._scrollWired = true; + // Vertical wheel → horizontal scroll. Only intercept when there's + // actually horizontal overflow to scroll through, otherwise let the + // page do its normal vertical scroll. + strip.addEventListener('wheel', (e) => { + if (strip.scrollWidth <= strip.clientWidth) return; + if (Math.abs(e.deltaY) <= Math.abs(e.deltaX)) return; + e.preventDefault(); + strip.scrollLeft += e.deltaY; + }, { passive: false }); + // Click-and-drag scroll. Track mousedown, then mousemove deltas + // bump scrollLeft. Cancel a chip click if the user actually dragged + // more than a few pixels. + let dragging = false; + let startX = 0; + let startScroll = 0; + let moved = 0; + strip.style.cursor = 'grab'; + strip.addEventListener('mousedown', (e) => { + if (e.button !== 0) return; + dragging = true; + moved = 0; + startX = e.pageX; + startScroll = strip.scrollLeft; + strip.style.cursor = 'grabbing'; + strip.style.userSelect = 'none'; + }); + window.addEventListener('mousemove', (e) => { + if (!dragging) return; + const dx = e.pageX - startX; + moved = Math.max(moved, Math.abs(dx)); + strip.scrollLeft = startScroll - dx; + }); + window.addEventListener('mouseup', () => { + if (!dragging) return; + dragging = false; + strip.style.cursor = 'grab'; + strip.style.userSelect = ''; + }); + // Swallow chip clicks fired after a real drag — the user meant to scroll, + // not select. + strip.addEventListener('click', (e) => { + if (moved > 5) { e.stopPropagation(); e.preventDefault(); moved = 0; } + }, true); + } _publishActiveAccount(); }