fix(Draggable): defer captureGesture to first motion (A22)#84
Conversation
Adds captureGestureTentatively to MouseDownEvent. Tentative captures drop silently on release-without-motion and fall through to normal click dispatch — descendants with onClick now receive their click on a press-without-motion inside a Draggable, no boilerplate needed. First motion promotes the gesture (cancels in-progress selection, fires onMove). dispatchMouseDown returns CapturedGesture instead of GestureHandlers; App.activeGestureTentative tracks the new state. Co-Authored-By: Mark <psyhik17@gmail.com> Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 996827e9b4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (app.activeGestureTentative) { | ||
| app.activeGestureTentative = false |
There was a problem hiding this comment.
Reset click cadence when tentative capture becomes a drag
When a tentative Draggable press receives its first motion, it is now a real drag, but the press-time clickCount/lastClick* state that was updated below remains intact. After a small drag or trackpad jitter, a quick next click within the multi-click window and distance is treated as click #2 and goes through onMultiClick, suppressing the intended onClick; confirmed captures avoid this by resetting clickCount when they short-circuit. Clear the multi-click chain on promotion so promoted tentative drags behave like the existing captured-gesture path.
Useful? React with 👍 / 👎.
Closes #72 (A22). Pairs with #81 (A21) to fully fix #55 (A3).
What
`MouseDownEvent` gains `captureGestureTentatively(handlers)`. Same first-call-wins rule as `captureGesture` (cross-protected — confirmed and tentative compete via the same single-slot field).
`Draggable` switches its press handler to `captureGestureTentatively`. App-level coordinator (`App.tsx`) gets `activeGestureTentative` flag and:
Net effect
`I want clicks!` works on first try. No `stopImmediatePropagation` boilerplate. Same for `` / `` / any clickable child.
Test plan
API surface
Cross-refs
captureGesturelast-call-wins inverts every other DOM "claim" semantic #71 (A21) — pairs with this for the full A3 fix<Draggable>gesture capture eatsonClickon inner children #55 (A3) — can be closed once A22 lands; the click-eating symptom is the union of A21 + A22