m4: drag-to-reorder polish — grip handle + drop affordances
CI & Build / Python lint (push) Successful in 3s
CI & Build / TypeScript typecheck (push) Successful in 6s
CI & Build / Python tests (push) Successful in 8s
CI & Build / Build & push image (push) Successful in 26s

Refine the masonry drag interaction (task 1869) so reordering reads as
intentional instead of an accidental, feedbackless jump:

- explicit grip handle (top-left, hover-revealed, board views only) gates
  dragging — a plain click or text-select no longer starts a drag
- source card dims while dragging; the card under the pointer shows a
  brand ring + slight lift, so the drop position is clear before release
- proper move cursor via dataTransfer effectAllowed/dropEffect
- dragleave uses a relatedTarget guard so the target ring doesn't flicker
  over child elements
- clear drag state on dragend (BoardView clears the tracked source even
  when a drag is cancelled off-target)
- add a "grip" icon to the shared Icon set

Native HTML5 DnD stays library-free; it remains a desktop/mouse
affordance (touch reorder is the M5 Android client's domain).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FRgehjoz7Yv8LkUfADxACm
This commit is contained in:
2026-07-21 08:33:29 -04:00
co-authored by Claude Opus 4.8
parent 3e9b6095dd
commit 5e225075f3
3 changed files with 79 additions and 6 deletions
+7
View File
@@ -155,6 +155,10 @@ const draggingId = ref<string | null>(null);
function onDragStart(note: Note) {
draggingId.value = note.id;
}
function onDragEnd() {
// Clear the tracked source even when a drag is cancelled (dropped on nothing).
draggingId.value = null;
}
async function onDrop(target: Note) {
const from = draggingId.value;
draggingId.value = null;
@@ -205,6 +209,7 @@ async function onDrop(target: Note) {
reorderable
@open="openEditor"
@dragstart="onDragStart"
@dragend="onDragEnd"
@drop="onDrop"
/>
</div>
@@ -222,6 +227,7 @@ async function onDrop(target: Note) {
reorderable
@open="openEditor"
@dragstart="onDragStart"
@dragend="onDragEnd"
@drop="onDrop"
/>
</div>
@@ -237,6 +243,7 @@ async function onDrop(target: Note) {
reorderable
@open="openEditor"
@dragstart="onDragStart"
@dragend="onDragEnd"
@drop="onDrop"
/>
</div>