Skip to content

2453: add cross-window panel dnd - #2454

Open
the-nelsonator wants to merge 2 commits into
mbnuqw:v5from
the-nelsonator:2453-panel-dnd
Open

the-nelsonator wants to merge 2 commits into
mbnuqw:v5from
the-nelsonator:2453-panel-dnd

Conversation

@the-nelsonator

@the-nelsonator the-nelsonator commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

Closes #2453

Summary

Right now, you can only drag a panel into the tabs section to open its tabs in that panel.

This PR adds cross-window panel drag-and-drop: dragging a tabs-panel nav button from one browser window's panel section onto another window's panel section.

Also fixes an existing bug where the dnd line between panels (previously unfunctional) would only show on the left when the target window has only one panel. Now that it's functional it matters so was fixed.

Demo

Screen.Recording.2026-09-10.200412.mp4

Key decisions:

  1. Tabs always land in the same panel in the destination window as they were in the target, regardless of which nav button was the drop target. This aligns with current same-window panel dnd, where dragging one panel onto another doesn't move tabs to it.
  2. Panel-scoped pinned tabs (pinnedTabsPosition === 'panel') move with the panel; globally-pinned tabs never move.
  3. Tabs.move()'s cross-window pull branch calls moveToThisWin(...) without await — so naively awaiting Tabs.move() twice (once for pinned, once for normal, since moveToThisWin applies one pinned flag per batch) would race: overlapping detachTabs calls clobber Tabs.detachingTabIds (replaced, not merged) and read stale panel.nextTabIndex. Adds a new Tabs.movePanelTabsToThisWin() that does one detachSidebarTabs IPC call, partitions the returned tabs, then calls the properly-awaitable Tabs.moveToThisWin() twice sequentially.

Changes

  • tabs.fg.move.ts: added movePanelTabsToThisWin(); fixed a latent detachTabs bug where recalcVisibleTabs was gated on probeTab.pinned instead of the batch actually containing normal tabs.
  • bar.navigation.vue: panel drag payload now includes panel-scoped pinned tabs (pinned-first ordering, load-bearing for downstream browser.tabs.move calls); fixed a pre-existing implicit-any[] type issue on contentList exposed by refactoring the push logic into a closure.
  • drag-and-drop.fg.ts: new branch — external panel drop onto any nav-bar target activates/un-hides the panel then moves its tabs (splitting copy-mode and cross-incognito into Tabs.open/Tabs.reopen, deliberately skipping dropTabCtx re-containerization since tabs are already legitimately in P); snapshotted srcIndex/srcPanelId/dropMode before the first await since a 150ms-delayed stopDrag broadcast can reset shared DnD state mid-handler; guarded the existing panel→tab-list path so newly-included pinned items don't get silently unpinned there; nav-reorder now runs after the tab move (ordering is load-bearing — moveNavItem's updateSidebar re-sorts native tab order and would otherwise race the panel move).

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.

[Bug] Can't drag a panel across windows

1 participant