Fix swipe: use passive:false addEventListener on handle to bypass scroll interception
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
2026-05-15 22:44:11 +02:00
parent 7cc3f2521c
commit 100235ca8a
+36 -20
View File
@@ -40,7 +40,39 @@ function HomePage() {
const [artworkIndex, setArtworkIndex] = useState(0); const [artworkIndex, setArtworkIndex] = useState(0);
const isMobile = useMediaQuery('(max-width: 768px)'); const isMobile = useMediaQuery('(max-width: 768px)');
const sheetRef = React.useRef(null); const sheetRef = React.useRef(null);
const handleRef = React.useRef(null);
const dragStartY = React.useRef(null); const dragStartY = React.useRef(null);
React.useEffect(() => {
const handle = handleRef.current;
if (!handle) return;
const onStart = e => { dragStartY.current = e.touches[0].clientY; };
const onMove = e => {
e.preventDefault();
const dy = e.touches[0].clientY - dragStartY.current;
if (dy > 0 && sheetRef.current) sheetRef.current.style.transform = `translateY(${dy}px)`;
};
const onEnd = e => {
const dy = e.changedTouches[0].clientY - dragStartY.current;
if (dy > 80) {
setExpandedCardId(null);
} else if (sheetRef.current) {
sheetRef.current.style.transition = 'transform 0.2s ease';
sheetRef.current.style.transform = '';
setTimeout(() => { if (sheetRef.current) sheetRef.current.style.transition = ''; }, 200);
}
};
handle.addEventListener('touchstart', onStart, { passive: true });
handle.addEventListener('touchmove', onMove, { passive: false });
handle.addEventListener('touchend', onEnd, { passive: true });
return () => {
handle.removeEventListener('touchstart', onStart);
handle.removeEventListener('touchmove', onMove);
handle.removeEventListener('touchend', onEnd);
};
}, [expandedCardId, setExpandedCardId]);
const debouncedSearch = useDebounce(searchTerm, 250); const debouncedSearch = useDebounce(searchTerm, 250);
const loadCards = useCallback(() => fetchCards().then(setCards), []); const loadCards = useCallback(() => fetchCards().then(setCards), []);
@@ -221,26 +253,10 @@ function HomePage() {
{isMobile && expandedCard && ( {isMobile && expandedCard && (
<> <>
<div className="sheet-backdrop" onClick={() => setExpandedCardId(null)} /> <div className="sheet-backdrop" onClick={() => setExpandedCardId(null)} />
<div <div ref={sheetRef} className="bottom-sheet">
ref={sheetRef} <div ref={handleRef} className="sheet-handle-area">
className="bottom-sheet" <div className="sheet-handle" />
onTouchStart={e => { dragStartY.current = e.touches[0].clientY; }} </div>
onTouchMove={e => {
const dy = e.touches[0].clientY - dragStartY.current;
if (dy > 0 && sheetRef.current) sheetRef.current.style.transform = `translateY(${dy}px)`;
}}
onTouchEnd={e => {
const dy = e.changedTouches[0].clientY - dragStartY.current;
if (dy > 80) {
setExpandedCardId(null);
} else if (sheetRef.current) {
sheetRef.current.style.transition = 'transform 0.2s ease';
sheetRef.current.style.transform = '';
setTimeout(() => { if (sheetRef.current) sheetRef.current.style.transition = ''; }, 200);
}
}}
>
<div className="sheet-handle-area"><div className="sheet-handle" /></div>
<div style={{ padding: '12px 16px', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '12px' }}> <div style={{ padding: '12px 16px', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '12px' }}>
{cardDetailContent(expandedCard)} {cardDetailContent(expandedCard)}
</div> </div>