1- import { useCallback , useId , type ReactNode } from "react" ;
1+ import {
2+ useCallback ,
3+ useEffect ,
4+ useId ,
5+ useRef ,
6+ type ReactNode ,
7+ } from "react" ;
28import { clx } from "~/sdk/clx" ;
39import { useEscapeKey } from "../../sdk/useEscapeKey" ;
410import Icon from "./Icon" ;
@@ -24,6 +30,42 @@ function Drawer(
2430
2531 useEscapeKey ( closeViaCheckbox ) ;
2632
33+ // Swipe-to-close: a horizontal swipe toward the edge the drawer opened from
34+ // closes it (the expected mobile gesture). Gesture-only — we let DaisyUI run
35+ // its own close transition rather than fighting it with a live drag transform.
36+ const asideRef = useRef < HTMLElement > ( null ) ;
37+ useEffect ( ( ) => {
38+ const aside = asideRef . current ;
39+ const root = aside ?. closest ( ".drawer" ) ;
40+ if ( ! aside || ! root ) return ;
41+ const closesRightward = root . classList . contains ( "drawer-end" ) ;
42+ let startX = 0 ;
43+ let startY = 0 ;
44+ let tracking = false ;
45+ const onDown = ( e : PointerEvent ) => {
46+ const input = document . getElementById ( toggleId ) as HTMLInputElement | null ;
47+ if ( ! input ?. checked ) return ; // only while open
48+ startX = e . clientX ;
49+ startY = e . clientY ;
50+ tracking = true ;
51+ } ;
52+ const onUp = ( e : PointerEvent ) => {
53+ if ( ! tracking ) return ;
54+ tracking = false ;
55+ const dx = e . clientX - startX ;
56+ const dy = e . clientY - startY ;
57+ // Require a clearly horizontal swipe so vertical scrolling is unaffected.
58+ if ( Math . abs ( dx ) < 60 || Math . abs ( dx ) < Math . abs ( dy ) ) return ;
59+ if ( closesRightward ? dx > 0 : dx < 0 ) closeViaCheckbox ( ) ;
60+ } ;
61+ aside . addEventListener ( "pointerdown" , onDown ) ;
62+ aside . addEventListener ( "pointerup" , onUp ) ;
63+ return ( ) => {
64+ aside . removeEventListener ( "pointerdown" , onDown ) ;
65+ aside . removeEventListener ( "pointerup" , onUp ) ;
66+ } ;
67+ } , [ toggleId , closeViaCheckbox ] ) ;
68+
2769 return (
2870 < div className = { clx ( "drawer" , _class ) } >
2971 < input
@@ -40,6 +82,7 @@ function Drawer(
4082 </ div >
4183
4284 < aside
85+ ref = { asideRef }
4386 data-aside
4487 className = { clx (
4588 "drawer-side h-full z-40 overflow-hidden" ,
0 commit comments