Skip to content

fix(dockview-core): tab group can't be moved after its first move (#1410)#1500

Merged
mathuo merged 2 commits into
masterfrom
claude/issue-1410-1177h3
Jul 21, 2026
Merged

fix(dockview-core): tab group can't be moved after its first move (#1410)#1500
mathuo merged 2 commits into
masterfrom
claude/issue-1410-1177h3

Conversation

@mathuo

@mathuo mathuo commented Jul 20, 2026

Copy link
Copy Markdown
Owner

Description

Fixes #1410 — a tab group could not be dragged again after being moved once (the issue surfaced as "tab groups can't be moved if a tab is in focus", but focus was incidental).

Root cause: Committing a group-chip move calls TabGroupManager.disposeChipDrag, which disposes the chip's HTML5 + pointer drag sources to release the transfer payload and iframe shield synchronously. A cross-group move dissolves the source chip entirely, so this is harmless. But a within-group reorder keeps the same chip element, and _ensureChipForGroup early-returns when a renderer entry already exists — so the disposed drag sources were never rebuilt. After its first move the chip kept draggable=true (a native dragstart still fired) but no longer set a transfer payload, so no drop overlay appeared and the group could not be moved.

Fix: Extract the chip drag-source wiring into _createChipDragSources and re-arm it from _ensureChipForGroup when a surviving entry has no live sources. disposeChipDrag now clears the source references so the following updateTabGroups() re-wires them. The context-menu long-press cancel resolves the pointer source from the entry so it targets the current (re-armed) source rather than a stale captured one.

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation
  • Refactor / cleanup
  • Build / CI / tooling

Affected packages

  • dockview-core
  • dockview (vanilla JS)
  • dockview-react
  • dockview-vue
  • dockview-angular
  • docs

How to test

Using the Tab Groups example: drag the "Feature" group by its chip to relocate it, then try to drag it again. On master the second drag does nothing; with this change it keeps working on every subsequent drag.

Automated: within-group chip stays draggable after a move (#1410) in dockviewComponent.spec.ts drives two consecutive chip drags across a within-group moveTabGroup and asserts the transfer payload (getPanelData().tabGroupId) is set both times. It fails on master (second read is undefined) and passes with the fix.

This was also verified end-to-end by driving the built bundle in a real Chromium via native drag: before the fix the drop overlay appeared only on the first move; after the fix it appears on every move.

Checklist

  • yarn lint:fix passes (no new errors)
  • yarn format passes
  • npm run gen has been run and generated files are up to date
  • yarn test passes (1080 dockview-core tests)
  • I have added or updated tests where applicable
  • Breaking changes are documented

🤖 Generated with Claude Code

https://claude.ai/code/session_01Heh7Wst7u9Vu6QbYE5uGAK


Generated by Claude Code

mathuo and others added 2 commits July 20, 2026 21:54
…-group move (#1410)

Committing a group-chip move calls `disposeChipDrag`, which disposes the
chip's HTML5 + pointer drag sources to release the transfer payload and
iframe shield synchronously. A cross-group move dissolves the source chip
entirely, so this is harmless — but a within-group reorder keeps the same
chip element. Because `_ensureChipForGroup` early-returns when a renderer
entry already exists, the disposed sources were never rebuilt, so after its
first move a chip kept `draggable=true` (firing a native `dragstart`) but no
longer set a transfer payload — leaving the tab group undraggable.

Extract the drag-source wiring into `_createChipDragSources` and re-arm it
from `_ensureChipForGroup` when a surviving entry has no live sources.
`disposeChipDrag` now clears the source references so the following
`update()` re-wires them. The context-menu long-press cancel resolves the
pointer source from the entry so it targets the current (re-armed) source.

Adds a regression test that drives two consecutive chip drags across a
within-group move and asserts the transfer payload is set both times.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Heh7Wst7u9Vu6QbYE5uGAK
Drive the real production commit path (`Tabs._commitGroupMove`) instead of
simulating `disposeChipDrag` + `moveTabGroup`, cover repeated within-group
moves, assert both the HTML5 and pointer drag sources are re-armed, and add
a smooth-mode variant matching the reported example's config (the FLIP
branch of `_commitGroupMove`). All fail against the pre-fix source.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Heh7Wst7u9Vu6QbYE5uGAK
@sonarqubecloud

Copy link
Copy Markdown

@mathuo
mathuo merged commit fa5c83c into master Jul 21, 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.

Tab groups can't be moved if a tab is in focus

1 participant