Skip to content

feat(agents): reorder agent cards with hold and drag - #1837

Open
zrmarley wants to merge 3 commits into
mainfrom
zmarley/agent-card-reorder
Open

zrmarley wants to merge 3 commits into
mainfrom
zmarley/agent-card-reorder

Conversation

@zrmarley

@zrmarley zrmarley commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Hold an agent card with mouse or pen to pick it up, slightly shrink it, and preview its new position as neighbours move. Drop commits; Escape cancels.
  • Keep the arrangement on this device, scoped to the viewer and community. New agents append; agent settings, runtime, teams, and main-agent choice are unchanged.
  • Reordering is drag-only, as requested in product review: no Move earlier / Move later menu items. Ordinary card keyboard navigation and existing touch long-press behaviour remain unchanged; there is no keyboard reorder command in this scope.

Implementation and design

Reuses the existing AgentCard, shared Select/Menu, @dnd-kit/core, Motion, and scoped shared/view-state owner. No dependencies or shared design-system APIs added. Stable agent keys preserve mounted controls and profile drafts.

Consulted the read-only Buzz design pack: AGENTS.md, DESIGN.md (Motion, Accessibility, Surface and depth), tokens/motion.json (duration-settle, easing-settle), tokens/elevation.json (shadow-sm), and components/registry.json. No proposed pack component is introduced. Current repository src/shared/design-system/DESIGN.md governs collection composition, contribution boundaries, focus, shared controls, and direct manipulation. Its semantic-role guidance supersedes the older pack's ramp-first guidance. The subtle card shrink is the explicitly requested local treatment. Reduced motion disables shrink and positional/drop animation.

Review

Code review and Slopaganda Panda ran independently, followed by bounded rechecks. Both report no remaining code blockers, with minimalness/elegance/correctness scores of 9/10.

The user subsequently requested removal of both menu reorder actions. This is an explicit drag-only product choice, not a replacement keyboard interaction. Its absence assertion failed before removal; persistence/error coverage is retained at the existing hook owner. Follow-up review found no blockers (9/10 minimalness, elegance, correctness); TypeScript, 77 AgentsPage tests plus 1 ordering-hook test, and all 4 Chromium/WebKit checks passed after removal.

Two review findings were reproduced before repair in both Chromium and WebKit:

  • Holding a portalled Model option started a background card drag. The row now rejects pointer targets outside its own DOM.
  • Escape followed by delayed mouse release selected the original card after the drag overlay had unmounted. A row-local capture guard suppresses that gesture's click while preserving keyboard activation and the next ordinary pointer click. No timer or document listener was added.

Validation

  • bin/pnpm typecheck
  • bin/pnpm exec vitest run src/bundled/agents/AgentsPage.test.tsx src/bundled/agents/agent-order.test.tsx — 78 passed (77 page + 1 hook). Covers absent reorder menu actions, stable mounts, scoped read/restore/appending, arrow navigation, malformed storage, save failure/retry, and removal reconciliation.
  • bin/pnpm test:browser tests/browser/agent-reorder.spec.mjs --no-deps --project chromium --project webkit --workers=1 — 4 passed in both engines after menu removal.
  • bin/pnpm test:browser tests/browser/agent-reorder.spec.mjs --no-deps --project chromium --project webkit --repeat-each=10 --workers=2 — 40 passed (1.6 minutes locally) after the animation-unmount barrier; focused follow-up review found no blockers (9/10).
  • Biome on changed files, git diff --check, and mandatory pre-commit hooks.
  • Mandatory pre-push types/related-unit tests, design-system checks, and applicable native-input gate passed again; remote head verified as 96e6ab3b9d3b3d2a9d38c50920bd7f67c437c9c5.
  • Hosted CI run 40737759860 passed on 96e6ab3b9d3b3d2a9d38c50920bd7f67c437c9c5, including functional shards and repeated Chromium/WebKit checks. Required CI required and DCO Check are both successful. Previous run 40734373756 exposed a real-time Web Animations vs. test-clock synchronization gap; the test now observes the cancelled overlay unmount. No app behaviour changed, no timeout/retry was added, and no animation was disabled.
  • Human confirmed the main drag interaction in the configured desktop development build before the two review fixes.
  • Human confirmed the repaired popup-hold and Escape/delayed-release edges work perfectly.
  • Human confirmed the menu reorder actions are gone.

