Skip to content

feat(navigation): drag project rows to reorder them - #360

Open
paradise-runner wants to merge 1 commit into
jmfederico:mainfrom
paradise-runner:feat/project-row-drag
Open

paradise-runner wants to merge 1 commit into
jmfederico:mainfrom
paradise-runner:feat/project-row-drag

Conversation

@paradise-runner

Copy link
Copy Markdown

What and why

Project rows render in the order they were added, and the only supported way to change that order is the row menu's Move up / Move down — one row and one click at a time. On a phone that menu is the only path, and once a machine has a dozen projects the order stops matching how the work is done.

This adds pointer drag to the project list. Drag a row and an accent line shows where it will land; near the top or bottom edge the list autoscrolls; on touch a short press lifts the row, and moving first scrolls the list instead. The row menu is unchanged, and both paths write through the same navigation order port, so stored order, revision checks, and concurrent browser sessions behave exactly as they do today.

Refs #211. That issue also asks for sort and pin controls, which this does not attempt.

Technical details — optional reading
  • listReorder.ts holds the pure parts: insertionSlot, dropTarget, and autoscrollStep, each unit tested. A drop reports a neighbor plus before/after rather than an index, so it composes with saved orders that contain entries this view is not showing.
  • ProjectList adds a pointer candidate with a 4px mouse threshold, Escape to cancel, and swallows the click that ends a drag only when a drag actually started.
  • Autoscroll uses a 36px edge zone at up to 14px per frame and recomputes the drop slot on every frame, so the insert line tracks the rows moving under a stationary pointer. It stops when the container cannot move, and a pointer parked at the end of a scrollable list resolves to the end of the list rather than the first row still hidden below the fold.
  • Touch needs a long press (350ms, 8px tolerance) because the drag direction is shared with scrolling. Once lifted, a non-passive touchmove listener ends scrolling for that gesture only and is removed on drop or cancel. -webkit-touch-callout: none is applied to .action-row, which covers machine, workspace, and session rows too — a wider change than the feature strictly needs, called out here deliberately.
  • The ghost is a clone appended to document.body with fixed positioning: inside the shadow root, the navigation panel's container-type captures fixed descendants. It carries its own chrome (--pi-surface, border, radius, shadow) and copies only text metrics and layout, so themes do not need duplicating.
  • Verification: typecheck, repository lint, knip, and build are clean. 42 unit tests cover ProjectList, listReorder, and navigationOrder. npm run test:browser passes in chromium, firefox, webkit, and the touch profile, including the new navigation.spec.ts fixture.
  • Not included: workspace and session-pin dragging (same algebra, different scopes), sort and pin controls, and an aria-live announcement for pointer reorders. Keyboard and the row menu remain the accessible path.

Automatically generated by the user's AI workflow.

Pointer drag on a project row reports the neighbor it landed against and the
parent persists it through the existing navigation order port, so the stored
order, revision checks, and menu Up/Down moves stay the only write path.

- listReorder: insertion-slot geometry, drop-target selection, and edge
  autoscroll velocity, unit tested
- ProjectList: pointer candidate with a 4px threshold, accent insert line,
  Escape to cancel, and the click that ends a drag stays a click when it should
- dragging near a list edge scrolls it and keeps the drop slot under the
  pointer; the loop stops at either end instead of spinning, and a pointer
  parked at the end of a scrollable list means "end of list"
- a touch drag needs a 350ms press and cancels into a scroll if the finger
  moves first, then blocks the rest of that gesture's scrolling
- a fixed ghost of the dragged row follows the pointer, so the project stays
  identifiable after autoscroll or outside the list
- drags do not start from the row menu, and are ignored without an onReorder
- browser fixture and specs cover reordering, the threshold, autoscroll, touch,
  and the ghost
- add a minor changeset

This branch has not been deployed

No deployments
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