Skip to content

[codex] Stabilize sidebar sortable drag#295

Merged
DeadWaveWave merged 8 commits into
mainfrom
feat/sidebar-item-ui
Jul 8, 2026
Merged

[codex] Stabilize sidebar sortable drag#295
DeadWaveWave merged 8 commits into
mainfrom
feat/sidebar-item-ui

Conversation

@DeadWaveWave

@DeadWaveWave DeadWaveWave commented Jul 8, 2026

Copy link
Copy Markdown
Owner

💡 Change Scope

  • Small Change: Fast feedback, localized UI/logic, low-risk.
  • Large Change: New feature, cross-boundary logic, runtime-risk (persistence, IPC, lifecycle, recovery).

📝 What Does This PR Do?

This PR stabilizes sidebar sortable drag behavior across all three visible hierarchy levels: projects, spaces, and agents.

It replaces the previous mostly-local drag handling with one shared sidebar drag contract:

  • Project, space, and agent items all use scoped sortable metadata.
  • Collision detection filters candidates to the allowed reorder scope before choosing an over target.
  • Spaces can only reorder inside the same project.
  • Agents can only reorder inside the same project and same sidebar group.
  • Drag overlays now exist for projects, spaces, and agents, so the dragged item visually lifts out instead of only causing list displacement.
  • Sortable transitions and drop animation timing are unified across the three levels.
  • New E2E coverage measures upward dragging, active overlay presence, source fading, and target displacement for project/space/agent rows.

Root cause: the sidebar had sortable behavior split across levels, used broad collision detection, and only rendered a project overlay. That made upward drag, cross-scope boundary behavior, and displacement animation depend too heavily on incidental DOM geometry.


🏗️ Large Change Spec (Required if "Large Change" is checked)

1. Context & Business Logic

Sidebar reorder should behave like a constrained sortable tree:

  • Projects reorder only against other projects.
  • Spaces reorder only against spaces in the same workspace/project.
  • Agents reorder only against agents in the same workspace/project and sidebar group.
  • Dragging outside the allowed scope must not reorder the nearest valid sibling by accident.
  • During drag, users should see a real dragged overlay and sibling displacement animation.

2. State Ownership & Invariants

State ownership:

  • Renderer DndContext owns the transient active drag item.
  • Existing sidebar reorder callbacks remain the only write path for durable sort order.
  • Existing persistence remains the durable source of truth after reorder.

Invariants:

  • SortableContext.items order matches rendered order for each scope.
  • A drag end only commits reorder when active and over payloads are compatible by kind and scope.
  • Pointer-based collision outside the allowed scope returns no target, so cross-project/cross-group drags cannot mutate local order.
  • DragOverlay stays mounted and swaps only its child content so drop animation can run.

3. Verification Plan & Regression Layer

Lowest meaningful layers:

  • Unit: SidebarDnd.spec.ts locks sortable scope invariants and malformed drag payload rejection.
  • Renderer tests: existing sidebar component tests still cover sidebar rendering and scroll behavior with updated dnd-kit mocks.
  • E2E: sidebar boundary, motion, reorder, spacing, and workspace tests cover real Electron drag behavior.

Validation run:

  • pnpm check
  • pnpm test -- --run src/app/renderer/shell/components/SidebarDnd.spec.ts src/app/renderer/shell/components/Sidebar.spec.tsx src/app/renderer/shell/components/Sidebar.scroll.spec.tsx src/app/renderer/shell/utils/sidebarReorder.spec.ts
  • pnpm test:e2e -- tests/e2e/workspace-canvas.sidebar-drag-boundaries.spec.ts tests/e2e/workspace-canvas.sidebar-drag-motion.spec.ts --project electron --reporter=line
  • pnpm test:e2e -- tests/e2e/workspace-canvas.sidebar-drag-reorder.spec.ts --project electron --reporter=line
  • pnpm pre-commit for the implementation commit: 249 passed, 47 skipped.
  • pnpm pre-commit for the changelog commit: exited 0 with 248 passed, 1 unrelated flaky retry pass, 47 skipped.
  • pnpm test:e2e -- tests/e2e/workspace-canvas.header-chrome-stability.spec.ts --project electron --reporter=line: 1 passed after the unrelated flaky was observed.

✅ Delivery & Compliance Checklist

  • My code passes the ultimate gatekeeper: pnpm pre-commit is completely green.
  • I have signed the CLA if required (see CLA.md).
  • I have included new tests to lock down the behavior (or explicitly stated why it's untestable).
  • I have strictly adhered to the DEVELOPMENT.md architectural boundaries.
  • I have attached a screenshot or screen recording (if this touches the UI).
  • I have updated the documentation accordingly (if adding a feature or changing a contract).

📸 Screenshots / Visual Evidence

No review-only media is committed. Runtime evidence is covered by the new Playwright motion test, which measures overlay presence, overlay height, source opacity, target displacement, and final order for project, space, and agent drags.

@DeadWaveWave DeadWaveWave marked this pull request as ready for review July 8, 2026 03:27
@DeadWaveWave DeadWaveWave merged commit e96cea3 into main Jul 8, 2026
9 of 10 checks passed
@DeadWaveWave DeadWaveWave deleted the feat/sidebar-item-ui branch July 8, 2026 03:38
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