fix(editor): Tracks-pane faders can be dragged again - #323
Merged
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughTrack-row controls now temporarily disable row dragging during pointer gestures, preventing accidental reordering from faders and other controls. Row-body dragging remains enabled, and regression tests cover restoration, cancellation, and listener cleanup. ChangesTrack control drag handling
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Two testers hit this: a fader could only be clicked to jump the thumb to a new
position, and "you have like a split second to move before it goes into drag-
the-track mode".
Track rows carry draggable="true" for reorder, so a native drag beginning
anywhere inside one steals the gesture. A plain click looked fine only because
it never moved far enough to pass the browser's drag threshold; any real drag
handed the pointer to the row reorder.
The guard cannot live in dragstart. The drag source is the ROW, so
dragstart.target is the row and not the control under the pointer — the two are
indistinguishable there. Confirmed in Chromium against a minimal repro:
dragstart.target on a row containing a range input:
"guard | closestInput=false"
guard at dragstart : value 53.0 -> 55.0 dragover=24 (drag stole it)
draggable toggle : value 53.0 -> 101.0 dragover=0 (fader kept it)
draggable="false" on the input is inert for the same reason: the drag source
resolves to the nearest draggable ancestor regardless.
So the row is taken out of the drag on pointerdown when the gesture starts on a
form control, and put back on pointerup/pointercancel. Reorder from the row body
is untouched.
Note this leaves the existing rename-input branch in the dragstart handler as
dead code — it tests the same target that can never match. Left alone here to
keep the diff to the reported bug; worth removing on its own.
Tests: tests/track_session_fader_row_drag.test.mjs — the row leaves the drag on
a fader press (fails on main), comes back on release, comes back on cancel, is
untouched by a press on the row body, and does not leak a pointerup listener per
gesture. Distinct from tests/track_session_fader_drag.test.mjs, which covers the
innerHTML rebuild destroying the slider mid-drag; either break alone kills the
fader, so both are pinned.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: ChrisBeWithYou <chris@rifflarr.local>
ChrisBeWithYou
force-pushed
the
fix/editor-track-fader-row-drag
branch
from
July 19, 2026 08:20
5990b1b to
7c976d9
Compare
The rename-input branch in the track-row dragstart handler tested
event.target.closest('[data-track-rename-input]'). The drag source is the ROW,
so event.target is always the row and never the control under the pointer —
the selector could not match, and the branch has never fired.
It was trying to keep a control's gesture out of the row reorder, which the
preceding commit now does correctly at pointerdown by taking the row out of the
drag. The rename input is a form control, so it is covered by that path; the
suite now pins it, which is what makes deleting this safe rather than merely
tidy.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: ChrisBeWithYou <chris@rifflarr.local>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Reported twice by testers:
Cause
Track rows carry
draggable="true"for reorder, so a native HTML5 drag beginning anywhere inside one steals the gesture. A plain click looked fine only because it never moved far enough to pass the browser's drag threshold — the "split second" is exactly that threshold.Why the obvious fix doesn't work
The guard cannot live in
dragstart. The drag source is the row, sodragstart.targetis the row, not the control under the pointer — they're indistinguishable there. I confirmed this in Chromium against a minimal repro before settling on the approach:draggable="false"on the input is inert for the same reason: the drag source resolves to the nearest draggable ancestor regardless of the child's own attribute.I mention this because I wrote the
dragstartversion first and it passed a unit test — the test constructed the event withtargetset to the fader, which is not what the browser does. The browser check is what caught it.The fix
The row drops out of the drag on
pointerdownwhen the gesture starts on a form control, and rejoins onpointerup/pointercancel. Reorder from the row body is untouched.Note for a follow-up
This leaves the existing rename-input branch in the
dragstarthandler as dead code — it tests the sametargetthat can never match, so it has presumably never fired. I left it alone to keep this diff scoped to the reported bug, but it's worth removing on its own.Tests
tests/track_session_fader_row_drag.test.mjs— the row leaves the drag on a fader press (fails on main), comes back on release, comes back on cancel, is untouched by a press on the row body, and doesn't leak apointeruplistener per gesture.Distinct from
tests/track_session_fader_drag.test.mjs, which covers the innerHTML rebuild destroying the slider mid-drag. Either break alone kills the fader, so both are now pinned.🤖 Generated with Claude Code
Summary by CodeRabbit