BottomThreadBar's thread stops cannot be reordered (no drag-and-drop) — Home page claims "reorder with drag-and-drop simplicity" but reorderColors only exists for the library catalog, not stops #165

Closed
opened 2026-10-03 17:30:28 +00:00 by Mark · 1 comment
Owner

Finding

The Home page feature grid advertises:

Thread stop management: Add, remove, and reorder thread stops with drag-and-drop simplicity.

The reorderColors(from, to) function exists in src/components/workspace/threadLibrary.ts:189 and is used by useThreadLibrary's reorder callback (line 557-560). This reorders the user's library catalog (the list of available thread colors).

The BottomThreadBar (src/components/workspace/BottomThreadBar.tsx, 320 lines) renders the design's threadStops — the ordered list of color changes in the stitch sequence. There is no drag handler, no reorder UI, no onDragStart, no onDrop, no setThreadStops reordering capability. The stops are rendered in state.threadStops order; the user can add/remove but not reorder.

grep -n 'draggable\|onDragStart\|onDrop\|reorder.*threadStops\|moveStop\|sortStops' src/components/workspace/BottomThreadBar.tsx
# (no matches)

A user who digitizes a design and wants to re-sequence the thread stops to optimize the stitch path cannot. They have to re-digitize, or accept the engine's order.

Where

  • BottomThreadBar: src/components/workspace/BottomThreadBar.tsx (no drag handlers)
  • threadLibrary reorder (different surface): src/components/workspace/threadLibrary.ts:189, 557-560
  • Home page claim: src/pages/Home.tsx ("Thread stop management" card)

Suggested fix shape

Add a reorderThreadStops(from: number, to: number) action to the workspace reducer (src/components/workspace/useWorkspace.ts) and expose it via the workspace hook. Then wire the BottomThreadBar to use it:

  1. Reducer action: REORDER_THREAD_STOPS with payload { from, to }. Update state.threadStops accordingly. The history snapshot captures the reorder for undo/redo.

  2. UI in BottomThreadBar: wrap each stop in a draggable element. Use the HTML5 drag-and-drop API (or react-dnd if the codebase already has it). On drop, dispatch the reorder action.

  3. Visual affordance: a drag handle (the 6-dot icon) appears on hover. The drop indicator shows where the stop will land. The reorder animates smoothly.

  4. Sort order persistence: the new order survives undo/redo and save-to-gallery.

Severity

Medium. A power-user feature for production embroidery, where stop order affects stitching time (the machine has to physically re-thread for each stop). The Home page promise is real but unfulfilled.

Discovered by

Gap analysis (2026-10-02) of thread stop affordances.

  • The existing reorderColors in threadLibrary.ts is the model implementation; copy the shape.
  • #128 (closed) — ΔE display + alternatives popover. The thread stop UI is the same surface; the reorder adds to it.
