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);
|
||||
}, [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(
|
||||
(event: UIEvent<HTMLElement>) => {
|
||||
if (!isMobile) return;
|
||||
|
||||
Reference in New Issue
Block a user