From 42d80cc72f59e937777acc58b530e3b348b644bb Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Mon, 13 Jul 2026 16:40:11 +0800 Subject: [PATCH 1/2] feat(settings): stack fields in narrow containers Co-authored-by: Codex --- Cargo.lock | 56 +++++++++--------- crates/ui/src/setting/item.rs | 96 +++++++++++++++++-------------- crates/ui/src/setting/settings.rs | 32 +++++++---- 3 files changed, 102 insertions(+), 82 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f64959d0c7..434d543a82 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -692,7 +692,7 @@ dependencies = [ "bitflags 2.11.1", "cexpr", "clang-sys", - "itertools 0.13.0", + "itertools 0.11.0", "log", "prettyplease", "proc-macro2", @@ -1196,7 +1196,7 @@ dependencies = [ [[package]] name = "collections" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#c545fb67d0ce13e335bff76f7c08986000333f2c" +source = "git+https://github.com/zed-industries/zed#aeeacf5439b2d30d01e38d65d767e6f31b255ecc" dependencies = [ "gpui_util", "indexmap", @@ -1752,7 +1752,7 @@ dependencies = [ [[package]] name = "derive_refineable" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#c545fb67d0ce13e335bff76f7c08986000333f2c" +source = "git+https://github.com/zed-industries/zed#aeeacf5439b2d30d01e38d65d767e6f31b255ecc" dependencies = [ "proc-macro2", "quote", @@ -2847,7 +2847,7 @@ dependencies = [ "log", "presser", "thiserror 2.0.18", - "windows 0.62.2", + "windows 0.58.0", ] [[package]] @@ -2873,7 +2873,7 @@ dependencies = [ [[package]] name = "gpui" version = "0.2.2" -source = "git+https://github.com/zed-industries/zed#c545fb67d0ce13e335bff76f7c08986000333f2c" +source = "git+https://github.com/zed-industries/zed#aeeacf5439b2d30d01e38d65d767e6f31b255ecc" dependencies = [ "accesskit", "anyhow", @@ -3120,7 +3120,7 @@ dependencies = [ [[package]] name = "gpui_linux" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#c545fb67d0ce13e335bff76f7c08986000333f2c" +source = "git+https://github.com/zed-industries/zed#aeeacf5439b2d30d01e38d65d767e6f31b255ecc" dependencies = [ "accesskit", "accesskit_unix", @@ -3171,7 +3171,7 @@ dependencies = [ [[package]] name = "gpui_macos" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#c545fb67d0ce13e335bff76f7c08986000333f2c" +source = "git+https://github.com/zed-industries/zed#aeeacf5439b2d30d01e38d65d767e6f31b255ecc" dependencies = [ "accesskit", "accesskit_macos", @@ -3218,7 +3218,7 @@ dependencies = [ [[package]] name = "gpui_macros" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#c545fb67d0ce13e335bff76f7c08986000333f2c" +source = "git+https://github.com/zed-industries/zed#aeeacf5439b2d30d01e38d65d767e6f31b255ecc" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -3229,7 +3229,7 @@ dependencies = [ [[package]] name = "gpui_platform" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#c545fb67d0ce13e335bff76f7c08986000333f2c" +source = "git+https://github.com/zed-industries/zed#aeeacf5439b2d30d01e38d65d767e6f31b255ecc" dependencies = [ "console_error_panic_hook", "gpui", @@ -3242,7 +3242,7 @@ dependencies = [ [[package]] name = "gpui_shared_string" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#c545fb67d0ce13e335bff76f7c08986000333f2c" +source = "git+https://github.com/zed-industries/zed#aeeacf5439b2d30d01e38d65d767e6f31b255ecc" dependencies = [ "schemars", "serde", @@ -3252,7 +3252,7 @@ dependencies = [ [[package]] name = "gpui_util" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#c545fb67d0ce13e335bff76f7c08986000333f2c" +source = "git+https://github.com/zed-industries/zed#aeeacf5439b2d30d01e38d65d767e6f31b255ecc" dependencies = [ "anyhow", "log", @@ -3262,7 +3262,7 @@ dependencies = [ [[package]] name = "gpui_web" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#c545fb67d0ce13e335bff76f7c08986000333f2c" +source = "git+https://github.com/zed-industries/zed#aeeacf5439b2d30d01e38d65d767e6f31b255ecc" dependencies = [ "anyhow", "console_error_panic_hook", @@ -3286,7 +3286,7 @@ dependencies = [ [[package]] name = "gpui_wgpu" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#c545fb67d0ce13e335bff76f7c08986000333f2c" +source = "git+https://github.com/zed-industries/zed#aeeacf5439b2d30d01e38d65d767e6f31b255ecc" dependencies = [ "anyhow", "bytemuck", @@ -3315,7 +3315,7 @@ dependencies = [ [[package]] name = "gpui_windows" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#c545fb67d0ce13e335bff76f7c08986000333f2c" +source = "git+https://github.com/zed-industries/zed#aeeacf5439b2d30d01e38d65d767e6f31b255ecc" dependencies = [ "accesskit", "accesskit_windows", @@ -3631,7 +3631,7 @@ dependencies = [ [[package]] name = "http_client" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#c545fb67d0ce13e335bff76f7c08986000333f2c" +source = "git+https://github.com/zed-industries/zed#aeeacf5439b2d30d01e38d65d767e6f31b255ecc" dependencies = [ "anyhow", "async-compression", @@ -3651,7 +3651,7 @@ dependencies = [ [[package]] name = "http_client_tls" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#c545fb67d0ce13e335bff76f7c08986000333f2c" +source = "git+https://github.com/zed-industries/zed#aeeacf5439b2d30d01e38d65d767e6f31b255ecc" dependencies = [ "rustls", "rustls-platform-verifier", @@ -3732,7 +3732,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.62.2", + "windows-core 0.58.0", ] [[package]] @@ -4673,7 +4673,7 @@ dependencies = [ [[package]] name = "media" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#c545fb67d0ce13e335bff76f7c08986000333f2c" +source = "git+https://github.com/zed-industries/zed#aeeacf5439b2d30d01e38d65d767e6f31b255ecc" dependencies = [ "anyhow", "bindgen", @@ -5084,7 +5084,7 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" dependencies = [ - "proc-macro-crate 3.5.0", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "syn 2.0.117", @@ -5642,7 +5642,7 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "perf" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#c545fb67d0ce13e335bff76f7c08986000333f2c" +source = "git+https://github.com/zed-industries/zed#aeeacf5439b2d30d01e38d65d767e6f31b255ecc" dependencies = [ "collections", "serde", @@ -6640,7 +6640,7 @@ dependencies = [ [[package]] name = "refineable" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#c545fb67d0ce13e335bff76f7c08986000333f2c" +source = "git+https://github.com/zed-industries/zed#aeeacf5439b2d30d01e38d65d767e6f31b255ecc" dependencies = [ "derive_refineable", ] @@ -6692,7 +6692,7 @@ checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" [[package]] name = "reqwest_client" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#c545fb67d0ce13e335bff76f7c08986000333f2c" +source = "git+https://github.com/zed-industries/zed#aeeacf5439b2d30d01e38d65d767e6f31b255ecc" dependencies = [ "anyhow", "bytes", @@ -7129,7 +7129,7 @@ dependencies = [ [[package]] name = "scheduler" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#c545fb67d0ce13e335bff76f7c08986000333f2c" +source = "git+https://github.com/zed-industries/zed#aeeacf5439b2d30d01e38d65d767e6f31b255ecc" dependencies = [ "async-task", "backtrace", @@ -7750,7 +7750,7 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "sum_tree" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#c545fb67d0ce13e335bff76f7c08986000333f2c" +source = "git+https://github.com/zed-industries/zed#aeeacf5439b2d30d01e38d65d767e6f31b255ecc" dependencies = [ "heapless", "log", @@ -9211,7 +9211,7 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "util_macros" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#c545fb67d0ce13e335bff76f7c08986000333f2c" +source = "git+https://github.com/zed-industries/zed#aeeacf5439b2d30d01e38d65d767e6f31b255ecc" dependencies = [ "perf", "quote", @@ -11211,7 +11211,7 @@ dependencies = [ [[package]] name = "zlog" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#c545fb67d0ce13e335bff76f7c08986000333f2c" +source = "git+https://github.com/zed-industries/zed#aeeacf5439b2d30d01e38d65d767e6f31b255ecc" dependencies = [ "anyhow", "chrono", @@ -11228,7 +11228,7 @@ checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" [[package]] name = "ztracing" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#c545fb67d0ce13e335bff76f7c08986000333f2c" +source = "git+https://github.com/zed-industries/zed#aeeacf5439b2d30d01e38d65d767e6f31b255ecc" dependencies = [ "tracing", "tracing-subscriber", @@ -11239,7 +11239,7 @@ dependencies = [ [[package]] name = "ztracing_macro" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#c545fb67d0ce13e335bff76f7c08986000333f2c" +source = "git+https://github.com/zed-industries/zed#aeeacf5439b2d30d01e38d65d767e6f31b255ecc" [[package]] name = "zune-core" diff --git a/crates/ui/src/setting/item.rs b/crates/ui/src/setting/item.rs index edae4f5970..27ed22af07 100644 --- a/crates/ui/src/setting/item.rs +++ b/crates/ui/src/setting/item.rs @@ -263,50 +263,58 @@ impl SettingItem { disabled, field, .. - } => div() - .w_full() - .overflow_hidden() - .when(disabled, |this| this.opacity(0.5)) - .map(|this| { - if layout.is_horizontal() { - this.h_flex().justify_between().items_start() - } else { - this.v_flex() - } - }) - .gap_3() - .child( - v_flex() - .map(|this| { - if layout.is_horizontal() { - this.flex_1().max_w_3_5() - } else { - this.w_full() - } - }) - .gap_1() - .child(Label::new(title.clone()).text_sm()) - .when_some(description.clone(), |this, description| { - this.child( - div() - .size_full() - .text_sm() - .text_color(cx.theme().muted_foreground) - .child(description), - ) - }), - ) - .child(div().id("field").child(Self::render_field( - field, - RenderOptions { - layout, - disabled, - ..*options - }, - window, - cx, - ))) - .into_any_element(), + } => { + let layout = if options.layout.is_vertical() { + Axis::Vertical + } else { + layout + }; + + div() + .w_full() + .overflow_hidden() + .when(disabled, |this| this.opacity(0.5)) + .map(|this| { + if layout.is_horizontal() { + this.h_flex().justify_between().items_start() + } else { + this.v_flex() + } + }) + .gap_3() + .child( + v_flex() + .map(|this| { + if layout.is_horizontal() { + this.flex_1().max_w_3_5() + } else { + this.w_full() + } + }) + .gap_1() + .child(Label::new(title).text_sm()) + .when_some(description, |this, description| { + this.child( + div() + .size_full() + .text_sm() + .text_color(cx.theme().muted_foreground) + .child(description), + ) + }), + ) + .child(div().id("field").child(Self::render_field( + field, + RenderOptions { + layout, + disabled, + ..*options + }, + window, + cx, + ))) + .into_any_element() + } SettingItem::Element { disabled, render, .. } => div() diff --git a/crates/ui/src/setting/settings.rs b/crates/ui/src/setting/settings.rs index ee4ba9aa5d..9ed8a45a1a 100644 --- a/crates/ui/src/setting/settings.rs +++ b/crates/ui/src/setting/settings.rs @@ -10,10 +10,13 @@ use crate::{ }; use gpui::{ App, AppContext as _, Axis, ElementId, Entity, IntoElement, ParentElement as _, Pixels, - RenderOnce, StyleRefinement, Styled, Window, div, prelude::FluentBuilder as _, px, relative, + RenderOnce, StyleRefinement, Styled, Window, container_query, div, prelude::FluentBuilder as _, + px, relative, }; use rust_i18n::t; +const STACKED_LAYOUT_MAX_WIDTH: Pixels = px(480.); + /// The settings structure containing multiple pages for app settings. /// /// The hierarchy of settings is as follows: @@ -145,7 +148,7 @@ impl Settings { options: &RenderOptions, window: &mut Window, cx: &mut App, - ) -> impl IntoElement { + ) -> gpui::AnyElement { let selected_index = state.read(cx).selected_index; for (ix, page) in pages.into_iter().enumerate() { @@ -294,20 +297,29 @@ impl RenderOnce for Settings { disabled: false, }; let sidebar_size_range = self.sidebar_size_range.clone(); + let sidebar = self + .render_sidebar(&state, &filtered_pages, window, cx) + .into_any_element(); h_resizable(self.id.clone()) .child( resizable_panel() .size(self.sidebar_width) .size_range(sidebar_size_range) - .child(self.render_sidebar(&state, &filtered_pages, window, cx)), + .child(sidebar), + ) + .child( + resizable_panel().child(container_query(move |size, window, cx| { + let options = RenderOptions { + layout: if size.width <= STACKED_LAYOUT_MAX_WIDTH { + Axis::Vertical + } else { + Axis::Horizontal + }, + ..options + }; + self.render_active_page(&state, &filtered_pages, &options, window, cx) + })), ) - .child(resizable_panel().child(self.render_active_page( - &state, - &filtered_pages, - &options, - window, - cx, - ))) } } From ace1b2040f77494a961d99ead0e08c14360b3580 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Mon, 13 Jul 2026 19:27:12 +0800 Subject: [PATCH 2/2] test(scroll): account for stretched GPUI roots GPUI now stretches auto-sized window roots to the viewport. Keep the auto-height panel under an explicit viewport root so the test continues to exercise descendant intrinsic sizing. Co-authored-by: Codex --- crates/ui/src/scroll/scrollable.rs | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/crates/ui/src/scroll/scrollable.rs b/crates/ui/src/scroll/scrollable.rs index e35d529914..d144ebf37c 100644 --- a/crates/ui/src/scroll/scrollable.rs +++ b/crates/ui/src/scroll/scrollable.rs @@ -325,20 +325,24 @@ mod tests { // Mimics Dialog: the panel height is auto (content-driven), the // body is flex_1 + overflow_hidden, and the scrollable content // should give the panel its intrinsic height. - crate::v_flex() - .w(px(200.)) - .child( - crate::v_flex().flex_1().overflow_hidden().child( - div().flex_1().overflow_hidden().child( - crate::v_flex() - .size_full() - .overflow_y_scrollbar() - .child(plain_row(50.)) - .child(plain_row(50.)), + // GPUI window roots with auto dimensions stretch to the viewport, + // so keep the auto-height panel below an explicit viewport root. + div().size_full().child( + crate::v_flex() + .w(px(200.)) + .child( + crate::v_flex().flex_1().overflow_hidden().child( + div().flex_1().overflow_hidden().child( + crate::v_flex() + .size_full() + .overflow_y_scrollbar() + .child(plain_row(50.)) + .child(plain_row(50.)), + ), ), - ), - ) - .child(row("auto-height-footer", 10.)) + ) + .child(row("auto-height-footer", 10.)), + ) } }