diff --git a/crates/story/src/dropdown_story.rs b/crates/story/src/dropdown_story.rs index 838f0516..ded9900f 100644 --- a/crates/story/src/dropdown_story.rs +++ b/crates/story/src/dropdown_story.rs @@ -42,6 +42,10 @@ impl DropdownItem for Country { self.name.clone() } + fn display_title(&self) -> Option { + Some(format!("{} ({})", self.name, self.code).into_any_element()) + } + fn value(&self) -> &Self::Value { &self.code } diff --git a/crates/ui/src/dropdown.rs b/crates/ui/src/dropdown.rs index 921473d7..1066549f 100644 --- a/crates/ui/src/dropdown.rs +++ b/crates/ui/src/dropdown.rs @@ -43,6 +43,12 @@ pub fn init(cx: &mut App) { pub trait DropdownItem { type Value: Clone; fn title(&self) -> SharedString; + /// Customize the display title used to selected item in Dropdown Input. + /// + /// If return None, the title will be used. + fn display_title(&self) -> Option { + None + } fn value(&self) -> &Self::Value; } @@ -550,33 +556,49 @@ where cx.emit(DropdownEvent::Confirm(None)); } + /// Returns the title element for the dropdown input. fn display_title(&self, _: &Window, cx: &App) -> impl IntoElement { - let title = if let Some(selected_index) = &self.selected_index(cx) { - let mut title = self - .list - .read(cx) - .delegate() - .delegate - .get(*selected_index) - .map(|item| item.title().to_string()) - .unwrap_or_default(); - - if let Some(prefix) = self.title_prefix.as_ref() { - title = format!("{}{}", prefix, title); - } - - div().child(title.clone()) - } else { - div().text_color(cx.theme().accent_foreground).child( + let default_title = div() + .text_color(cx.theme().accent_foreground) + .child( self.placeholder .clone() .unwrap_or_else(|| t!("Dropdown.placeholder").into()), ) + .when(self.disabled, |this| { + this.text_color(cx.theme().muted_foreground) + }); + + let Some(selected_index) = &self.selected_index(cx) else { + return default_title; }; - title.when(self.disabled, |this| { - this.text_color(cx.theme().muted_foreground) - }) + let Some(title) = self + .list + .read(cx) + .delegate() + .delegate + .get(*selected_index) + .map(|item| { + if let Some(el) = item.display_title() { + el + } else { + if let Some(prefix) = self.title_prefix.as_ref() { + format!("{}{}", prefix, item.title()).into_any_element() + } else { + item.title().into_any_element() + } + } + }) + else { + return default_title; + }; + + div() + .when(self.disabled, |this| { + this.text_color(cx.theme().muted_foreground) + }) + .child(title) } }