Skip to content

Commit

Permalink
feat: implement search input (#37)
Browse files Browse the repository at this point in the history
* feat: implement search input

* chore: bump pf-yew version
  • Loading branch information
aDogCalledSpot authored Nov 21, 2023
1 parent eaff417 commit 60b127b
Show file tree
Hide file tree
Showing 10 changed files with 180 additions and 4 deletions.
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ browser-panic-hook = "0.2"
chrono = { version = "0.4.30", default-features = false, features = ["wasmbind"] }
gloo-utils = "0.2"
log = "0.4"
patternfly-yew = { version = "0.5.1", features = ["tree", "dual_list_selector", "icons-fab"] }
patternfly-yew = { version = "0.5.2", features = ["tree", "dual_list_selector", "icons-fab", "search_input"] }
popper-rs = { version = "0.3.0", features = ["yew", "debug"] }
serde_json = "1"
strum = { version = "0.25", features = ["derive"] }
Expand All @@ -35,7 +35,7 @@ features = [

[patch.crates-io]
#patternfly-yew = { path = "../patternfly-yew" }
patternfly-yew = { git = "https://github.com/ctron/patternfly-yew", rev = "ef507153eabf2dd3ab4dff2ece3325896510daba" } # FIXME: awaiting release
#patternfly-yew = { git = "https://github.com/ctron/patternfly-yew", rev = "ef507153eabf2dd3ab4dff2ece3325896510daba" } # FIXME: awaiting release
#yew-nested-router = { path = "../yew-nested-router" }
#yew-more-hooks = { git = "https://github.com/ctron/yew-more-hooks", rev = "f535bb2e7b227aac7010035215c11d4aeae6cb62" } # FIXME: awaiting release
#yew-more-hooks = { path = "../yew-more-hooks" }
Expand Down
3 changes: 3 additions & 0 deletions src/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ pub enum Component {
Pagination,
Popover,
Progress,
SearchInput,
Skeleton,
Slider,
Spinner,
Expand Down Expand Up @@ -166,6 +167,7 @@ fn switch_app_route(target: AppRoute) -> Html {
Component::Pagination => html! {<components::PaginationExample/>},
Component::Popover => html! {<components::PopoverExample/>},
Component::Progress => html! {<components::ProgressExample/>},
Component::SearchInput => html! {<components::SearchInputExample/>},
Component::Skeleton => html! {<components::SkeletonExample/>},
Component::Slider => html! {<components::SliderExample/>},
Component::Spinner => html! {<components::SpinnerExample/>},
Expand Down Expand Up @@ -304,6 +306,7 @@ fn page(props: &PageProps) -> Html {
<NavRouterItem<AppRoute> to={AppRoute::Component(Component::Pagination)}>{"Pagination"}</NavRouterItem<AppRoute>>
<NavRouterItem<AppRoute> to={AppRoute::Component(Component::Popover)}>{"Popover"}</NavRouterItem<AppRoute>>
<NavRouterItem<AppRoute> to={AppRoute::Component(Component::Progress)}>{"Progress"}</NavRouterItem<AppRoute>>
<NavRouterItem<AppRoute> to={AppRoute::Component(Component::SearchInput)}>{"Search Input"}</NavRouterItem<AppRoute>>
<NavRouterItem<AppRoute> to={AppRoute::Component(Component::Skeleton)}>{"Skeleton"}</NavRouterItem<AppRoute>>
<NavRouterItem<AppRoute> to={AppRoute::Component(Component::Slider)}>{"Slider"}</NavRouterItem<AppRoute>>
<NavRouterItem<AppRoute> to={AppRoute::Component(Component::Spinner)}>{"Spinner"}</NavRouterItem<AppRoute>>
Expand Down
2 changes: 2 additions & 0 deletions src/components/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ mod modal;
mod pagination;
mod popover;
mod progress;
mod search_input;
mod skeleton;
mod slider;
mod spinner;
Expand Down Expand Up @@ -74,6 +75,7 @@ pub use modal::*;
pub use pagination::*;
pub use popover::*;
pub use progress::*;
pub use search_input::*;
pub use skeleton::*;
pub use slider::*;
pub use spinner::*;
Expand Down
25 changes: 25 additions & 0 deletions src/components/search_input/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use crate::{example, example::ExamplePage};

use patternfly_yew::prelude::*;
use yew::prelude::*;

#[function_component(SearchInputExample)]
pub fn search_input() -> Html {
let example1 = example! ("Basic" => "search_input.1.example");
let example2 = example! ("Match with result count" => "search_input.2.example");
let example3 = example! ("Match with navigable options" => "search_input.3.example");
let example4 = example! ("With submit button" => "search_input.4.example");
let example5 = example! ("With expandable button" => "search_input.5.example");

html! {
<>
<ExamplePage title="Search Input">
{example1}
{example2}
{example3}
{example4}
{example5}
</ExamplePage>
</>
}
}
31 changes: 31 additions & 0 deletions src/components/search_input/search_input.1.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
#[function_component(SearchInputExampleBasic)]
fn basic() -> Html {
let colors = &["red", "green", "blue", "black", "yellow", "purple"];

let value = use_state(String::new);
let onchange = use_callback(value.clone(), |new, old| old.set(new));
let onclear = use_callback(value.clone(), |_, val| val.set(String::new()));
let possible_values: Vec<&'static str> = colors
.iter()
.filter(|c| c.starts_with(&value.to_lowercase()))
.map(|c| *c)
.collect();
html! {
<>
<SearchInput
placeholder={"Find by name"}
value={(*value).clone()}
{onchange}
{onclear}
/>
<div>
{format!("Possible results: {possible_values:?}")}
</div>
</>
}
}
html! {
<SearchInputExampleBasic/>
}
}
25 changes: 25 additions & 0 deletions src/components/search_input/search_input.2.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
#[function_component(SearchInputExampleResults)]
fn results() -> Html {
let value = use_state(String::new);
let results = use_state(|| ResultsCount::Absolute(0));
let onchange = use_callback((value.clone(), results.clone()), |new, (value, results)| {
results.set(ResultsCount::Absolute(3));
value.set(new);
});
let onclear = use_callback((value.clone(), results.clone()), |_, (value, results)| {
results.set(ResultsCount::Absolute(0));
value.set(String::new())
});
html! {
<SearchInput
placeholder={"Find by name"}
value={(*value).clone()}
{onchange}
{onclear}
results_count={(*results).clone()}
/>
}
}
html! { <SearchInputExampleResults/> }
}
42 changes: 42 additions & 0 deletions src/components/search_input/search_input.3.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
#[function_component(SearchInputExampleNavigable)]
fn navigable() -> Html {
let value = use_state(String::new);
let results = use_state(|| 0);
let current_result = use_state(|| 1);

let onchange = use_callback((value.clone(), results.clone()), |new, (value, results)| {
results.set(3);
value.set(new)
});
let onclear = use_callback((value.clone(), results.clone()), |_, (value, results)| {
results.set(0);
value.set(String::new())
});
let onnextclick = use_callback(
(current_result.clone(), results.clone()),
|_, (current_result, results_count)| {
let new_result = (**current_result + 1).min(**results_count);
current_result.set(new_result)
}
);
let onpreviousclick = use_callback(current_result.clone(), |_, current_result| {
let new_result = (**current_result - 1).max(1);
current_result.set(new_result)
});
html! {
<SearchInput
placeholder={"Find by name"}
value={(*value).clone()}
{onchange}
{onclear}
results_count={ResultsCount::Fraction(*current_result, *results)}
{onnextclick}
{onpreviousclick}
previous_navigation_button_disabled={*current_result == 1}
next_navigation_button_disabled={*current_result == *results}
/>
}
}
html! { <SearchInputExampleNavigable/> }
}
21 changes: 21 additions & 0 deletions src/components/search_input/search_input.4.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
#[function_component(SearchInputExampleSubmit)]
fn submit() -> Html {
let value = use_state(String::new);

let onchange = use_callback(value.clone(), |new, old| old.set(new));
let onsearch = use_callback(value.clone(), |(_, new), old| old.set(new));
let onclear = use_callback(value.clone(), |_, old| old.set(String::new()));

html! {
<SearchInput
placeholder={"Find by name"}
value={(*value).clone()}
{onchange}
{onsearch}
{onclear}
/>
}
}
html! { <SearchInputExampleSubmit/> }
}
26 changes: 26 additions & 0 deletions src/components/search_input/search_input.5.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
#[function_component(SearchInputExampleExpand)]
fn expand() -> Html {
let value = use_state(String::new);
let expanded = use_state(|| false);

let onchange = use_callback(value.clone(), |new, value| value.set(new));
let ontoggleexpand = use_callback(expanded.clone(), |(_, prev): (MouseEvent, bool), curr| curr.set(!prev));
let expandable = SearchInputExpandableProperties {
expanded: *expanded,
ontoggleexpand,
toggle_aria_label: AttrValue::from("Expandable input search toggle"),
};
let onclear = use_callback(value.clone(), |_, value| value.set(String::new()));
html! {
<SearchInput
placeholder={"Find by name"}
value={(*value).clone()}
{onchange}
{expandable}
{onclear}
/>
}
}
html! { <SearchInputExampleExpand/> }
}

0 comments on commit 60b127b

Please sign in to comment.