Skip to content

Confine the drag press-and-hold delay to touch input - #15186

Open
akolson wants to merge 1 commit into
learningequality:developfrom
akolson:drag-n-drop
Open

Confine the drag press-and-hold delay to touch input#15186
akolson wants to merge 1 commit into
learningequality:developfrom
akolson:drag-n-drop

Conversation

@akolson

@akolson akolson commented Aug 13, 2026

Copy link
Copy Markdown
Member

Summary

This PR fixes drag-and-drop reordering of channels with a mouse.

The drag system configures SortableJS with a 250ms press-and-hold delay to prevent touch dragging from interfering with page scrolling. That delay was also being applied to mouse input. Because a mouse drag normally involves pressing and immediately moving, SortableJS would cancel the pending drag before it started, making reordering appear broken. The drag would only work if the user held the mouse still for the full 250ms before moving.

Setting delayOnTouchOnly: true limits the delay to touch input, where it is needed, while allowing mouse drags to start immediately.

Before:

Grabacion.de.pantalla.2026-08-10.a.la.s.10.50.37.a.m.mov

After:

Screen.Recording.2026-08-13.at.17.26.33.mov

References

Fixes #15175

Reviewer guidance

  1. Sign in as a device admin (or a user with content management permission)
  2. Go to Device > Manage channels
  3. Click "Edit channel order"
  4. Attempt to drag a channel row to reorder it
  5. (Additional guidance can be found on Drag and drop not working on Rearrange Channels page #15175)

AI usage

Used Claude Code to investigate the bug, identify the root cause and propose the fix. It verified the change against a running instance and added a regression test. I reviewed the diagnosis, the fix and the test before opening this PR.

@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

@akolson akolson added TODO: needs review Waiting for review TODO: needs QA re-review For stale issues that need to be revisited bug Behavior is wrong or broken APP: Device Re: Device App (content import/export, facility-syncing, user permissions, etc.) DEV: frontend and removed TODO: needs QA re-review For stale issues that need to be revisited labels Aug 13, 2026
@akolson
akolson requested a review from rtibblesbot August 13, 2026 14:54
@rtibblesbot

rtibblesbot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

🔵 Review posted

Last updated: 2026-08-13 16:02 UTC

@rtibblesbot rtibblesbot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #15186 — the fix is correct and minimal. Traced SortableJS 1.15.7: _prepareDragStart gates the delay on options.delay && (!options.delayOnTouchOnly || touch), and during the delay window _delayedDragTouchMoveHandler cancels the drag once the pointer moves past touchStartThreshold (devicePixelRatio || 1, i.e. 1px) — so a mouse drag was cancelled instantly. delayOnTouchOnly: true resolves it for mouse while keeping the hold for touch.

CI passing. No UI QA run — the behaviour is a pointer-timing interaction that jsdom can't reproduce; live verification is worth doing before merge.

AC3 (other consumers) is met: new Sortable(...) appears once in the tree (useDraggableRegion.js:223) and spreads sortableDefaults, so LessonResourcesTable, QuestionsAccordion, SectionOrder, OrderInteraction and RearrangeChannelsPage all pick it up; none override delay.

One suggestion and one nitpick inline. Worth noting: touch in SortableJS excludes pointerType === 'pen', so a stylus drag now starts on first movement — arguably right (a pen is precise), but on Android a stylus also scrolls, so the scroll-vs-drag conflict returns for that input. SortableJS offers no pen-inclusive variant; flagging as information only.


@rtibblesbot's comments are generated by an LLM, and should be evaluated accordingly

How was this generated?

Ran a phased review pipeline over the pull request diff:

  • Classified the diff to select review passes (core, frontend, backend) and whether manual QA was required
  • Core review pass checked correctness, design, architecture, testing, completeness, and DRY/SRP/Rule-of-Three principles
  • Specialized frontend/backend review passes applied framework-specific lenses where those files changed
  • For UI changes: manual QA and an accessibility audit against a live dev server, when available
  • Checked CI status and linked issue acceptance criteria
  • Synthesized one review from those passes and chose the verdict from the findings, CI status, and QA evidence

Comment thread packages/kolibri-common/components/draggable/__tests__/DraggableRegion.spec.js Outdated
The 250ms press-and-hold delay exists so that a touch drag does not
fight the page scroll, but it was applied to every input device. While
a delayed drag is pending, SortableJS cancels it as soon as the pointer
moves further than touchStartThreshold (1px). A mouse drag is performed
by pressing and immediately moving, so that movement landed inside the
250ms window and the gesture was discarded before it began, silently.
Rows only picked up when the user happened to hold still for a full
quarter second first, which is why dragging appeared broken yet worked
occasionally.

delayOnTouchOnly confines the delay to touch input, where it is needed,
and lets a mouse drag begin on the first movement. The option lives on
the shared universe defaults, so every region gets it.

Fixes learningequality#15175

@rtibblesbot rtibblesbot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #15186 — 2 of 2 prior findings resolved; no new findings.

Prior-finding status

RESOLVED — packages/kolibri-common/components/draggable/tests/DraggableRegion.spec.js:59 — drop the delay assertion pinning an unchanged default
RESOLVED — packages/kolibri-common/components/draggable/useDraggableUniverse.js:56 — consumer-facing docs still described a device-agnostic delay


@rtibblesbot's comments are generated by an LLM, and should be evaluated accordingly

How was this generated?

Compared the current PR state against findings from a prior review:

  • Retrieved prior bot reviews via the GitHub API
  • Classified each prior finding as RESOLVED, UNADDRESSED, ACKNOWLEDGED, or CONTESTED
  • Only raised NEW findings for newly introduced code
  • Ran the same phased review passes as a first review (core, frontend/backend lenses, manual QA when required)
  • Synthesized one review from the passes and chose the verdict from the findings, CI status, and QA evidence

@rtibbles rtibbles self-assigned this Aug 13, 2026

@habibayman habibayman left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Code changes are minimal and LGTM
  • Ran it locally and it works as expected

Thank you Alan!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

APP: Device Re: Device App (content import/export, facility-syncing, user permissions, etc.) bug Behavior is wrong or broken DEV: frontend SIZE: small TODO: needs review Waiting for review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Drag and drop not working on Rearrange Channels page

4 participants