## Finding The Home page feature grid advertises: > **Thread stop management**: Add, remove, and reorder thread stops with drag-and-drop simplicity. The `reorderColors(from, to)` function exists in `src/components/workspace/threadLibrary.ts:189` and is used by `useThreadLibrary`'s `reorder` callback (line 557-560). This reorders the user's **library catalog** (the list of available thread colors). The BottomThreadBar (`src/components/workspace/BottomThreadBar.tsx`, 320 lines) renders the design's `threadStops` — the ordered list of color changes in the stitch sequence. There is no drag handler, no reorder UI, no onDragStart, no onDrop, no `setThreadStops` reordering capability. The stops are rendered in `state.threadStops` order; the user can add/remove but not reorder. ``` grep -n 'draggable\|onDragStart\|onDrop\|reorder.*threadStops\|moveStop\|sortStops' src/components/workspace/BottomThreadBar.tsx # (no matches) ``` A user who digitizes a design and wants to re-sequence the thread stops to optimize the stitch path cannot. They have to re-digitize, or accept the engine's order. ## Where - BottomThreadBar: `src/components/workspace/BottomThreadBar.tsx` (no drag handlers) - threadLibrary reorder (different surface): `src/components/workspace/threadLibrary.ts:189, 557-560` - Home page claim: `src/pages/Home.tsx` ("Thread stop management" card) ## Suggested fix shape Add a `reorderThreadStops(from: number, to: number)` action to the workspace reducer (`src/components/workspace/useWorkspace.ts`) and expose it via the workspace hook. Then wire the BottomThreadBar to use it: 1. **Reducer action**: `REORDER_THREAD_STOPS` with payload `{ from, to }`. Update `state.threadStops` accordingly. The history snapshot captures the reorder for undo/redo. 2. **UI in BottomThreadBar**: wrap each stop in a draggable element. Use the HTML5 drag-and-drop API (or `react-dnd` if the codebase already has it). On drop, dispatch the reorder action. 3. **Visual affordance**: a drag handle (the 6-dot icon) appears on hover. The drop indicator shows where the stop will land. The reorder animates smoothly. 4. **Sort order persistence**: the new order survives undo/redo and save-to-gallery. ## Severity Medium. A power-user feature for production embroidery, where stop order affects stitching time (the machine has to physically re-thread for each stop). The Home page promise is real but unfulfilled. ## Discovered by Gap analysis (2026-10-02) of thread stop affordances. ## Related - The existing `reorderColors` in `threadLibrary.ts` is the model implementation; copy the shape. - #128 (closed) — ΔE display + alternatives popover. The thread stop UI is the same surface; the reorder adds to it.
Author
Owner

Shipped as commit 81107c1 on main (#165):

  • BottomThreadBar.tsx: each chip wrapper now renders a GripVertical drag handle (the only draggable element — the chip's onClick select behavior is preserved). Source wrapper dims to opacity 0.4 while dragging; a vertical accent bar appears next to the drop target, switching left/right based on cursor position vs. the wrapper midpoint.
  • Workspace.tsx: passes an onReorderStops callback that dispatches REORDER_THREAD_STOPS { from, to } to the reducer. The reducer splice-moves the stop and pushes history, so undo/redo round-trip the new order.
  • issue-165.test.tsx: 8 regression tests covering handle presence/absence, forward + backward splice math, no-op on same-chip drop, drop indicator visibility, and source wrapper opacity.

Gates green: npm run lint ✓, npm test (728/728, 8 new) ✓, npm run build ✓. The Home page "Thread stop management" feature card is now genuinely fulfilled — user can re-sequence the stops in place to optimize the stitch path.

Note for gap-analysis: the reducer's REORDER_THREAD_STOPS was declared and implemented but had no dispatcher; this fix wires the dispatcher + adds the UI. The underlying splice-move + pushHistory behavior is covered by issue-92.test.ts (pre-#165).

Shipped as commit 81107c1 on `main` (#165): - `BottomThreadBar.tsx`: each chip wrapper now renders a `GripVertical` drag handle (the only draggable element — the chip's onClick select behavior is preserved). Source wrapper dims to opacity 0.4 while dragging; a vertical accent bar appears next to the drop target, switching left/right based on cursor position vs. the wrapper midpoint. - `Workspace.tsx`: passes an `onReorderStops` callback that dispatches `REORDER_THREAD_STOPS { from, to }` to the reducer. The reducer splice-moves the stop and pushes history, so undo/redo round-trip the new order. - `issue-165.test.tsx`: 8 regression tests covering handle presence/absence, forward + backward splice math, no-op on same-chip drop, drop indicator visibility, and source wrapper opacity. Gates green: `npm run lint` ✓, `npm test` (728/728, 8 new) ✓, `npm run build` ✓. The Home page "Thread stop management" feature card is now genuinely fulfilled — user can re-sequence the stops in place to optimize the stitch path. Note for gap-analysis: the reducer's `REORDER_THREAD_STOPS` was declared and implemented but had no dispatcher; this fix wires the dispatcher + adds the UI. The underlying splice-move + pushHistory behavior is covered by `issue-92.test.ts` (pre-#165).
Mark closed this issue 2026-10-03 18:36:25 +00:00
Sign in to join this conversation.
No description provided.