Skip to content

Commit

Permalink
update examples; add highlighted option;
Browse files Browse the repository at this point in the history
  • Loading branch information
m-wrzr committed Oct 28, 2024
1 parent 8807b48 commit 3b8e83c
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 10 deletions.
23 changes: 18 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,25 @@ Create a searchbox component and pass a `search_function` that accepts a `str` s
You can either pass a list of arguments, e.g.

```python
import streamlit as st
import wikipedia

from streamlit_searchbox import st_searchbox

# function with list of labels
def search_wikipedia(searchterm: str) -> List[any]:

def search_wikipedia(searchterm: str) -> list:
# search wikipedia for the searchterm
return wikipedia.search(searchterm) if searchterm else []


# pass search function to searchbox
# pass search function and other options as needed
selected_value = st_searchbox(
search_wikipedia,
key="wiki_searchbox",
placeholder="Search Wikipedia... ",
key="my_key",
)

st.write(f"Selected value: {selected_value}")
```

This example will call the Wikipedia Api to reload suggestions. The `selected_value` will be one of the items the `search_wikipedia` function returns, the suggestions shown in the UI components are a `str` representation. In case you want to provide custom text for suggestions, pass a `Tuple`.
Expand Down Expand Up @@ -195,18 +201,23 @@ To further customize the styling of the searchbox, you can override the default

```json
{
// change the clear icon
"clear":{
"width":20,
"height":20,
// also available: circle-unfilled, circle-filled
"icon":"cross",
// also available: never, after-submit
"clearable":"always"
},
// change the dropdown icon
"dropdown":{
"rotate":true,
"width":30,
"height":30,
"fill":"red"
},
// styling for the searchbox itself, mostly passed to react-select
"searchbox":{
"menuList":{
"backgroundColor":"transparent"
Expand All @@ -216,7 +227,9 @@ To further customize the styling of the searchbox, you can override the default
},
"option":{
"color":"blue",
"backgroundColor":"yellow"
"backgroundColor":"yellow",
// highlight matching text
"highlightColor":"green"
}
}
}
Expand Down
11 changes: 9 additions & 2 deletions example.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,10 @@ def search_kwargs(searchterm: str, **kwargs) -> List[str]:
default_options=["inital", "list", "of", "options"],
key=f"{search.__name__}_default_options",
label=f"{search.__name__}_default_options",
style_overrides={"clear": {"width": 25, "height": 25}},
style_overrides={
"clear": {"width": 25, "height": 25},
"searchbox": {"option": {"highlight": "#f1660f"}},
},
),
dict(
search_function=search,
Expand Down Expand Up @@ -268,7 +271,11 @@ def search_kwargs(searchterm: str, **kwargs) -> List[str]:
"searchbox": {
"menuList": {"backgroundColor": "transparent"},
"singleValue": {"color": "red", "some": "data"},
"option": {"color": "blue", "backgroundColor": "yellow"},
"option": {
"color": "blue",
"backgroundColor": "yellow",
"highlightColor": "green",
},
},
},
)
Expand Down
12 changes: 11 additions & 1 deletion streamlit_searchbox/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,14 +175,24 @@ def _set_defaults(
total=False,
)

OptionStyle = TypedDict(
"OptionStyle",
{
"color": str,
"backgroundColor": str,
"highlightColor": str | None,
},
total=False,
)


class SearchboxStyle(TypedDict, total=False):
menuList: dict | None
singleValue: dict | None
input: dict | None
placeholder: dict | None
control: dict | None
option: dict | None
option: OptionStyle | None


class StyleOverrides(TypedDict, total=False):
Expand Down
6 changes: 6 additions & 0 deletions streamlit_searchbox/frontend/src/Searchbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,12 @@ class Searchbox extends StreamlitComponentBase<State> {
),
IndicatorSeparator: () => null,
Input: editableAfterSubmit ? Input : components.Input,
Option: (props) =>
this.style.optionHighlighted(
props,
this.props.args.style_overrides?.searchbox?.option
?.highlightColor || undefined,
),
}}
// handlers
filterOption={(_, __) => true}
Expand Down
31 changes: 31 additions & 0 deletions streamlit_searchbox/frontend/src/styling.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
StylesConfig,
ControlProps,
OptionProps,
components,
} from "react-select";

import {
Expand All @@ -12,6 +13,7 @@ import {
ClearIconCross,
ClearIconCircularUnfilled,
} from "./icons";

class SearchboxStyle {
theme: any;
label: any;
Expand Down Expand Up @@ -188,6 +190,35 @@ class SearchboxStyle {
/>
);
}

optionHighlighted = (props: any, highlightColor: string | undefined) => {
if (!highlightColor || highlightColor === "") {
return <components.Option {...props} />;
}

const { children, selectProps } = props;
const inputValue = selectProps.inputValue as string;

// split into parts that match or don't match the inputValue
const parts =
typeof children === "string"
? children.split(new RegExp(`(${inputValue})`, "gi"))
: [];

return (
<components.Option {...props}>
{parts.map((part, index) =>
part.toLowerCase() === inputValue.toLowerCase() ? (
<span key={index} style={{ backgroundColor: highlightColor }}>
{part}
</span>
) : (
part // no match
),
)}
</components.Option>
);
};
}

export default SearchboxStyle;
2 changes: 0 additions & 2 deletions tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ def selection_to_text(result):
label=search_wikipedia_ids.__name__,
default="SOME DEFAULT",
clear_on_submit=False,
clearable=True,
key=search_wikipedia_ids.__name__,
),
dict(
Expand All @@ -96,7 +95,6 @@ def selection_to_text(result):
search_function=search_rnd_delay,
default=None,
clear_on_submit=False,
clearable=True,
label=search_rnd_delay.__name__,
key=search_rnd_delay.__name__,
),
Expand Down

0 comments on commit 3b8e83c

Please sign in to comment.