diff --git a/crates/story/src/stories/settings_story.rs b/crates/story/src/stories/settings_story.rs index 252605ee7..a83961535 100644 --- a/crates/story/src/stories/settings_story.rs +++ b/crates/story/src/stories/settings_story.rs @@ -314,6 +314,18 @@ impl SettingsStory { .default_value(false), ) .description("Lock the other settings."), + SettingItem::new( + "Foo", + SettingField::switch( + |cx: &App| AppSettings::global(cx).disabled, + |checked: bool, cx: &mut App| { + AppSettings::global_mut(cx).disabled = checked + }, + ) + .default_value(false), + ) + .description("Find me by searching for my sibling") + .keywords(["Bar"]), SettingItem::render(|options, _, _| { h_flex() .w_full() diff --git a/crates/ui/src/setting/item.rs b/crates/ui/src/setting/item.rs index ee157880f..0ca3b960b 100644 --- a/crates/ui/src/setting/item.rs +++ b/crates/ui/src/setting/item.rs @@ -22,6 +22,7 @@ pub enum SettingItem { Item { title: SharedString, description: Option, + keywords: Vec, layout: Axis, disabled: bool, field: Rc, @@ -29,6 +30,7 @@ pub enum SettingItem { /// A full custom element to render. Element { disabled: bool, + keywords: Vec, render: Rc AnyElement + 'static>, }, } @@ -44,6 +46,7 @@ impl SettingItem { description: None, layout: Axis::Horizontal, disabled: false, + keywords: Vec::new(), field: Rc::new(field), } } @@ -56,12 +59,31 @@ impl SettingItem { { SettingItem::Element { disabled: false, + keywords: Vec::new(), render: Rc::new(move |options, window, cx| { render(options, window, cx).into_any_element() }), } } + /// Set additional keywords used only for search matching (not rendered). + /// + /// For example, an item titled "Enable Two-factor auth" can be made + /// searchable via "MFA". This is also useful for custom elements that + /// have no title/description but should still show up in search results. + pub fn keywords(mut self, keywords: I) -> Self + where + I: IntoIterator, + S: Into, + { + let keywords: Vec = keywords.into_iter().map(Into::into).collect(); + match &mut self { + SettingItem::Item { keywords: k, .. } => *k = keywords, + SettingItem::Element { keywords: k, .. } => *k = keywords, + } + self + } + /// Set whether the setting item is disabled, default is false. /// /// A disabled item is rendered with reduced opacity. For @@ -106,17 +128,23 @@ impl SettingItem { pub(crate) fn is_match(&self, query: &str, cx: &App) -> bool { match self { SettingItem::Item { - title, description, .. + title, + description, + keywords, + .. } => { - title.to_lowercase().contains(&query.to_lowercase()) - || description.as_ref().map_or(false, |d| { - d.get_text(cx) - .to_lowercase() - .contains(&query.to_lowercase()) - }) + let q = &query.to_lowercase(); + title.to_lowercase().contains(q) + || description + .as_ref() + .map_or(false, |d| d.get_text(cx).to_lowercase().contains(q)) + || keywords.iter().any(|s| s.to_lowercase().contains(q)) } // We need to show all custom elements when not searching. - SettingItem::Element { .. } => query.is_empty(), + SettingItem::Element { keywords, .. } => { + let q = &query.to_lowercase(); + query.is_empty() || keywords.iter().any(|s| s.to_lowercase().contains(q)) + } } } @@ -191,6 +219,7 @@ impl SettingItem { layout, disabled, field, + .. } => div() .w_full() .overflow_hidden() @@ -235,7 +264,9 @@ impl SettingItem { cx, ))) .into_any_element(), - SettingItem::Element { disabled, render } => div() + SettingItem::Element { + disabled, render, .. + } => div() .w_full() .when(disabled, |this| this.opacity(0.5)) .child((render)( diff --git a/docs/docs/components/settings.md b/docs/docs/components/settings.md index b2a2f11f7..cdfbd411e 100644 --- a/docs/docs/components/settings.md +++ b/docs/docs/components/settings.md @@ -8,7 +8,7 @@ description: A settings UI with grouped setting items and pages. > Since: v0.5.0 The Settings component provides a UI for managing application settings. It includes grouped setting items and pages. -We can search by title and description to filter the settings to display only relevant settings (Like this macOS, iOS Settings). +We can search by title, description, and custom keywords to filter the settings to display only relevant settings (Like this macOS, iOS Settings). ## Import @@ -260,6 +260,30 @@ SettingItem::render(|options, _, _| { .disabled(true) ``` +### Search Keywords + +Use `keywords` to attach additional search terms to an item. They are only used +for search matching and are never rendered. For example, an item titled "Enable +Two-factor auth" can be made searchable via "MFA": + +```rust +SettingItem::new( + "Enable Two-factor auth", + SettingField::switch(...) +) +.keywords(["MFA", "2FA"]) +``` + +This is also useful for [SettingItem::render] custom items that have no title or +description but should still appear in search results: + +```rust +SettingItem::render(|options, _, _| { + h_flex().child("Custom content").into_any_element() +}) +.keywords(["Advanced", "Network"]) +``` + ## Setting Fields The [SettingField] enum provides different field types for various input needs. diff --git a/docs/zh-CN/docs/components/settings.md b/docs/zh-CN/docs/components/settings.md index 0fe30eab2..2d2dc201c 100644 --- a/docs/zh-CN/docs/components/settings.md +++ b/docs/zh-CN/docs/components/settings.md @@ -7,7 +7,7 @@ description: 用于构建设置页、设置分组和设置项的界面组件。 > Since: v0.5.0 -Settings 组件用于构建应用设置界面,支持页面分组、搜索过滤以及多种字段类型,适合实现类似 macOS 或 iOS 设置页的结构。 +Settings 组件用于构建应用设置界面,支持页面分组、按标题/描述/自定义关键词搜索过滤以及多种字段类型,适合实现类似 macOS 或 iOS 设置页的结构。 ## 导入 @@ -253,6 +253,30 @@ SettingItem::render(|options, _, _| { .disabled(true) ``` +### 搜索关键词 + +通过 `keywords` 可以为设置项附加额外的搜索关键词。这些关键词仅用于搜索匹配, +不会被渲染出来。例如,标题为 "Enable Two-factor auth" 的设置项可以通过 "MFA" +搜索到: + +```rust +SettingItem::new( + "Enable Two-factor auth", + SettingField::switch(...) +) +.keywords(["MFA", "2FA"]) +``` + +这对于没有标题和描述、但仍希望能被搜索到的 [SettingItem::render] 自定义项同样 +有用: + +```rust +SettingItem::render(|options, _, _| { + h_flex().child("Custom content").into_any_element() +}) +.keywords(["Advanced", "Network"]) +``` + ## Setting Fields [SettingField] 枚举提供了多种常见字段类型。