layout: make strips the titlebar with window controls

This commit is contained in:
2026-11-02 19:04:13 +07:00
parent f295b25366
commit a6014b4ff3
13 changed files with 603 additions and 62 deletions
+43 -29
View File
@@ -3,8 +3,9 @@
use gpui::prelude::FluentBuilder as _;
use gpui::{
AnyElement, App, AppContext as _, Context, ElementId, Entity, IntoElement, ParentElement as _,
Pixels, RenderOnce, SharedString, Styled as _, Window, div, px,
AnyElement, App, AppContext as _, Context, ElementId, Entity, InteractiveElement as _,
IntoElement, ParentElement as _, Pixels, RenderOnce, SharedString,
StatefulInteractiveElement as _, Styled as _, Window, WindowControlArea, div, px,
};
use gpui_native_core::button::{Button, ButtonVariant};
use gpui_native_core::common::{Sizable as _, h_flex, v_flex};
@@ -13,6 +14,7 @@ use gpui_native_icons::IconRole;
use gpui_native_theme::{ActiveTheme as _, Size};
use crate::resize_handle::ResizeHandle;
use crate::window_controls::{TRAFFIC_LIGHT_PAD, WindowControls, maximize_on_double_click};
use crate::window_frame::frame;
/// The width a sidebar opens at.
@@ -254,37 +256,49 @@ fn sidebar_region(
strip_height: Pixels,
padding_x: Pixels,
) -> AnyElement {
let strip = h_flex()
.id(SharedString::from(format!("sidebar-strip-{}", side.name())))
.debug_selector(move || format!("sidebar-strip-{}", side.name()))
.flex_none()
.h(strip_height)
.items_center()
.justify_end()
.window_control_area(WindowControlArea::Drag)
.on_click(maximize_on_double_click())
.map(|strip| match side {
Side::Left => strip.when(cfg!(target_os = "macos"), |strip| {
strip.pl(px(TRAFFIC_LIGHT_PAD))
}),
Side::Right => strip.child(WindowControls::new("sidebar-window-controls")),
})
.px(padding_x)
.child(
Button::new(SharedString::from(format!(
"sidebar-toggle-{}",
side.name()
)))
.icon(side.toggle_icon())
.variant(ButtonVariant::Ghost)
.small()
.accessibility_label(side.toggle_label())
.on_click({
let state = state.clone();
move |_, _, cx| match side {
Side::Left => {
state.update(cx, |state, cx| state.set_left_sidebar_visible(false, cx))
}
Side::Right => {
state.update(cx, |state, cx| state.set_right_sidebar_visible(false, cx))
}
}
}),
);
v_flex()
.w(width)
.h_full()
.overflow_hidden()
.child(
h_flex()
.flex_none()
.h(strip_height)
.items_center()
.justify_end()
.px(padding_x)
.child(
Button::new(SharedString::from(format!(
"sidebar-toggle-{}",
side.name()
)))
.icon(side.toggle_icon())
.variant(ButtonVariant::Ghost)
.small()
.accessibility_label(side.toggle_label())
.on_click({
let state = state.clone();
move |_, _, cx| match side {
Side::Left => state
.update(cx, |state, cx| state.set_left_sidebar_visible(false, cx)),
Side::Right => state
.update(cx, |state, cx| state.set_right_sidebar_visible(false, cx)),
}
}),
),
)
.child(strip)
.child(div().flex_1().min_h_0().overflow_hidden().child(content))
.into_any_element()
}