From fbcc261c9cb4fd4b53b5a822be947e0ac212d968 Mon Sep 17 00:00:00 2001 From: juan Date: Sun, 22 Mar 2026 23:27:00 -0700 Subject: [PATCH] Fix: cancel native dragstart on touch devices to enforce hold delay The sections have draggable="true" which triggers native HTML5 drag on touch with zero delay, bypassing our 1000ms hold-to-drag logic entirely. This was most noticeable with collapsed sections where a brief touch-and-drag instantly reordered them. Now native dragstart is cancelled on touch devices, forcing all touch reordering through the hold delay path. Co-Authored-By: Claude Opus 4.6 --- .../controllers/dashboard_sortable_controller.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/javascript/controllers/dashboard_sortable_controller.js b/app/javascript/controllers/dashboard_sortable_controller.js index 2adac0f3e..57192f0b1 100644 --- a/app/javascript/controllers/dashboard_sortable_controller.js +++ b/app/javascript/controllers/dashboard_sortable_controller.js @@ -22,12 +22,22 @@ export default class extends Controller { // ===== Mouse Drag Events ===== dragStart(event) { + // On touch devices, cancel native drag — use touch events with hold delay instead + if (this.isTouchDevice()) { + event.preventDefault(); + return; + } + this.draggedElement = event.currentTarget; this.draggedElement.classList.add("opacity-50"); this.draggedElement.setAttribute("aria-grabbed", "true"); event.dataTransfer.effectAllowed = "move"; } + isTouchDevice() { + return "ontouchstart" in window || navigator.maxTouchPoints > 0; + } + dragEnd(event) { event.currentTarget.classList.remove("opacity-50"); event.currentTarget.setAttribute("aria-grabbed", "false");