feat(ui): add swipe gesture to open/close sidebar on mobile
Swipe right from the left edge (30px zone) opens the sidebar, swipe left when open closes it. Ignores vertical scrolling. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -80,6 +80,51 @@ export function Layout() {
|
|||||||
setMobileNavVisible(true);
|
setMobileNavVisible(true);
|
||||||
}, [isMobile]);
|
}, [isMobile]);
|
||||||
|
|
||||||
|
// Swipe gesture to open/close sidebar on mobile
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isMobile) return;
|
||||||
|
|
||||||
|
const EDGE_ZONE = 30; // px from left edge to start open-swipe
|
||||||
|
const MIN_DISTANCE = 50; // minimum horizontal swipe distance
|
||||||
|
const MAX_VERTICAL = 75; // max vertical drift before we ignore
|
||||||
|
|
||||||
|
let startX = 0;
|
||||||
|
let startY = 0;
|
||||||
|
|
||||||
|
const onTouchStart = (e: TouchEvent) => {
|
||||||
|
const t = e.touches[0]!;
|
||||||
|
startX = t.clientX;
|
||||||
|
startY = t.clientY;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onTouchEnd = (e: TouchEvent) => {
|
||||||
|
const t = e.changedTouches[0]!;
|
||||||
|
const dx = t.clientX - startX;
|
||||||
|
const dy = Math.abs(t.clientY - startY);
|
||||||
|
|
||||||
|
if (dy > MAX_VERTICAL) return; // vertical scroll, ignore
|
||||||
|
|
||||||
|
// Swipe right from left edge → open
|
||||||
|
if (!sidebarOpen && startX < EDGE_ZONE && dx > MIN_DISTANCE) {
|
||||||
|
setSidebarOpen(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swipe left when open → close
|
||||||
|
if (sidebarOpen && dx < -MIN_DISTANCE) {
|
||||||
|
setSidebarOpen(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener("touchstart", onTouchStart, { passive: true });
|
||||||
|
document.addEventListener("touchend", onTouchEnd, { passive: true });
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener("touchstart", onTouchStart);
|
||||||
|
document.removeEventListener("touchend", onTouchEnd);
|
||||||
|
};
|
||||||
|
}, [isMobile, sidebarOpen, setSidebarOpen]);
|
||||||
|
|
||||||
const handleMainScroll = useCallback(
|
const handleMainScroll = useCallback(
|
||||||
(event: UIEvent<HTMLElement>) => {
|
(event: UIEvent<HTMLElement>) => {
|
||||||
if (!isMobile) return;
|
if (!isMobile) return;
|
||||||
|
|||||||
Reference in New Issue
Block a user