Author: Andy Green Date: Sat Sep 12 21:08:54 2026 +0100 assets: resizers: make the tasks splitter draggable by touch On Android the browser claimed touches on the 5px sub-pane splitter as a pan of the surrounding scrollers before the drag handlers saw a move, and the touchstart listener was passive so it couldn't object. - touch-action: none on all three resizers, so the browser leaves touch gestures starting on them to the page - the tasks splitter becomes a 13px hit target drawing the same 5px bar - its touchstart listener is non-passive and preventDefaults, which also stops the synthesized mousedown after touchend starting a second drag Bump the asset cache-bust to v=14. Co-Authored-By: Claude Fable 5.1 diff --git a/assets/index.html b/assets/index.html index a17dc3f..daaebe0 100644 --- a/assets/index.html +++ b/assets/index.html @@ -2,9 +2,9 @@ - + - + diff --git a/assets/sai.css b/assets/sai.css index f54c72c..2ade62a 100644 --- a/assets/sai.css +++ b/assets/sai.css @@ -1229,6 +1229,7 @@ table.comp.adhoc { cursor: ew-resize; background-color: #ccc; flex-shrink: 0; + touch-action: none; } .step-progress { @@ -2203,6 +2204,7 @@ div.ibuil.vm-builder { cursor: ns-resize; background-color: #ccc; flex-shrink: 0; + touch-action: none; } .event-tasks-header { @@ -2448,12 +2450,18 @@ td.e6 a:hover { overflow: auto; } +/* + * 13px wide hit target (finger-friendly) drawing the same 5px bar the + * other resizers use; touch-action: none so the browser doesn't turn a + * touch drag into a pan of the surrounding scrollers + */ .resizer-v { - width: 5px; - margin: 0 4px; + width: 13px; cursor: ew-resize; - background-color: #ccc; + background: linear-gradient(to right, transparent 4px, #ccc 4px, + #ccc 9px, transparent 9px); flex-shrink: 0; + touch-action: none; } /* the task table itself */ diff --git a/assets/sai.js b/assets/sai.js index 4055df8..a76f7c9 100644 --- a/assets/sai.js +++ b/assets/sai.js @@ -5424,8 +5424,13 @@ window.addEventListener("load", function() { var rz = e.target.closest ? e.target.closest('.resizer-v') : null; if (!rz || !rz.previousElementSibling || e.touches.length !== 1) return; + /* + * Claim the gesture: no pan of the surrounding scrollers, and + * no synthesized mousedown after touchend starting a second drag + */ + e.preventDefault(); sai_tt_split_begin(rz.previousElementSibling, e.touches[0].clientX); - }, { passive: true }); + }, { passive: false }); const resizer = document.getElementById('resizer'); if (resizer) {