From 55db53a46d0cc8a9760a10b441d5935538b6df8c Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Tue, 28 Oct 2025 21:37:00 +0800 Subject: [PATCH] select: Impl SelectItem for `&'static str`. (#1451) --- crates/story/src/select_story.rs | 38 +++++++++++--------------------- crates/ui/src/select.rs | 12 ++++++++++ docs/docs/components/select.md | 26 +++++++++++++++------- 3 files changed, 43 insertions(+), 33 deletions(-) diff --git a/crates/story/src/select_story.rs b/crates/story/src/select_story.rs index 05a536bf..10f3e24b 100644 --- a/crates/story/src/select_story.rs +++ b/crates/story/src/select_story.rs @@ -38,9 +38,9 @@ impl SelectItem for Country { pub struct SelectStory { disabled: bool, country_select: Entity>>>, - fruit_select: Entity>>, - simple_select1: Entity>>, - simple_select2: Entity>>, + fruit_select: Entity>>, + simple_select1: Entity>>, + simple_select2: Entity>>, simple_select3: Entity>>, disabled_select: Entity>>, appearance_select: Entity>>, @@ -103,13 +103,13 @@ impl SelectStory { let input_state = cx.new(|cx| InputState::new(window, cx).placeholder("Your phone number")); let fruits = SearchableVec::new(vec![ - "Apple".into(), - "Orange".into(), - "Banana".into(), - "Grape".into(), - "Pineapple".into(), - "Watermelon & This is a long long long long long long long long long title".into(), - "Avocado".into(), + "Apple", + "Orange", + "Banana", + "Grape", + "Pineapple", + "Watermelon & This is a long long long long long long long long long title", + "Avocado", ]); let fruit_select = cx.new(|cx| SelectState::new(fruits, None, window, cx)); @@ -124,15 +124,8 @@ impl SelectStory { simple_select1: cx.new(|cx| { SelectState::new( vec![ - "GPUI".into(), - "Iced".into(), - "egui".into(), - "Makepad".into(), - "Slint".into(), - "QT".into(), - "ImGui".into(), - "Cocoa".into(), - "WinUI".into(), + "GPUI", "Iced", "egui", "Makepad", "Slint", "QT", "ImGui", "Cocoa", + "WinUI", ], Some(IndexPath::default()), window, @@ -143,12 +136,7 @@ impl SelectStory { let mut select = SelectState::new(SearchableVec::new(vec![]), None, window, cx); select.set_items( - SearchableVec::new(vec![ - "Rust".into(), - "Go".into(), - "C++".into(), - "JavaScript".into(), - ]), + SearchableVec::new(vec!["Rust", "Go", "C++", "JavaScript"]), window, cx, ); diff --git a/crates/ui/src/select.rs b/crates/ui/src/select.rs index 05400acd..2afff7f9 100644 --- a/crates/ui/src/select.rs +++ b/crates/ui/src/select.rs @@ -72,6 +72,18 @@ impl SelectItem for SharedString { } } +impl SelectItem for &'static str { + type Value = Self; + + fn title(&self) -> SharedString { + SharedString::from(self.to_string()) + } + + fn value(&self) -> &Self::Value { + self + } +} + pub trait SelectDelegate: Sized { type Item: SelectItem; diff --git a/docs/docs/components/select.md b/docs/docs/components/select.md index b8562b6f..fd2534d1 100644 --- a/docs/docs/components/select.md +++ b/docs/docs/components/select.md @@ -28,10 +28,16 @@ use gpui_component::select::{ ### Basic Select +You can create a basic select dropdown by initializing a `SelectState` with a list of items. + +The first type parameter of `SelectState` is the items for the state, which must implement the [SelectItem] trait. + +The built-in implementations of `SelectItem` include common types like `String`, `SharedString`, and `&'static str`. + ```rust let state = cx.new(|cx| { SelectState::new( - vec!["Apple".into(), "Orange".into(), "Banana".into()], + vec!["Apple", "Orange", "Banana"], Some(IndexPath::default()), // Select first item window, cx, @@ -46,7 +52,7 @@ Select::new(&state) ```rust let state = cx.new(|cx| { SelectState::new( - vec!["Rust".into(), "Go".into(), "JavaScript".into()], + vec!["Rust", "Go", "JavaScript"], None, // No initial selection window, cx, @@ -61,11 +67,7 @@ Select::new(&state) ```rust let fruits = SearchableVec::new(vec![ - "Apple".into(), - "Orange".into(), - "Banana".into(), - "Grape".into(), - "Pineapple".into(), + "Apple", "Orange", "Banana", "Grape", "Pineapple", ]); let state = cx.new(|cx| { @@ -76,7 +78,13 @@ Select::new(&state) .icon(IconName::Search) // Shows search icon ``` -### Custom Item +### Impl SelectItem + +By default, we have implmemented `SelectItem` for common types like `String`, `SharedString` and `&'static str`. You can also create your own item types by implementing the `SelectItem` trait. + +This is useful when you want to display complex data structures, and also want get that data type from `select_value` method. + +You can also customize the search logic by overriding the `matches` method. ```rust #[derive(Debug, Clone)] @@ -377,3 +385,5 @@ The dropdown respects the current theme and uses the following theme tokens: - `accent_foreground` - Placeholder text color - `border` - Menu border - `radius` - Border radius + +[SelectItem]: https://docs.rs/gpui-component/latest/gpui_component/select/trait.SelectItem.html