From f2a33a9164792499bd4f69e0c83862080656ac37 Mon Sep 17 00:00:00 2001 From: th Date: Wed, 15 Apr 2026 21:20:27 +0200 Subject: [PATCH] bucket-bar: hide scrollbar, soft edge fades, wheel-to-scroll MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The horizontal scrollbar on the bucket row was ugly and inconsistent with the rest of the app's scrollbar-less panels. Hide it, redirect vertical wheel over the bar to horizontal scroll, and surface overflow with soft bg-coloured gradients on whichever side has more content off-screen: right only while anchored at the start, both in the middle, left only at the end. Fade overlays live on #bucket-row (parent) as pseudo-elements with pointer-events:none, rather than mask-image on the bar itself — a mask would also clip super-bucket popovers that are intentionally rendered inside #bucket-bar for the collab MutationObserver. Co-Authored-By: Claude Opus 4.6 (1M context) --- config.php | 2 +- electron/package.json | 2 +- public/css/style.css | 44 ++++++++++++++++++++++++++++++++++++ public/js/modules/buckets.js | 37 ++++++++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 2 deletions(-) diff --git a/config.php b/config.php index 616d4cb..febdef0 100644 --- a/config.php +++ b/config.php @@ -1,7 +1,7 @@ 2; + const canRight = bar.scrollLeft + bar.clientWidth < bar.scrollWidth - 2; + barRow.classList.toggle('fade-left', canLeft && !canRight); + barRow.classList.toggle('fade-right', !canLeft && canRight); + barRow.classList.toggle('fade-both', canLeft && canRight); + // Right-side fade overlay is anchored to the parent's right edge; + // the actual bar ends before the toolbar toggles. Compute the + // distance so the gradient lines up with the bar's right edge. + const rowRect = barRow.getBoundingClientRect(); + const barRect = bar.getBoundingClientRect(); + const rightInset = Math.max(0, rowRect.right - barRect.right); + barRow.style.setProperty('--bucket-row-right-inset', rightInset + 'px'); +} +if (bar) { + bar.addEventListener('wheel', (e) => { + if (e.deltaY === 0) return; + if (bar.scrollWidth <= bar.clientWidth) return; + e.preventDefault(); + bar.scrollLeft += e.deltaY; + }, { passive: false }); + bar.addEventListener('scroll', updateBucketBarFades, { passive: true }); + window.addEventListener('resize', updateBucketBarFades); + new MutationObserver(updateBucketBarFades).observe(bar, { childList: true, subtree: false }); + updateBucketBarFades(); +} + /** Switch the active bucket without going through the click path — * used by the number-key hotkeys (and any other code that wants to * activate a bucket programmatically without triggering the super-