select, list: Update searchable default to false. (#1504)
Continue #1503 to update the `searchable` default to `false`.
This commit is contained in:
parent
2870bc6e36
commit
087cb70d00
7 changed files with 37 additions and 31 deletions
|
|
@ -304,6 +304,7 @@ impl DrawerStory {
|
|||
)
|
||||
.child(
|
||||
List::new(&list)
|
||||
.searchable(true)
|
||||
.border_1()
|
||||
.border_color(cx.theme().border)
|
||||
.rounded(cx.theme().radius)
|
||||
|
|
|
|||
|
|
@ -536,6 +536,7 @@ impl Render for ListStory {
|
|||
)
|
||||
.child(
|
||||
List::new(&self.company_list)
|
||||
.searchable(true)
|
||||
.p(px(8.))
|
||||
.flex_1()
|
||||
.w_full()
|
||||
|
|
|
|||
|
|
@ -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.))
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
```
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue