fix(ui): restore mobile touch scroll in popover dropdowns inside dialogs

Radix Dialog's modal DismissableLayer calls preventDefault() on pointerdown
events originating outside the Dialog DOM tree. Popover portals render at the
body level (outside the Dialog), so touch events on popover content were
treated as 'outside' — killing scroll gesture recognition on mobile.

Fix: add onPointerDownOutside to NewIssueDialog's DialogContent that detects
events from Radix popper wrappers and calls event.preventDefault() on the
Radix event (not the native event), which skips the Dialog's native
preventDefault and restores touch scrolling.

Also cleans up previous CSS-only workarounds (-webkit-overflow-scrolling,
touch-pan-y on individual buttons) that couldn't override JS preventDefault.
This commit is contained in:
Dotta
2026-03-05 17:04:25 -06:00
parent 0e387426fa
commit c486bad2dd
2 changed files with 14 additions and 5 deletions

View File

@@ -158,10 +158,7 @@ export const InlineEntitySelector = forwardRef<HTMLButtonElement, InlineEntitySe
}
}}
/>
<div
className="max-h-56 overflow-y-auto overscroll-contain py-1 touch-pan-y"
style={{ WebkitOverflowScrolling: "touch" }}
>
<div className="max-h-56 overflow-y-auto overscroll-contain py-1 touch-pan-y">
{filteredOptions.length === 0 ? (
<p className="px-2 py-2 text-xs text-muted-foreground">{emptyMessage}</p>
) : (
@@ -173,7 +170,7 @@ export const InlineEntitySelector = forwardRef<HTMLButtonElement, InlineEntitySe
key={option.id || "__none__"}
type="button"
className={cn(
"flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-sm touch-pan-y",
"flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-sm",
isHighlighted && "bg-accent",
)}
onMouseEnter={() => setHighlightedIndex(index)}

View File

@@ -522,6 +522,18 @@ export function NewIssueDialog() {
: "sm:max-w-lg"
)}
onKeyDown={handleKeyDown}
onPointerDownOutside={(event) => {
// Radix Dialog's modal DismissableLayer calls preventDefault() on
// pointerdown events that originate outside the Dialog DOM tree.
// Popover portals render at the body level (outside the Dialog), so
// touch events on popover content get their default prevented — which
// kills scroll gesture recognition on mobile. Telling Radix "this
// event is handled" skips that preventDefault, restoring touch scroll.
const target = event.detail.originalEvent.target as HTMLElement | null;
if (target?.closest("[data-radix-popper-content-wrapper]")) {
event.preventDefault();
}
}}
>
{/* Header bar */}
<div className="flex items-center justify-between px-4 py-2.5 border-b border-border shrink-0">