Add drag-tab-to-pane-split#11404
Conversation
Lets users drag a tab from the vertical tabs panel and drop it onto another tab's pane area to create a directional split (left/right/up/down). The destination pane is computed from the cursor's closest edge, and a translucent half-pane overlay previews where the new pane will land during drag. When the source is the currently-active tab, the workspace auto-switches to the previous MRU tab so the user has a visible destination; the original active tab is restored if the drop is cancelled. Gated behind a new `DragTabToPaneSplit` feature flag (off by default). Co-Authored-By: Warp <agent@warp.dev>
|
Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have the users @vascodegraaff on file. In order for us to review and merge your code, each contributor must visit https://cla.warp.dev to read and agree to our CLA. Once you have done so, please comment |
|
/oz-review |
|
This PR is not linked to an issue that is marked with Issue-state enforcement details:
Readiness check:
To continue, link this PR to a same-repo issue such as Powered by Oz |
There was a problem hiding this comment.
This PR is not linked to an issue that is marked with ready-to-implement.
Issue-state enforcement details:
-
Associated same-repo issues checked: #8959
-
Required readiness label:
ready-to-implement
Readiness check:
- #8959: missing
ready-to-implement; readiness labels present: none
To continue, link this PR to a same-repo issue such as Closes #123 in the PR description, and make sure that issue has ready-to-implement.
Powered by Oz
Fixes a wrong-target overlay regression that landed with the initial PR: `find_drop_target_pane` iterated over every tab and asked `element_position_by_id` for each pane's rect. Pane positions are cached indefinitely and are never cleared when a `PaneGroup` unmounts, so panes from previously-active tabs returned stale rects that could match the cursor and route the drop to the wrong destination tab. The lookup is now restricted to the active tab — the only tab whose panes are actually in the rendered view tree. Suppresses the tab-reorder block in `on_tab_drag` when the drag is hovering over another tab's pane area. Without this guard, the reorder logic swaps the source tab into the destination tab's slot and flips `active_tab_index`, which then makes `find_drop_target_pane` reject the follow-up drop because `src_idx == active_tab_index`. Drops the iTerm-style auto-switch-to-MRU-previous behavior that the initial PR added. The view now stays on the user's current tab throughout the drag; dragging the active tab onto its own pane is a no-op. Adds a tall tail drop-zone below the last tab in the vertical tabs panel so the empty area catches pane-header drags as "append new tab" with the existing blue insertion indicator at the top. Kills the flicker caused by the cursor leaving the small per-tab `insert_after_index` sliver into a no-drop-target gap. Adds integration tests in `crates/integration` covering the happy path (Right split), one non-Right direction (Down split via cursor position on the bottom half of the destination pane), and two no-op cases (source tab has an internal split; dragging the active tab onto its own pane). Gated on a new `drag_tab_to_pane_split` Cargo feature in the integration crate that forwards to the warp crate.
…ane-split # Conflicts: # crates/integration/src/test/workspace.rs
There was a problem hiding this comment.
This PR is not linked to an issue that is marked with ready-to-implement.
Issue-state enforcement details:
-
Associated same-repo issues checked: #8959
-
Required readiness label:
ready-to-implement
Readiness check:
- #8959: missing
ready-to-implement; readiness labels present: none
To continue, link this PR to a same-repo issue such as Closes #123 in the PR description, and make sure that issue has ready-to-implement.
Powered by Oz
|
/oz-review who can i ping about updating the status of the issue? |
There was a problem hiding this comment.
This PR is not linked to an issue that is marked with ready-to-implement.
Issue-state enforcement details:
-
Associated same-repo issues checked: #8959
-
Required readiness label:
ready-to-implement
Readiness check:
- #8959: missing
ready-to-implement; readiness labels present: none
To continue, link this PR to a same-repo issue such as Closes #123 in the PR description, and make sure that issue has ready-to-implement.
Powered by Oz
who can i tag to update this? @oz-agent |
Description
Adds a new UX for splitting tabs: drag a tab from the vertical tabs panel and drop it onto another tab's pane area to create a directional split.
Behavior
theme.surface_overlay_2/theme.split_pane_border_color) previews where the new pane will land during the drag.Out of scope (deferred to follow-ups)
DragTabsToWindowsflow handles cross-window detach unchanged).Gated behind a new
DragTabToPaneSplitfeature flag (off by default — dark merge).How
FeatureFlag::DragTabToPaneSplitvariant, registered inapp/src/features.rsbehind adrag_tab_to_pane_splitCargo feature.pub(crate) PaneGroup::add_existing_pane_visible(...)helper next toadd_pane_as_hidden, wrappingadd_pane_with_optionsfor cross-PaneGroup transplant.last_tab_dragandcurrent_drag_target_pane;on_tab_dragand theDropTabarm coordinate hit-testing, cross-window suppression, and the actual drop viatry_drop_tab_on_pane.find_drop_target_paneis restricted to the active tab only. Pane positions are cached indefinitely and never cleared when aPaneGroupunmounts, so iterating over every tab would match stale rects from previously-active tabs and route the drop to the wrong destination.on_tab_dragsuppresses its reorder block when the cursor is hovering over another tab's pane area. Without this, the source tab would get swapped into the destination tab's slot andactive_tab_indexwould flip, which then makes the follow-up drop reject (src_idx == active_tab_index).SavePositionfor panes (pane_id.position_id()).PaneGroup::remove_pane_for_move(which callsdetach(DetachType::Moved)to preserve session state) andremove_tab_without_undo.vertical_tabs.rsunlocks horizontal drag when eitherDragTabsToWindowsorDragTabToPaneSplitis enabled, and renders a tall tail drop zone (with the existing insertion-indicator slot at the top) below the last tab so the empty area below catches drops cleanly without flicker.Directionenum gainsPartialEq, Eqso the workspace can diff drag-target state across frames.Linked Issue
Closes #8959.
ready-to-specorready-to-implement.(Issue #8959 is labeled
enhancement/triaged/area:window-tabs-panes. Flagging in case maintainers want to addready-to-implementretroactively — I picked this up because it matched what I wanted to build personally.)Testing
./script/run --features drag_tab_to_pane_splitManual test matrix walked through:
Automated tests
Integration tests added in
crates/integration/src/test/workspace.rs, gated on a newdrag_tab_to_pane_splitfeature in the integration crate (forwards towarp/drag_tab_to_pane_split). Registered inbin/integration.rsandtests/integration/ui_tests.rs:test_drag_tab_to_pane_split_right— happy path: 2 tabs, drag non-active onto active's pane right-half → 1 tab with 2 panes; both terminals' block history is intact (verifies theDetachType::Movedsession preservation).test_drag_tab_to_pane_split_down— direction picking: drop on bottom half → panes stack vertically (verified by inspecting rendered pane rects).test_drag_tab_to_pane_split_source_with_split_is_noop— source tab has 2 panes → drop rejected, workspace unchanged.test_drag_tab_to_pane_split_active_self_drop_is_noop— drag active tab onto its own pane → drop rejected (covers thesrc_idx == active_tab_indexguard added above).Run a single test directly:
Or via nextest:
Screenshots / Videos
Screen.Recording.2026-05-26.at.4.02.30.PM.mov
Agent Mode
CHANGELOG-IMPROVEMENT: You can now drag a tab from the left vertical tabs panel and drop it onto another tab's pane area to create a directional split, behind the
drag_tab_to_pane_splitfeature flag.