Skip to content

feat(worksheets): select several rows and drag them together - #181

Merged
Artmann merged 1 commit into
mainfrom
feature/multi-select-worksheets
Aug 21, 2026
Merged

feat(worksheets): select several rows and drag them together#181
Artmann merged 1 commit into
mainfrom
feature/multi-select-worksheets

Conversation

@Artmann

@Artmann Artmann commented Aug 21, 2026

Copy link
Copy Markdown
Owner

The sidebar could only ever move one worksheet at a time. Now several rows can be picked out and dragged as a group.

What you can do

  • ⌘/Ctrl-click toggles a row in and out of the selection.
  • Shift-click takes the range from the anchor, and re-measures from that same anchor on the next shift-click instead of growing one click at a time.
  • Drag any selected row and all of them travel. A non-contiguous selection gathers into a block at the drop point, keeping its list order; every travelling row dims, since nothing here renders a drag preview.
  • Right-click a selected row for "Delete 3 worksheets" behind one confirmation. Rename is dropped while it means nothing, the "never empty the list" guard still applies, and a half-failed delete reports Failed to delete 1 of 2 worksheets rather than stranding the rest.

A plain click still just opens one worksheet, and typing in the filter clears the selection — a filtered list cannot be dragged, and hidden rows should not be deletable.

Two decisions worth reviewing

The open worksheet is the implicit selection. With nothing picked out, a ⌘-click adds to the row you were already on rather than replacing it, so the first modified click cannot silently drop it. That fallback depends on view state the reducer does not have, so the slice is a holder (worksheetSelectionChanged) and the math runs at the call site — the same shape worksheetRenameStarted already uses.

Modified clicks do not open anything. Picking rows out to move them should not swap the editor under you.

Shape

  • src/app/list-move.tsmoveIds, the block move. Returns the list it was given, by reference, for every drop that means nothing (row gone mid-drag, drop inside the moving block), which is how the hook knows to skip the write.
  • src/app/list-selection.ts — toggle / extend / prune, all pure.
  • src/app/hooks/use-list-reorder.ts — takes selectedIds as an option and adds isMoving. Single-row drags route through the same moveIds, so the tab strip and the database explorer are untouched.
  • src/app/hooks/use-worksheet-selection.ts — prunes rows that have gone and applies the open-worksheet fallback.

Verification

Unit tests for both pure modules, multi-drag and isMoving cases in use-list-reorder.test.ts, and explorer tests for ⌘-click, Ctrl-click, shift-click, plain click, multi-delete, the all-selected guard, and the partial-failure message. Full suite green (1414 tests), typecheck and prettier clean.

Also driven against the running app, since jsdom cannot do a real drag: ⌘-clicked three non-contiguous rows, dragged them to the top of the list, and confirmed PUT /worksheets/order wrote them as a contiguous block in list order; shift-click ranges and the "Delete 3 worksheets" menu both behave in a real browser, where Radix menus have misled this project's jsdom tests before.

Deliberately not included

  • No keyboard shortcut for delete — Backspace would fire inside the SQL editor.
  • No ARIA selection semantics. Rows carry data-selected for styling and tests; making the list a real listbox would imply arrow-key navigation it does not have.

The sidebar could only ever move one worksheet at a time. Command- or
control-click picks rows out, shift-click takes a range from the anchor,
and grabbing any selected row now carries the whole group to the drop
point — gathering a non-contiguous selection into a block that keeps its
list order.

With nothing picked out the open worksheet stands in for the selection,
so the first modified click adds to the row you were on rather than
silently dropping it. Modified clicks deliberately leave the editor
alone: picking rows out to move them should not swap what you are
looking at.

The context menu follows the selection — "Delete 3 worksheets" behind
one confirmation, Rename gone while it means nothing, and the same
never-empty-the-list guard as a single row. A delete that only half
works says how many of them failed instead of stranding the rest.

`moveIds` and the selection math are pure and tested on their own;
`useListReorder` takes the selection as an option, so the tab strip and
the database explorer keep their single-row drag untouched.
@github-actions

Copy link
Copy Markdown
Contributor

React Doctor found no new issues. 🎉

Reviewed by React Doctor for commit a0acbc5.

@Artmann
Artmann merged commit 6558293 into main Aug 21, 2026
10 checks passed
@Artmann
Artmann deleted the feature/multi-select-worksheets branch August 21, 2026 11:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant