title_bar: Add "panel layout" menu to the user menu (#54771)

Closes https://github.com/zed-industries/zed/issues/54545

With the release of the parallel agents feature, we changed the default
panel positions optimizing for an agentic-first layout. Even though we
introduced a settings backfill _and_ the ability to revert after
interacting with the announcement toast, this change seems to be causing
a bit of frustration still. In response, this PR adds a "Panel Layout"
menu in the user menu that allows to quickly toggle between the
"Classic" layout and the "Agentic" layout. If you have a different set
up, you'll see a "custom" item there just confirming that.

| Panel Layout | Custom set up |
|--------|--------|
| <img width="1110" height="866" alt="Screenshot 2026-04-24 at 12 
52@2x"
src="https://github.com/user-attachments/assets/197fc4ec-b4b3-4b13-bcb3-9d3495cf0d0a"
/> | <img width="1156" height="866" alt="Screenshot 2026-04-24 at 12 
55@2x"
src="https://github.com/user-attachments/assets/ca791b1b-eb6a-47a9-8aa5-c2015f33e5bd"
/> |

Release Notes:

- Added a menu item in the user menu called "Panel Layout" which offers
the ability to quickly swap between the two standard panel layouts:
classic (project panel, git panel, etc., on the left) and agentic (agent
panel on the left, everything else on the right).
This commit is contained in:
Danilo Leal 2026-04-24 09:47:15 -03:00 committed by GitHub
parent e483c3e1de
commit cd2248f76e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 54 additions and 2 deletions

2
Cargo.lock generated
View file

@ -18159,6 +18159,7 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
name = "title_bar"
version = "0.1.0"
dependencies = [
"agent_settings",
"anyhow",
"arrayvec",
"auto_update",
@ -18168,6 +18169,7 @@ dependencies = [
"client",
"cloud_api_types",
"db",
"fs",
"git_ui",
"gpui",
"icons",

View file

@ -29,8 +29,10 @@ test-support = [
]
[dependencies]
agent_settings.workspace = true
anyhow.workspace = true
auto_update.workspace = true
fs.workspace = true
platform_title_bar.workspace = true
call.workspace = true
channel.workspace = true

View file

@ -7,6 +7,7 @@ mod update_version;
use crate::application_menu::{ApplicationMenu, show_menus};
use crate::plan_chip::PlanChip;
use agent_settings::{AgentSettings, WindowLayout};
use arrayvec::ArrayVec;
use git_ui::worktree_picker::WorktreePicker;
pub use platform_title_bar::{
@ -44,8 +45,8 @@ use std::time::Duration;
use theme::ActiveTheme;
use title_bar_settings::TitleBarSettings;
use ui::{
Avatar, ButtonLike, ContextMenu, IconWithIndicator, Indicator, PopoverMenu, PopoverMenuHandle,
TintColor, Tooltip, prelude::*, utils::platform_title_bar_height,
Avatar, ButtonLike, ContextMenu, ContextMenuEntry, IconWithIndicator, Indicator, PopoverMenu,
PopoverMenuHandle, TintColor, Tooltip, prelude::*, utils::platform_title_bar_height,
};
use update_version::UpdateVersion;
use util::ResultExt;
@ -1202,6 +1203,13 @@ impl TitleBar {
let organizations = organizations.clone();
let user_store = user_store.clone();
let ai_enabled = !project::DisableAiSettings::get_global(cx).disable_ai;
let current_layout = AgentSettings::get_layout(cx);
let is_editor = matches!(current_layout, WindowLayout::Editor(_));
let is_agent = matches!(current_layout, WindowLayout::Agent(_));
let is_custom = matches!(current_layout, WindowLayout::Custom(_));
let fs = <dyn fs::Fs>::global(cx);
ContextMenu::build(window, cx, |menu, _, _cx| {
menu.when(is_signed_in, |this| {
let user_login = user_login.clone();
@ -1311,6 +1319,46 @@ impl TitleBar {
"Extensions",
zed_actions::Extensions::default().boxed_clone(),
)
.when(ai_enabled, |menu| {
let fs = fs.clone();
menu.separator()
.submenu("Panel Layout", move |menu, _window, _cx| {
let fs = fs.clone();
menu.toggleable_entry(
"Classic",
is_editor,
IconPosition::Start,
None,
{
let fs = fs.clone();
move |_window, cx| {
drop(AgentSettings::set_layout(
WindowLayout::Editor(None),
fs.clone(),
cx,
));
}
},
)
.toggleable_entry("Agentic", is_agent, IconPosition::Start, None, {
let fs = fs.clone();
move |_window, cx| {
drop(AgentSettings::set_layout(
WindowLayout::Agent(None),
fs.clone(),
cx,
));
}
})
.when(is_custom, |menu| {
menu.item(
ContextMenuEntry::new("Custom")
.toggleable(IconPosition::Start, true)
.disabled(true),
)
})
})
})
.when(is_signed_in, |this| {
this.separator()
.action("Sign Out", client::SignOut.boxed_clone())