From 79106d7da9c2e1255ba80ce7bc4630bca10c686b Mon Sep 17 00:00:00 2001 From: Floyd Wang Date: Mon, 13 Jul 2026 10:49:32 +0800 Subject: [PATCH] setting: Add `title_suffix` for setting page header --- crates/story/src/stories/settings_story.rs | 9 ++++ crates/ui/src/setting/page.rs | 61 ++++++++++++++++------ docs/docs/components/settings.md | 17 ++++++ docs/zh-CN/docs/components/settings.md | 16 ++++++ 4 files changed, 86 insertions(+), 17 deletions(-) diff --git a/crates/story/src/stories/settings_story.rs b/crates/story/src/stories/settings_story.rs index f695ae71d2..1c3dd8f4bf 100644 --- a/crates/story/src/stories/settings_story.rs +++ b/crates/story/src/stories/settings_story.rs @@ -139,6 +139,15 @@ impl SettingsStory { .resettable(resettable) .default_open(true) .icon(Icon::new(IconName::Settings2)) + .title_suffix(|_, _| { + Button::new("help") + .icon(IconName::Info) + .ghost() + .xsmall() + .on_click(|_, _, cx| { + cx.open_url("https://longbridge.github.io/gpui-component/") + }) + }) .groups(vec![ SettingGroup::new().title("Appearance").items(vec![ SettingItem::new( diff --git a/crates/ui/src/setting/page.rs b/crates/ui/src/setting/page.rs index 94fb4488c5..6e6745e403 100644 --- a/crates/ui/src/setting/page.rs +++ b/crates/ui/src/setting/page.rs @@ -1,5 +1,7 @@ +use std::rc::Rc; + use gpui::{ - App, Entity, InteractiveElement as _, IntoElement, ListAlignment, ListState, + AnyElement, App, Entity, InteractiveElement as _, IntoElement, ListAlignment, ListState, ParentElement as _, SharedString, StyleRefinement, Styled, Window, div, list, prelude::FluentBuilder as _, px, }; @@ -22,6 +24,7 @@ pub struct SettingPage { resettable: bool, pub(super) default_open: bool, pub(super) title: SharedString, + pub(super) title_suffix: Option AnyElement>>, pub(super) description: Option, pub(super) groups: Vec, pub(super) header_style: StyleRefinement, @@ -34,6 +37,7 @@ impl SettingPage { resettable: true, default_open: false, title: title.into(), + title_suffix: None, description: None, groups: Vec::new(), header_style: StyleRefinement::default(), @@ -46,6 +50,20 @@ impl SettingPage { self } + /// Set a custom element to render after the title in the page header. + /// + /// For example, an info icon button that opens the help documentation. + pub fn title_suffix(mut self, suffix: F) -> Self + where + E: IntoElement, + F: Fn(&mut Window, &mut App) -> E + 'static, + { + self.title_suffix = Some(Rc::new(move |window, cx| { + suffix(window, cx).into_any_element() + })); + self + } + /// Set the icon of the setting page. pub fn icon(mut self, icon: impl Into) -> Self { self.icon = Some(icon.into()); @@ -149,24 +167,33 @@ impl SettingPage { .border_b_1() .border_color(cx.theme().border) .refine_style(&self.header_style) - .child(h_flex().justify_between().child(self.title.clone()).when( - self.is_resettable(cx), - |this| { - this.child( - Button::new("reset") - .icon(IconName::Undo2) - .ghost() - .small() - .tooltip(t!("Settings.Reset All")) - .on_click({ - let page = self.clone(); - move |_, window, cx| { - page.reset_all(window, cx); - } + .child( + h_flex() + .justify_between() + .child( + h_flex() + .gap_1() + .child(self.title.clone()) + .when_some(self.title_suffix.clone(), |this, suffix| { + this.child(suffix(window, cx)) }), ) - }, - )) + .when(self.is_resettable(cx), |this| { + this.child( + Button::new("reset") + .icon(IconName::Undo2) + .ghost() + .small() + .tooltip(t!("Settings.Reset All")) + .on_click({ + let page = self.clone(); + move |_, window, cx| { + page.reset_all(window, cx); + } + }), + ) + }), + ) .when_some(self.description.clone(), |this, description| { this.child( Label::new(description) diff --git a/docs/docs/components/settings.md b/docs/docs/components/settings.md index cdfbd411ee..e70b9ea2df 100644 --- a/docs/docs/components/settings.md +++ b/docs/docs/components/settings.md @@ -127,6 +127,23 @@ SettingPage::new("General") .groups(vec![...]) ``` +### Title Suffix + +Use `title_suffix` to render a custom element after the title in the page header, +for example an info icon button that opens the help documentation: + +```rust +SettingPage::new("General") + .title_suffix(|_, _| { + Button::new("help") + .icon(IconName::Info) + .ghost() + .xsmall() + .on_click(|_, _, cx| cx.open_url("https://example.com/help")) + }) + .groups(vec![...]) +``` + ### Default Open ```rust diff --git a/docs/zh-CN/docs/components/settings.md b/docs/zh-CN/docs/components/settings.md index 2d2dc201c2..0346121ed5 100644 --- a/docs/zh-CN/docs/components/settings.md +++ b/docs/zh-CN/docs/components/settings.md @@ -126,6 +126,22 @@ SettingPage::new("General") .groups(vec![...]) ``` +### 标题后缀 + +使用 `title_suffix` 在页头标题后渲染自定义元素,例如一个点击后打开帮助文档的 info 图标按钮: + +```rust +SettingPage::new("General") + .title_suffix(|_, _| { + Button::new("help") + .icon(IconName::Info) + .ghost() + .xsmall() + .on_click(|_, _, cx| cx.open_url("https://example.com/help")) + }) + .groups(vec![...]) +``` + ### 默认展开 ```rust