From 367cd759636225affd1df3d10afc1199dbbb56e7 Mon Sep 17 00:00:00 2001
From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com>
Date: Thu, 16 Jul 2026 08:21:16 +0900
Subject: [PATCH] workspace: Add visual indicator for editor zoom (#61039)
The earlier editor-only zoom implementation in #32860 rendered the
active pane with padding, a border, rounded corners, and a shadow. In
addition to keeping docks visible, that treatment made the transient
editor zoom mode apparent.
The current `ToggleEditorZoom` implementation (#53911) only omits
sibling panes from the pane group, without any visual indication.
Without a persistent control or decoration, the result can look like an
ordinary single-pane layout, so users cannot tell whether toggling the
command will restore hidden splits.
So this commit renders the maximized pane as an inset card with padding,
a subtle theme border, rounded corners, and a shadow. Keeping this
treatment in `PaneGroup` makes it apply only to editor zoom, leaves
docks untouched, and distinguishes it from `ToggleZoom`'s square
workspace overlay.
## Showcase
---
Release Notes:
- N/A
---------
Co-authored-by: Danilo Leal
---
crates/workspace/src/pane_group.rs | 52 +++++++++++++++++++-----------
1 file changed, 34 insertions(+), 18 deletions(-)
diff --git a/crates/workspace/src/pane_group.rs b/crates/workspace/src/pane_group.rs
index dcd0b091a3f..3b0d07dcf25 100644
--- a/crates/workspace/src/pane_group.rs
+++ b/crates/workspace/src/pane_group.rs
@@ -545,39 +545,55 @@ impl Member {
};
}
- if let Some(maximized) = maximized {
+ let is_maximized = if let Some(maximized) = maximized {
if maximized.upgrade().as_ref() != Some(pane) {
return PaneRenderResult {
element: div().into_any(),
contains_active_pane: false,
};
}
- }
+ true
+ } else {
+ false
+ };
let decoration = render_cx.decorate(pane, cx);
let is_active = pane == render_cx.active_pane();
+ let pane = div()
+ .relative()
+ .size_full()
+ .when(is_maximized, |this| {
+ this.bg(cx.theme().colors().background)
+ .border_1()
+ .border_color(cx.theme().colors().border)
+ .shadow_lg()
+ .overflow_hidden()
+ })
+ .child(
+ AnyView::from(pane.clone())
+ .cached(StyleRefinement::default().v_flex().size_full()),
+ )
+ .when_some(decoration.border, |this, color| {
+ this.child(
+ div()
+ .absolute()
+ .size_full()
+ .left_0()
+ .top_0()
+ .border_2()
+ .border_color(color),
+ )
+ })
+ .children(decoration.status_box);
+
PaneRenderResult {
element: div()
.relative()
.flex_1()
.size_full()
- .child(
- AnyView::from(pane.clone())
- .cached(StyleRefinement::default().v_flex().size_full()),
- )
- .when_some(decoration.border, |this, color| {
- this.child(
- div()
- .absolute()
- .size_full()
- .left_0()
- .top_0()
- .border_2()
- .border_color(color),
- )
- })
- .children(decoration.status_box)
+ .when(is_maximized, |this| this.p_2())
+ .child(pane)
.into_any(),
contains_active_pane: is_active,
}