Object List rows in right panel show GripVertical with cursor:grab but no drag handlers — reorder of colorRegions / stitchObjects is non-functional #182

Closed
opened 2026-10-03 19:38:49 +00:00 by Mark · 1 comment
Owner

Finding

src/components/workspace/RightPanel.tsx:587 (post #177 location; pre-#177 line number was the same) renders a GripVertical icon as the first child of each Object List row:

<GripVertical size={12} style={{ color: '#A8A29E', cursor: 'grab' }} />

The cursor: 'grab' style suggests the user can drag the row to reorder it. Verified: there is no draggable attribute, no onDragStart, no onDragOver, no onDrop on the parent <div> (lines 580-651 in the post-#177 file). The cursor change is a visual lie.

This is the same class of bug as #177 (which fixed the Thread Stops list) and #165 (which fixed BottomThreadBar). The Object List is a separate surface that renders colorRegions (during digitizing) or stitchObjects (during digitized), so the reorder action would dispatch on a different reducer key.

The Thread Stops reorder reducer (REORDER_THREAD_STOPS) doesn't apply here — object order matters for render layering (z-order, selection, Group/Ungroup) but the current state shape doesn't have an explicit ordering field on stitchObjects / colorRegions. A reorder would need to either:

  • Add an order field to each stitchObjects / colorRegions entry and sort by it on render, OR
  • Sort the array in place by current array index (re-derive order from array position).

Where

  • src/components/workspace/RightPanel.tsx:587 — GripVertical icon with cursor: 'grab'
  • No drag handler: src/components/workspace/RightPanel.tsx:580-651 (the parent <div> has no draggable / onDragStart)
  • No reorder reducer action: grep -rn 'REORDER_OBJECTS\|MOVE_OBJECT\|REORDER_STITCH_OBJECTS' src/ returns 0 hits
  • Helper functions for color-region / stitch-object ordering are not present in the workspace reducer

Suggested fix shape

Two options:

  1. Remove the GripVertical icon (and its cursor: grab) until reorder is implemented. Replace with a non-interactive indicator (or just no leading icon). The row is clickable for selection; the user gets to see the order, but can't change it.

  2. Implement Object List reorder. Add a REORDER_OBJECTS reducer action ({ from: number, to: number }) operating on the active list (colorRegions in digitizing, stitchObjects in digitized). Use HTML5 drag-and-drop on the row (draggable={true}, onDragStart={...}, onDragOver={preventDefault}, onDrop={...}). On drop, dispatch the reorder. The GripVertical becomes a real drag handle.

Option 2 is the right product move; consistent with the BottomThreadBar (#165) and Thread Stops list (#177) surfaces.

Severity

Medium. Same class of bug as #177 — UI lie. Users who try to drag will see the cursor change but the row won't move.

Discovered by

Triage of #177 (RightPanel thread stops). The Object List grip was noted in the #177 closing comment as out of scope; filing as a separate issue so the next triage sweep can route it.

  • #165 (closed) — BottomThreadBar's thread stop reorder (same gap, fixed).
  • #177 (closed) — Right panel Thread Stops list reorder (same gap, fixed).
## Finding `src/components/workspace/RightPanel.tsx:587` (post #177 location; pre-#177 line number was the same) renders a `GripVertical` icon as the first child of each Object List row: ```tsx <GripVertical size={12} style={{ color: '#A8A29E', cursor: 'grab' }} /> ``` The `cursor: 'grab'` style suggests the user can drag the row to reorder it. Verified: there is no `draggable` attribute, no `onDragStart`, no `onDragOver`, no `onDrop` on the parent `<div>` (lines 580-651 in the post-#177 file). The cursor change is a visual lie. This is the same class of bug as #177 (which fixed the Thread Stops list) and #165 (which fixed BottomThreadBar). The Object List is a separate surface that renders `colorRegions` (during `digitizing`) or `stitchObjects` (during `digitized`), so the reorder action would dispatch on a different reducer key. The Thread Stops reorder reducer (`REORDER_THREAD_STOPS`) doesn't apply here — object order matters for render layering (z-order, selection, Group/Ungroup) but the current state shape doesn't have an explicit ordering field on `stitchObjects` / `colorRegions`. A reorder would need to either: - Add an `order` field to each `stitchObjects` / `colorRegions` entry and sort by it on render, OR - Sort the array in place by current array index (re-derive order from array position). ## Where - `src/components/workspace/RightPanel.tsx:587` — `GripVertical` icon with `cursor: 'grab'` - No drag handler: `src/components/workspace/RightPanel.tsx:580-651` (the parent `<div>` has no `draggable` / `onDragStart`) - No reorder reducer action: `grep -rn 'REORDER_OBJECTS\|MOVE_OBJECT\|REORDER_STITCH_OBJECTS' src/` returns 0 hits - Helper functions for color-region / stitch-object ordering are not present in the workspace reducer ## Suggested fix shape Two options: 1. **Remove the GripVertical icon (and its `cursor: grab`) until reorder is implemented.** Replace with a non-interactive indicator (or just no leading icon). The row is clickable for selection; the user gets to see the order, but can't change it. 2. **Implement Object List reorder.** Add a `REORDER_OBJECTS` reducer action (`{ from: number, to: number }`) operating on the active list (`colorRegions` in `digitizing`, `stitchObjects` in `digitized`). Use HTML5 drag-and-drop on the row (`draggable={true}`, `onDragStart={...}`, `onDragOver={preventDefault}`, `onDrop={...}`). On drop, dispatch the reorder. The GripVertical becomes a real drag handle. Option 2 is the right product move; consistent with the BottomThreadBar (#165) and Thread Stops list (#177) surfaces. ## Severity Medium. Same class of bug as #177 — UI lie. Users who try to drag will see the cursor change but the row won't move. ## Discovered by Triage of #177 (RightPanel thread stops). The Object List grip was noted in the #177 closing comment as out of scope; filing as a separate issue so the next triage sweep can route it. ## Related - #165 (closed) — BottomThreadBar's thread stop reorder (same gap, fixed). - #177 (closed) — Right panel Thread Stops list reorder (same gap, fixed).
Mark closed this issue 2026-10-03 19:48:39 +00:00
Author
Owner

Implemented HTML5 drag-and-drop reorder of the Object List rows, mirroring the BottomThreadBar pattern from #165 and the right-panel thread-stops fix from #177.

Changes

  • useWorkspace.ts: new action REORDER_OBJECTS { list: 'colorRegions' | 'stitchObjects', from, to } that splice-moves an entry in the active list and pushes history (same pushHistory shape REORDER_THREAD_STOPS / REORDER_STITCH_OBJECTS have used since #165).
  • RightPanel.tsx: extracted ObjectList subcomponent. Each row now carries a real <GripVertical> drag handle (the only draggable element — the row's onClick select is preserved). Drop fires REORDER_OBJECTS with the active list key. A 3px gold vertical accent bar appears next to the drop target on dragover, switching left/right based on cursor X vs. wrapper midpoint. Source row dims to opacity 0.4 while a drag is in flight.
  • Tests: issue-182.test.tsx (7 cases) covers drag-handle rendering, forward/backward drops, the active-list dispatch key for both appState paths (digitizing -> colorRegions, digitized -> stitchObjects), same-row self-drop no-op, drop indicator, source-row dim, and click-preserved SELECT. issue-182-reducer.test.ts (5 cases) pins the reducer math: splice-move within the active list, cross-list isolation, and the post-action snapshot contract shared with #165.

Fix landed on main as commit c898c46 (rebased onto b5bc1fe / #177). Closing.

Implemented HTML5 drag-and-drop reorder of the Object List rows, mirroring the BottomThreadBar pattern from #165 and the right-panel thread-stops fix from #177. **Changes** - `useWorkspace.ts`: new action `REORDER_OBJECTS { list: 'colorRegions' | 'stitchObjects', from, to }` that splice-moves an entry in the active list and pushes history (same `pushHistory` shape `REORDER_THREAD_STOPS` / `REORDER_STITCH_OBJECTS` have used since #165). - `RightPanel.tsx`: extracted `ObjectList` subcomponent. Each row now carries a real `<GripVertical>` drag handle (the only draggable element — the row's onClick select is preserved). Drop fires `REORDER_OBJECTS` with the active list key. A 3px gold vertical accent bar appears next to the drop target on dragover, switching left/right based on cursor X vs. wrapper midpoint. Source row dims to opacity 0.4 while a drag is in flight. - Tests: `issue-182.test.tsx` (7 cases) covers drag-handle rendering, forward/backward drops, the active-list dispatch key for both appState paths (digitizing -> `colorRegions`, digitized -> `stitchObjects`), same-row self-drop no-op, drop indicator, source-row dim, and click-preserved SELECT. `issue-182-reducer.test.ts` (5 cases) pins the reducer math: splice-move within the active list, cross-list isolation, and the post-action snapshot contract shared with #165. Fix landed on `main` as commit c898c46 (rebased onto b5bc1fe / #177). Closing.
Sign in to join this conversation.
No description provided.