Skip to content

fix(frontend): let drag handle icons start a drag - #1999

Merged
smartcmd merged 1 commit into
TokenFlux:mainfrom
SHLE1:fix/drag-handle-icon-pointer-events
Oct 30, 2026
Merged

smartcmd merged 1 commit into
TokenFlux:mainfrom
SHLE1:fix/drag-handle-icon-pointer-events

Conversation

@SHLE1

@SHLE1 SHLE1 commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Related Issue

  • Closes: none. No issue was filed; the defect was reported during a review of the sort dialog, and the reproduction plus the result after the fix are recorded under Proof of Work.

Type of change

  • Bug fix
  • New feature
  • Performance / Refactor
  • Documentation

Description

Dragging a row by its ≡ handle did nothing in the group sort dialog, while dragging by the row text worked. The animated icon is the cause: pressing it focuses the SVG, useIconAnimation moves that focus away, and Chromium then never starts the native drag that vue-draggable-plus relies on. The payment provider list was worse, because its only handle is the grip icon, so that list could not be reordered at all.

Both icons are now pointer-events-none, which keeps the press on the row or the handle. Appearance is unchanged.

The change and this description were produced by an AI coding agent (OpenCode, model magpie/auto/deepseek-v4.1-flash) at the owner's request. A second agent (Codex, model gpt-6-astra) independently reviewed the diagnosis and the scope of the fix.

Proof of Work

A repro page mounted the real Icon.vue and the real vue-draggable-plus under the project's Tailwind build, driven in Chrome through ego-browser. The list items carry placeholder names here; the actual deployments use their own group and provider names.

Before the fix:

  • Drag starting on the sort dialog's ≡ icon: no dragstart event fired, order unchanged (3/3 runs).
  • Drag starting on the row name or #id text: worked.
  • Replacing the icon's SVG with a plain SVG of the same size: worked, which isolates the icon element.
  • The payment provider list with handle=".drag-handle": dragging its grip icon left the order unchanged (provider-a,provider-b,provider-c).

After the fix:

  • Sort dialog, drag from the ≡ handle area: group-a,group-b,group-c became group-b,group-c,group-a.
  • Sort dialog, drag from the row name: same result.
  • Payment provider list, drag from the grip: provider-a,provider-b,provider-c became provider-b,provider-c,provider-a.

Checks run in frontend/: npm run typecheck (no output, exit 0), npx prettier --check on both components, npm run check:comments (1288 files, 0 violations), npx vitest run GroupsView.tabs GroupsView.duplicate (34 passed), npx vitest run SettingsView (57 passed). From the repository root: make fmt, make fmt-check (Prettier reports all files formatted).

No screenshot is attached because the change alters hit testing only and the dialog renders the same. No automated test was added: the defect only appears with real Chromium native drag, and jsdom does not reproduce it.

Checklist

  • Human review: Whether or not the description was AI-generated, I have reviewed and condensed the full text, retained only the points needed for review, and take responsibility for its accuracy and completeness. I have not pasted unfiltered AI-generated text in the PR body or in later comments.
  • Not a duplicate: I have searched existing Issues and PRs and confirmed this is not a duplicate.
  • Feature issue: Not a new feature.
  • Prior discussion: Not a large or directional change.
  • Scope: This PR follows the repository's provider and protocol support matrix, or maintainers have agreed to the new support scope in the linked Issue.
  • Upstream errors: This PR addresses TokenRouter behavior and does not treat an unchanged upstream error alone as a TokenRouter defect.
  • Focused change: This PR is a single focused change and does not include unrelated code.
  • Local verification: I verified the changed path and recorded the commands and observed results.
  • Security: This change does not include secrets and follows the project's coding guidelines.

Pressing the animated icon inside a sortable item starts no native drag in
Chromium. The icon's SVG takes focus on mousedown, useIconAnimation moves that
focus away, and the browser never fires dragstart for the row underneath.

That left the group sort dialog unable to move a row when grabbed on its menu
icon, and the payment provider list unable to move a provider at all, because
its only handle is the grip icon. Marking both icons pointer-events-none keeps
the press on the row or handle, so the whole handle area drags again.

Record the rule in the icon conventions.
@smartcmd

Copy link
Copy Markdown
Contributor

Thanks for your contribution!

@smartcmd
smartcmd merged commit 2f8acd6 into TokenFlux:main Oct 30, 2026
9 checks passed
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