Browser coverage

Adds 2 cases, removes none. Real browser hit testing, portalled controls, grid geometry, focus, and native release/click ordering cannot be established with jsdom. Persistence/error matrices remain in colocated React tests. After menu removal, failed-save error/retry is asserted at the real hook rather than via the deleted menu action; the simple page alert wiring is not independently exercised by a failed drag. Both review regression scenarios failed before the repair and pass afterward in both engines. Controlled clocks exercise the activation/cancel boundaries; Select closure is checked through aria-expanded before advancing its exit transition.

Remaining gates / limits

Ready for review after agent reviews, local checks, hosted CI, and explicit human acceptance of the drag interaction, both repaired edge cases, and the final menu removal. Theme/narrow-width/enlarged-text/reduced-motion visual acceptance remains outside that human acceptance scope. Browser fixtures exercise the real Agents page with synthetic service records, not packaged desktop persistence or relay/runtime execution. The configured desktop development build was used for human acceptance. Broad/native lanes passed in hosted CI; no routine local just scan was run. Required code-owner approval is still a merge gate; this update does not merge the PR.

Latest fetched main at this update: a0ea099b5; incoming files were inspected and do not overlap the feature owners. Human acceptance is complete. Required CI and DCO must pass before ready-for-review; required code-owner approval remains a merge gate. No merge is requested by this readiness update.

Screenshots

Actual Agents page rendered with synthetic fixture identities only; no live community/account information.

Before dragging During drag: Ada previews the last slot
Synthetic agent cards in original Ada, Bo, Cy order Ada lifted at the last slot while Bo and Cy shift left

Card actions after removing menu reordering

Agent card menu with Open settings, Copy public key, and Delete agent; no reorder actions

Agent review, agent exercise, and explicit human acceptance complete: buzz-review-completed. Final edit only synchronizes the browser test with the existing drop animation; accepted app behaviour is unchanged.

zrmarley and others added 3 commits October 28, 2026 13:06
Keep card order on this device per account and community, with live drag previews and menu actions for keyboard users.

Co-authored-by: Codex <noreply@openai.com>
Signed-off-by: Zach Marley <zmarley@squareup.com>
Remove menu reordering actions as requested in product review; retain persistence and save-recovery coverage at the existing ordering hook.

Co-authored-by: Codex <noreply@openai.com>
Signed-off-by: Zach Marley <zmarley@squareup.com>
The Web Animations drop transition follows real browser time, not the test clock. Observe its unmount before sending another pointerdown.

Co-authored-by: Codex <noreply@openai.com>
Signed-off-by: Zach Marley <zmarley@squareup.com>
@zrmarley
zrmarley marked this pull request as ready for review October 28, 2026 17:54
@zrmarley
zrmarley requested a review from a team as a code owner October 28, 2026 17:54

@kalvinnchau kalvinnchau left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 One persistence defect: reordering a temporarily incomplete inventory removes saved positions for absent agents.

);
const save = (next: readonly Agent[]) => {
const saved =
!!scope &&

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 [P2] Preserve saved positions for temporarily absent agents

Saving only the currently visible keys discards hosted/elsewhere agents while relay listings are unavailable. The agent service clears listings on session changes, but dragging remains enabled whenever connection.scope exists, including cached/connecting startup states. Reordering local agents during startup or reconnect therefore makes returning hosted agents append at the end.

A hook reproduction starts with saved [H, A, B], renders [A, B], saves [B, A], then restores inventory [A, H, B]: storage becomes [B, A] and display becomes [B, A, H]. Preserve absent saved keys while rewriting the reordered subset, or gate saving on an explicit complete-inventory signal. Add a regression covering save while an agent is temporarily absent and its subsequent return.

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.

2 participants