diff --git a/src/pages/SetsPage.jsx b/src/pages/SetsPage.jsx index 46d52f4..e5451d6 100644 --- a/src/pages/SetsPage.jsx +++ b/src/pages/SetsPage.jsx @@ -110,6 +110,42 @@ function SetsPage() { const [searchTerm, setSearchTerm] = useState(''); const [expandedCardId, setExpandedCardId] = useState(null); const isMobile = useMediaQuery('(max-width: 768px)'); + const sheetRef = React.useRef(null); + const handleRef = React.useRef(null); + const dragStartY = React.useRef(null); + + const closeSheet = React.useCallback(() => { setSelectedSet(null); setSetCards([]); }, []); + + 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) { + closeSheet(); + } 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); + }; + }, [selectedSet, closeSheet]); useEffect(() => { fetchSets().then(setSets).catch(console.error).finally(() => setLoading(false)); @@ -204,9 +240,9 @@ function SetsPage() { {/* Mobile: bottom sheet */} {isMobile && selectedSet && ( <> -
{ setSelectedSet(null); setSetCards([]); }} /> -
-
+
+
+
{setDetail}