select, list: Update searchable default to false. (#1504)

Continue #1503 to update the `searchable` default to `false`.
This commit is contained in:
Jason Lee 2025-11-04 20:59:38 +08:00 committed by GitHub
parent 2870bc6e36
commit 087cb70d00
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 37 additions and 31 deletions

View file

@ -304,6 +304,7 @@ impl DrawerStory {
)
.child(
List::new(&list)
.searchable(true)
.border_1()
.border_color(cx.theme().border)
.rounded(cx.theme().radius)

View file

@ -536,6 +536,7 @@ impl Render for ListStory {
)
.child(
List::new(&self.company_list)
.searchable(true)
.p(px(8.))
.flex_1()
.w_full()

View file

@ -191,6 +191,7 @@ impl Render for SelectStory {
.child(
section("Select").max_w_128().child(
Select::new(&self.country_select)
.searchable(true)
.search_placeholder("Search country by name or code")
.cleanable()
.disabled(self.disabled),
@ -199,6 +200,7 @@ impl Render for SelectStory {
.child(
section("Searchable").max_w_128().child(
Select::new(&self.fruit_select)
.searchable(true)
.disabled(self.disabled)
.icon(IconName::Search)
.w(px(320.))

View file

@ -61,7 +61,7 @@ impl Default for ListOptions {
scrollbar_visible: true,
max_height: None,
selectable: true,
searchable: true,
searchable: false,
search_placeholder: None,
paddings: EdgesRefinement::default(),
}
@ -70,9 +70,9 @@ impl Default for ListOptions {
/// The state for List.
pub struct ListState<D: ListDelegate> {
focus_handle: FocusHandle,
pub(crate) focus_handle: FocusHandle,
pub(crate) query_input: Entity<InputState>,
options: ListOptions,
query_input: Option<Entity<InputState>>,
delegate: D,
last_query: Option<String>,
scroll_handle: VirtualListScrollHandle,
@ -104,7 +104,7 @@ where
options: ListOptions::default(),
delegate,
rows_cache: RowsCache::default(),
query_input: Some(query_input),
query_input,
last_query: None,
selected_index: None,
item_to_measure_index: IndexPath::default(),
@ -131,6 +131,11 @@ where
self.focus_handle(cx).focus(window);
}
/// Return true if either the list or the search input is focused.
pub(crate) fn is_focused(&self, window: &Window, cx: &App) -> bool {
self.focus_handle.is_focused(window) || self.query_input.focus_handle(cx).is_focused(window)
}
/// Set the selected index of the list,
/// this will also scroll to the selected item.
pub(crate) fn _set_selected_index(
@ -254,10 +259,8 @@ where
}
fn set_searching(&mut self, searching: bool, window: &mut Window, cx: &mut Context<Self>) {
if let Some(input) = &self.query_input {
input.update(cx, |input, cx| input.set_loading(searching, window, cx))
}
cx.notify();
self.query_input
.update(cx, |input, cx| input.set_loading(searching, window, cx));
}
/// Dispatch delegate's `load_more` method when the
@ -523,12 +526,8 @@ where
D: ListDelegate,
{
fn focus_handle(&self, cx: &App) -> FocusHandle {
if !self.options.searchable {
return self.focus_handle.clone();
}
if let Some(query_input) = &self.query_input {
query_input.focus_handle(cx)
if self.options.searchable {
self.query_input.focus_handle(cx)
} else {
self.focus_handle.clone()
}
@ -552,16 +551,12 @@ where
let loading = self.delegate().loading(cx);
let query_input = if self.options.searchable {
// sync placeholder
if let Some(query_input) = &self.query_input {
if let Some(placeholder) = &self.options.search_placeholder {
query_input.update(cx, |input, cx| {
input.set_placeholder(placeholder.clone(), window, cx);
});
}
Some(query_input.clone())
} else {
None
if let Some(placeholder) = &self.options.search_placeholder {
self.query_input.update(cx, |input, cx| {
input.set_placeholder(placeholder.clone(), window, cx);
});
}
Some(self.query_input.clone())
} else {
None
};
@ -591,7 +586,7 @@ where
.size_full()
.relative()
.overflow_hidden()
.when_some(query_input.clone(), |this, input| {
.when_some(query_input, |this, input| {
this.child(
div()
.map(|this| match self.options.size {
@ -670,7 +665,7 @@ where
self
}
/// Sets whether the list is searchable, default is `true`.
/// Sets whether the list is searchable, default is `false`.
///
/// When `true`, there will be a search input at the top of the list.
pub fn searchable(mut self, searchable: bool) -> Self {

View file

@ -324,7 +324,7 @@ impl Default for SelectOptions {
menu_width: Length::Auto,
disabled: false,
appearance: true,
searchable: true,
searchable: false,
search_placeholder: None,
}
}
@ -559,9 +559,12 @@ where
};
let list = cx.new(|cx| ListState::new(delegate, window, cx).reset_on_cancel(false));
let list_focus_handle = list.read(cx).focus_handle.clone();
let list_search_focus_handle = list.read(cx).query_input.focus_handle(cx);
let _subscriptions = vec![
cx.on_blur(&list.focus_handle(cx), window, Self::on_blur),
cx.on_blur(&list_focus_handle, window, Self::on_blur),
cx.on_blur(&list_search_focus_handle, window, Self::on_blur),
cx.on_blur(&focus_handle, window, Self::on_blur),
];
@ -645,7 +648,7 @@ where
fn on_blur(&mut self, window: &mut Window, cx: &mut Context<Self>) {
// When the select and dropdown menu are both not focused, close the dropdown menu.
if self.list.focus_handle(cx).is_focused(window) || self.focus_handle.is_focused(window) {
if self.list.read(cx).is_focused(window, cx) || self.focus_handle.is_focused(window) {
return;
}
@ -954,7 +957,7 @@ where
self
}
/// Sets whether the dropdown menu is searchable, default is `true`.
/// Sets whether the dropdown menu is searchable, default is `false`.
///
/// When `true`, there will be a search input at the top of the dropdown menu.
pub fn searchable(mut self, searchable: bool) -> Self {

View file

@ -171,6 +171,8 @@ fn render_item(
The list automatically includes a search input by default. Implement `perform_search` to handle queries:
And you should use `searchable(true)` when creating the list to show search input.
```rust
impl ListDelegate for MyListDelegate {
fn perform_search(
@ -190,9 +192,8 @@ impl ListDelegate for MyListDelegate {
}
}
// Create list without search input
let state = cx.new(|cx| ListState::new(delegate, window, cx));
List::new(&state).searchable(false)
List::new(&state).searchable(true)
```
### List with Loading State

View file

@ -65,6 +65,8 @@ Select::new(&state)
### Searchable
Use `searchable(true)` to enable search functionality within the dropdown.
```rust
let fruits = SearchableVec::new(vec![
"Apple", "Orange", "Banana", "Grape", "Pineapple",
@ -75,6 +77,7 @@ let state = cx.new(|cx| {
});
Select::new(&state)
.searchable(true)
.icon(IconName::Search) // Shows search icon
```