Add mouse-wheel scrolling to the package tile row
Client feedback: after removing mouse-drag on the coverflow (it fought the 3D transform), the thin scrollbar underneath was the only desktop way to browse tiles - too fiddly. Hovering the tile row and scrolling the wheel now moves the row horizontally, fluid/1:1 with the wheel delta rather than snapping one card per tick, with scroll-snap briefly suspended during the burst and re-enabled ~150ms after the last tick so cards settle into place afterward - the same pattern already used for the old drag interaction. At the first card, scrolling further "up" is left alone (no preventDefault): the event falls through to native behavior, which is already exactly how the page scrolls today when hovering the row, so the page scrolls up instead. Same at the last card scrolling "down" - the page takes over. Horizontal wheel/trackpad sideswipe (deltaX) is untouched, since the container already handles that natively. Applies uniformly to both strip and coverflow (same scrollerRef container); the scrollbar stays as-is. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
79fc5f2f76
commit
eb59e9c1c9
3 changed files with 63 additions and 22 deletions
|
|
@ -317,8 +317,9 @@ export default function ModelPage() {
|
||||||
|
|
||||||
// Kein Karten-Drag per Maus mehr (Kundenfeedback: fuehlte sich in Kombination mit der
|
// Kein Karten-Drag per Maus mehr (Kundenfeedback: fuehlte sich in Kombination mit der
|
||||||
// 3D-Transformation im Coverflow nicht gut an). Auf dem Desktop navigiert man
|
// 3D-Transformation im Coverflow nicht gut an). Auf dem Desktop navigiert man
|
||||||
// stattdessen ueber die eigene Scroll-Leiste unten; Touch-Geraete behalten ohnehin
|
// stattdessen per Mausrad (siehe Effect weiter unten) oder ueber die eigene
|
||||||
// das native, fluessige Wisch-Scrolling der scroll-snap-Kartenreihe.
|
// Scroll-Leiste; Touch-Geraete behalten ohnehin das native, fluessige
|
||||||
|
// Wisch-Scrolling der scroll-snap-Kartenreihe.
|
||||||
//
|
//
|
||||||
// Stattdessen: einmaliger kurzer Wisch-Hinweis beim ersten Laden auf Touch-Geraeten
|
// Stattdessen: einmaliger kurzer Wisch-Hinweis beim ersten Laden auf Touch-Geraeten
|
||||||
// (Kundenwunsch) - die Reihe faehrt kurz ein Stueck nach rechts und wieder zurueck,
|
// (Kundenwunsch) - die Reihe faehrt kurz ein Stueck nach rechts und wieder zurueck,
|
||||||
|
|
@ -340,6 +341,46 @@ export default function ModelPage() {
|
||||||
};
|
};
|
||||||
}, [layout, data]);
|
}, [layout, data]);
|
||||||
|
|
||||||
|
// Mausrad ueber der Kartenreihe scrollt horizontal (Kundenfeedback: die Scroll-
|
||||||
|
// Leiste allein war als einzige Desktop-Bedienung zu fummelig). Steht man an der
|
||||||
|
// ersten/letzten Karte und "scrollt" in Richtung des Randes hinaus, wird NICHT
|
||||||
|
// abgefangen (kein preventDefault) - der Browser scrollt dann ganz normal die
|
||||||
|
// Seite weiter, genau wie es heute schon passiert, wenn die Kartenreihe keinen
|
||||||
|
// Overflow hat. Reines horizontales Wheel/Trackpad-Sideswipe (deltaX) faellt
|
||||||
|
// schon nativ auf den Container und wird hier nicht angefasst.
|
||||||
|
useEffect(() => {
|
||||||
|
const el = scrollerRef.current;
|
||||||
|
if (layout === 'grid' || !el) return undefined;
|
||||||
|
let snapTimer = 0;
|
||||||
|
|
||||||
|
const onWheel = (e) => {
|
||||||
|
if (Math.abs(e.deltaX) > Math.abs(e.deltaY)) return;
|
||||||
|
const maxScroll = el.scrollWidth - el.clientWidth;
|
||||||
|
if (maxScroll <= 1) return;
|
||||||
|
const atStart = el.scrollLeft <= 1;
|
||||||
|
const atEnd = el.scrollLeft >= maxScroll - 1;
|
||||||
|
if ((e.deltaY < 0 && atStart) || (e.deltaY > 0 && atEnd)) return;
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
// Snap waehrend der Wheel-Boe aussetzen (wie beim frueheren Ziehen), sonst
|
||||||
|
// kaempft scroll-snap gegen schnell aufeinanderfolgende Wheel-Ticks. Der
|
||||||
|
// Nachlauf-Timer wird bei jedem Tick verlaengert, rastet also erst kurz
|
||||||
|
// nach dem letzten Tick der Boe wieder ein.
|
||||||
|
el.style.scrollSnapType = 'none';
|
||||||
|
el.scrollLeft += e.deltaY;
|
||||||
|
clearTimeout(snapTimer);
|
||||||
|
snapTimer = setTimeout(() => {
|
||||||
|
el.style.scrollSnapType = '';
|
||||||
|
}, 150);
|
||||||
|
};
|
||||||
|
|
||||||
|
el.addEventListener('wheel', onWheel, { passive: false });
|
||||||
|
return () => {
|
||||||
|
el.removeEventListener('wheel', onWheel);
|
||||||
|
clearTimeout(snapTimer);
|
||||||
|
};
|
||||||
|
}, [layout, data]);
|
||||||
|
|
||||||
// Eigene, zum Design passende Scroll-Leiste unter der Kartenreihe (Strip + Coverflow):
|
// Eigene, zum Design passende Scroll-Leiste unter der Kartenreihe (Strip + Coverflow):
|
||||||
// die native Browser-Leiste ist ausgeblendet, stattdessen ein schmaler zentrierter
|
// die native Browser-Leiste ist ausgeblendet, stattdessen ein schmaler zentrierter
|
||||||
// Track mit markengruenem, leuchtendem Daumen. Daumen ist ziehbar, Klick auf den
|
// Track mit markengruenem, leuchtendem Daumen. Daumen ist ziehbar, Klick auf den
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -43,7 +43,7 @@
|
||||||
"sameAs": ["https://www.youtube.com/@hifiplanet2812"]
|
"sameAs": ["https://www.youtube.com/@hifiplanet2812"]
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script type="module" crossorigin src="/assets/index-D7QmGTZX.js"></script>
|
<script type="module" crossorigin src="/assets/index-3Dk2mE1-.js"></script>
|
||||||
<link rel="modulepreload" crossorigin href="/assets/lucide-icons-CnpfS6R8.js">
|
<link rel="modulepreload" crossorigin href="/assets/lucide-icons-CnpfS6R8.js">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-9666bnLb.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-9666bnLb.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue