Skip to content

Group vertical tabs by project#9876

Open
rgatx wants to merge 2 commits intowarpdotdev:masterfrom
rgatx:rgatx/project-group-vertical-tabs
Open

Group vertical tabs by project#9876
rgatx wants to merge 2 commits intowarpdotdev:masterfrom
rgatx:rgatx/project-group-vertical-tabs

Conversation

@rgatx
Copy link
Copy Markdown

@rgatx rgatx commented May 2, 2026

Description

Adds an optional vertical-tabs setting to group visible tabs by detected project root. When enabled, vertical tabs render lightweight project section headers using the detected git repo root when available, falling back to the tab working directory. Unknown tabs remain independent so unrelated tabs are not collapsed together.

This is scoped to vertical tabs only and is default-off.

What changed

  • Added appearance.vertical_tabs.group_by_project, default false.
  • Added a "Group by project" toggle to the vertical tabs view options popup.
  • Added project grouping resolution for terminal and code panes:
    • Uses cached git repo roots from DetectedRepositories when available.
    • Falls back to normalized cwd/path.
    • Normalizes Windows drive paths and WSL /mnt/<drive>/... paths to the same grouping key shape.
    • Uses all panes/editor tabs in stable order so mixed-project tabs do not jump groups when focus changes.
  • Added project section headers with tab/pane counts and a rail colored from the top tab.
  • Preserved tab/pane colors instead of forcing group color onto every row.
  • Updated grouped drag/drop behavior so full visual orders can be materialized safely before pane insertion, while filtered views avoid partial-order materialization.
  • Added unit coverage for project grouping helpers, path normalization, visual-order validation, and active-tab preservation after visual-order materialization.

Notes on drag/drop behavior

When project grouping is enabled, dragging tabs or dropping panes may materialize the grouped visual order into the underlying tab order so grouped sections stay contiguous. While a vertical-tabs search filter is active, pane drops fall back to flat tab insertion rather than materializing a partial filtered order, to avoid reordering tabs that are hidden by search.

Scope

This PR is intentionally narrow. It does not propose a workspace concept, an explicit project configuration, or any UI beyond the existing vertical tab grouping setting surface. It only changes how tabs are grouped when the existing "Group by project" setting is enabled.

The resolver is structured to compose with the upcoming project primitive on the May–June 2026 roadmap (#9233). The detected project identity from this PR can be replaced or augmented by an explicit project configuration without changing the resolver's signature. The current order, git repo root, then normalized cwd, then unknown, would gain an explicit-project-match step at position 1 once that primitive lands.

Note: #9992 (vertical tabs panel position toggle) also touches vertical_tabs.rs. The two changes are orthogonal (placement vs grouping); rebase will be mechanical.

Follow-ups

Linked Issue

Draft PR for #9875.

  • The linked issue is labeled ready-to-spec or ready-to-implement.

Issue is pending maintainer guidance on whether this needs a spec PR first or can be marked ready-to-implement.

Screenshots / Videos

Loom walkthrough of the feature in action: https://www.loom.com/share/fde2ad29a4564237846d2ca384dd3c65

Testing

  • cargo fmt -p warp --check
  • git diff --check origin/master...HEAD
  • cargo check -p warp
  • cargo test -p warp --lib workspace::view::vertical_tabs
  • cargo test -p warp --lib visual_tab_order_rewrite

Note: local ./script/presubmit was not completed because this machine is using Homebrew rustc 1.93.0/Clippy while the repo pins 1.92.0; Clippy 1.93 reports new unnecessary_unwrap warnings in current origin/master unrelated to this branch.

Agent Mode

  • Warp Agent Mode - This PR was created via Warp's AI Agent Mode

Changelog Entries for Stable

CHANGELOG-IMPROVEMENT: Optionally group vertical tabs by detected git repo or working directory.

Co-Authored-By: Warp [email protected]

@cla-bot
Copy link
Copy Markdown

cla-bot Bot commented May 2, 2026

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 @rgatx 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 @cla-bot check to trigger another check.

@github-actions github-actions Bot added the external-contributor Indicates that a PR has been opened by someone outside the Warp team. label May 2, 2026
@AlexRokalo
Copy link
Copy Markdown

A very useful pull request! I came here specifically to see if something like this exists. It would also be great to add functions for hiding and collapsing groups in the UI, and highlighting the entire group with some color.

@rgatx
Copy link
Copy Markdown
Author

rgatx commented May 2, 2026

@cla-bot check

@cla-bot cla-bot Bot added the cla-signed label May 2, 2026
@cla-bot
Copy link
Copy Markdown

cla-bot Bot commented May 2, 2026

The cla-bot has been summoned, and re-checked this pull request!

@rgatx rgatx force-pushed the rgatx/project-group-vertical-tabs branch from 1eb87a7 to 63f024b Compare May 2, 2026 18:43
@rgatx rgatx marked this pull request as ready for review May 2, 2026 18:50
@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented May 2, 2026

@rgatx

I'm starting a first review of this pull request.

You can view the conversation on Warp.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

oz-for-oss[bot]
oz-for-oss Bot previously requested changes May 2, 2026
Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

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

Overview

This PR adds a default-off vertical tabs option that groups visible tabs by detected project identity, including new grouping UI, drag/drop handling, settings, telemetry, and unit coverage.

Concerns

  • WSL drive paths are normalized before cached repository-root lookup, which can cause DetectedRepositories lookups to miss the actual /mnt/<drive>/... path and fall back to per-directory cwd grouping instead of grouping subdirectories under the same repo.
  • This is a user-visible vertical tabs UI change, but the PR description says screenshots/videos are pending. For faster review, please upload screenshots or a video of the feature working end to end.

Verdict

Found: 0 critical, 2 important, 0 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

) -> ProjectGroupKey {
let mut candidate_paths: Vec<PathBuf> = Vec::new();
let mut push_candidate = |path: PathBuf| {
let path = normalize_project_group_path(path);
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.

⚠️ [IMPORTANT] Normalizing WSL paths before DetectedRepositories::get_root_for_path can make the cache lookup miss roots keyed by the actual /mnt/<drive>/... local path, so tabs in different subdirectories of the same repo fall back to separate cwd groups. Keep the raw path for repo-root lookup and normalize only the returned root or fallback key.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks for the review.

  1. Good catch on the WSL normalization order. The resolver currently normalizes paths before the DetectedRepositories cache lookup, which causes the cache miss you described. Fixing by restructuring so the lookup runs against the un-normalized path, and normalization only happens at the moment of constructing the ProjectGroupKey. Adding unit tests for the WSL/Windows-mixed case and the no-cache fallback.
  2. Recording the video on a Windows VM with WSL set up so I can demonstrate the path normalization
    end to end. Will attach to the PR description and mark ready-for-review once attached.

oz-for-oss[bot]
oz-for-oss Bot previously requested changes May 2, 2026
Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

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

Overview

This PR adds a default-off vertical tabs option that groups visible tabs by detected project identity, including new grouping UI, drag/drop handling, settings, telemetry, and unit coverage.

Concerns

  • WSL drive paths are normalized before cached repository-root lookup, which can cause DetectedRepositories lookups to miss the actual /mnt/<drive>/... path and fall back to per-directory cwd grouping instead of grouping subdirectories under the same repo.
  • This is a user-visible vertical tabs UI change, but the PR description says screenshots/videos are pending. For faster review, please upload screenshots or a video of the feature working end to end.

Verdict

Found: 0 critical, 2 important, 0 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

) -> ProjectGroupKey {
let mut candidate_paths: Vec<PathBuf> = Vec::new();
let mut push_candidate = |path: PathBuf| {
let path = normalize_project_group_path(path);
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.

⚠️ [IMPORTANT] Normalizing WSL paths before DetectedRepositories::get_root_for_path can make the cache lookup miss roots keyed by the actual /mnt/<drive>/... local path, so tabs in different subdirectories of the same repo fall back to separate cwd groups. Keep the raw path for repo-root lookup and normalize only the returned root or fallback key.

@rgatx
Copy link
Copy Markdown
Author

rgatx commented May 2, 2026

Thanks @AlexRokalo, glad this matches what you were looking for. Those follow-ups are good - collapsible sections and a fuller group color treatment are on my list. Group show/hide is interesting. I've got a broader project-scoped spec PR forthcoming this week and will tag you when that lands so you can weigh in.

@rgatx
Copy link
Copy Markdown
Author

rgatx commented May 4, 2026

/oz-review

@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented May 4, 2026

@rgatx

I'm re-reviewing this pull request in response to a review request.

You can view the conversation on Warp.

I reviewed this pull request and requested human review from: @zachbai.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

@oz-for-oss oz-for-oss Bot dismissed stale reviews from themself May 4, 2026 05:33

Oz no longer requests changes for this pull request after the latest automated review.

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

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

Overview

This PR adds a default-off vertical-tabs option to group tabs by detected project roots, with drag/drop materialization, project headers, telemetry, settings, and unit coverage. I also applied a security pass and did not find security concerns in the changed code.

Concerns

  • One render-time allocation pattern in the grouped vertical tabs path can be improved to avoid scaling poorly with large tab counts.

Verdict

Found: 0 critical, 0 important, 1 suggestions

Approve with nits

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

.find(|group| group.contains(&tab_index))
.cloned()
});
let visual_tab_order =
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.

💡 [SUGGESTION] This clones the full visual order for every rendered tab, and each insertion drop target can clone it again, making grouped vertical-tab rendering scale quadratically with tab count. Compute the complete order once per render and share it, for example with an Arc<[usize]> in the drag/drop state.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed external-contributor Indicates that a PR has been opened by someone outside the Warp team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants