Skip to content

Commit 296cbd0

Browse files
committed
fix: dialog backdrop being stuck when closed via swipe
1 parent d1165d0 commit 296cbd0

2 files changed

Lines changed: 52 additions & 250 deletions

File tree

src/shared/ui/dialog.tsx

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,50 @@ function DialogContent({
5858
let closeRef = React.useRef<HTMLButtonElement>(null)
5959
let dragY = useMotionValue(0)
6060
let isBeyondThresholdRef = React.useRef(false)
61+
let dragStartYRef = React.useRef<number | null>(null)
62+
let resetDragOnMount = React.useCallback(
63+
(el: HTMLDivElement | null) => {
64+
if (el) dragY.set(0)
65+
},
66+
[dragY],
67+
)
68+
69+
let onHandlePointerDown = (event: React.PointerEvent<HTMLDivElement>) => {
70+
if (event.button !== 0 && event.pointerType === "mouse") return
71+
dragStartYRef.current = event.clientY
72+
event.currentTarget.setPointerCapture(event.pointerId)
73+
dragY.stop()
74+
}
75+
76+
let onHandlePointerMove = (event: React.PointerEvent<HTMLDivElement>) => {
77+
if (dragStartYRef.current == null) return
78+
let offset = Math.max(0, event.clientY - dragStartYRef.current)
79+
dragY.set(offset)
80+
let isBeyond = offset > SWIPE_CLOSE_THRESHOLD
81+
if (isBeyond !== isBeyondThresholdRef.current) {
82+
isBeyondThresholdRef.current = isBeyond
83+
triggerHaptic()
84+
}
85+
}
86+
87+
let onHandlePointerEnd = (event: React.PointerEvent<HTMLDivElement>) => {
88+
if (dragStartYRef.current == null) return
89+
let offset = Math.max(0, event.clientY - dragStartYRef.current)
90+
dragStartYRef.current = null
91+
isBeyondThresholdRef.current = false
92+
if (event.currentTarget.hasPointerCapture(event.pointerId)) {
93+
event.currentTarget.releasePointerCapture(event.pointerId)
94+
}
95+
if (offset > SWIPE_CLOSE_THRESHOLD) {
96+
animate(dragY, window.innerHeight, {
97+
duration: 0.15,
98+
ease: "easeOut",
99+
onComplete: () => closeRef.current?.click(),
100+
})
101+
} else {
102+
animate(dragY, 0, { type: "spring", stiffness: 300, damping: 25 })
103+
}
104+
}
61105

62106
let contentClassName = cn(
63107
"bg-background ring-foreground/5 fixed z-50 flex max-h-[95dvh] flex-col gap-6 overflow-y-auto p-6 text-sm shadow-lg ring-1 outline-none will-change-transform max-md:duration-200 md:duration-100",
@@ -99,49 +143,23 @@ function DialogContent({
99143
data-slot="dialog-content"
100144
render={
101145
<motion.div
102-
style={{ ...mobileStyle, y: dragY }}
146+
ref={resetDragOnMount}
147+
style={{ ...mobileStyle, y: dragY, transition: "none" }}
103148
className={contentClassName}
104149
/>
105150
}
106151
{...props}
107152
initialFocus={false}
108153
>
109-
<motion.div
110-
drag="y"
111-
dragConstraints={{ top: 0, bottom: 0 }}
112-
dragElastic={0}
113-
style={{ x: 0, y: 0 }}
114-
onDrag={(_, info) => {
115-
let offset = Math.max(0, info.offset.y)
116-
dragY.set(offset)
117-
118-
let isBeyond = offset > SWIPE_CLOSE_THRESHOLD
119-
if (isBeyond !== isBeyondThresholdRef.current) {
120-
isBeyondThresholdRef.current = isBeyond
121-
triggerHaptic()
122-
}
123-
}}
124-
onDragEnd={(_, info) => {
125-
if (info.offset.y > SWIPE_CLOSE_THRESHOLD) {
126-
isBeyondThresholdRef.current = false
127-
animate(dragY, window.innerHeight, {
128-
duration: 0.15,
129-
ease: "easeOut",
130-
onComplete: () => closeRef.current?.click(),
131-
})
132-
} else {
133-
isBeyondThresholdRef.current = false
134-
animate(dragY, 0, {
135-
type: "spring",
136-
stiffness: 300,
137-
damping: 25,
138-
})
139-
}
140-
}}
154+
<div
155+
onPointerDown={onHandlePointerDown}
156+
onPointerMove={onHandlePointerMove}
157+
onPointerUp={onHandlePointerEnd}
158+
onPointerCancel={onHandlePointerEnd}
141159
className="-mt-4 -mb-1 flex cursor-grab touch-none justify-center pt-1 pb-1.5 select-none active:cursor-grabbing pointer-fine:hidden"
142160
>
143161
<div className="bg-muted-foreground/30 h-1.5 w-10 rounded-full" />
144-
</motion.div>
162+
</div>
145163
{children}
146164
{closeButton}
147165
</DialogPrimitive.Popup>

src/shared/ui/drawer.tsx

Lines changed: 0 additions & 216 deletions
This file was deleted.

0 commit comments

Comments
 (0)