SearchBox
Overview
The "Search Box" in an e-commerce page is a user interface element that allows users to quickly and easily search for specific products within an online store's catalog.
Usage
// importing component
import { SearchBox } from "@unbxd-ui/react-search-components";
// import styles for the component
import "@unbxd-ui/react-search-components/styles/searchbox.css";
import "@unbxd-ui/react-search-components/styles/autosuggest.css";
If the styles import does not work, use the following code to import it:
require.resolve("@unbxd-ui/react-search-components/styles/searchbox.css");
require.resolve("@unbxd-ui/react-search-components/styles/autosuggest.css");
The SearchBox component must be used within the wrapper (in CSR, SSR and Custom Hooks approaches) to ensure that the component and the search functionality work properly.
Live Demo
1. Searchbox without autosuggest
2. Searchbox with autosuggest
Props
- The placeholder for the search input element.
- Default Value:
"Enter the search query.."
.
- Boolean value which indicates if the label for the search input element must be shown or not.
- Default Value:
false
.
- The text must be shown as the label for the search input element.
- Default Value:
""
.
- Boolean value which indicates if products for entered query must be fetched on pressing the "Enter" key.
- Default Value:
false
.
- Boolean value which indicates if the search button must be shown or not.
- Default Value:
true
.
- The text that must be shown in the submit query button.
- Default Value:
"Search"
.
- Boolean value which indicates if there must be a minimum delay between submitting the query and making the API call for the submitted query.
- Ensure that both
showSubmitButton
andsubmitOnEnter
are turned off for this functionality to work. delay
must be provided, otherwise a default delay of 0 will be applied.- Default Value:
false
.
- The time in milliseconds between submitting the new query and firing the API call for this query.
- Default Value:
0
.
- Turn this boolean to
true
if you want the api call to trigger even when you hit the same query. If this is turned tofalse
, then for the same query, multiple calls will not happen. - Default Value:
false
.
- Turn this boolean to
true
if you want to show a clear button on searchbox. This clear button on click, clears out the searchbox and throws an api call for "*" query. - Default Value:
false
.
- The component used to display the clear button, which clears the query in the searchbox.
- Default Value:
const ClearBtnComponent = () => {
return <>Clear</>;
};
- A function that will be called when the query in the searchbox changes.
- Default Value:
() => {}
.
- A function to handle the search box focus event.
- Default Value:
() => {}
.
- A function to handle the search box blur event.
- Default Value:
() => {}
.
- This prop will be used to style the component.
- The value must use a defined structure (the structure can be seen in the following example).
- The keys in the structure must be the same while the values can changed as per the user's choice.
styles={{
root: "searchbox-root", // used for the wrapper element
label: "searchbox-label", // used for the label
input: "searchbox-input", // used for the input element
clearButton: "search-clear-btn", // used for the clear button
submitButton: "searchbox-btn" // used for the submit button
}}
-
An object which contains the configuration for the autosuggest feature.
-
Following further configurations can be passed to the object:
-
- Enables autosuggest feature for the searchbox input.
- Default Value:
false
.
-
- It is the component which is passed by the user to render the autosuggest.
- Default Value:
import { useState, useEffect } from "react"; import { PopularProducts, KeywordSuggestions, TrendingQueries, TopQueries, PromotedSuggestions } from "@unbxd-ui/react-search-components"; const AutosuggestComponent = ({ autosuggest, response, hideAutosuggest, setQuery }) => { const { LoaderComponent, inFields: { noOfInfields, filterField, Component: InFields, HeaderComponent: InFieldsHeader }, popularProducts: { Component: PopularProducts = PopularProducts, HeaderComponent: PopularProductsHeader }, keywordSuggestions: { Component: KeywordSuggestions = KeywordSuggestions, HeaderComponent: KeywordSuggestionsHeader }, trendingSearches: { Component: TrendingQueries = TrendingQueries, HeaderComponent: TrendingQueriesHeader }, topQueries: { Component: TopQueries = TopQueries, HeaderComponent: TopQueriesHeader }, promotedSuggestions: { Component: PromotedSuggestions = PromotedSuggestions, HeaderComponent: PromotedSuggestionsHeader }, onItemClick, onItemHover } = autosuggest; const { loading, autosuggestQuery = "", setAutosuggestQuery, response: { trendingSearches, popularProducts, keywordSuggestions, inFields, topSearchSuggestions, promotedSuggestions }, fetchSearchData, searchResults, } = response; const [hoveredQuery, setHoveredQuery] = useState(autosuggestQuery); const [products, setProducts] = useState(popularProducts); const handleHover = (query, item) => { onItemHover(item); if (hoveredQuery !== query) { if (searchResults[query]) { setProducts(searchResults[query]); } else { fetchSearchData({ query }); } } setHoveredQuery(query); }; useEffect(() => { setHoveredQuery(autosuggestQuery) }, [autosuggestQuery]) useEffect(() => { if (hoveredQuery.length > 0) { setProducts(searchResults[hoveredQuery]?.length > 0 ? searchResults[hoveredQuery] : popularProducts); } else { setProducts(popularProducts); } }, [searchResults, hoveredQuery]); useEffect(() => { if (hoveredQuery === autosuggestQuery) { setProducts(popularProducts); } }, [popularProducts]); useEffect(() => { setHoveredQuery(autosuggestQuery) }, [autosuggestQuery]) if (loading) { return ( <div className="autosuggest-wrapper"> <LoaderComponent /> </div> ); } const handleAllProductsClick = () => { hideAutosuggest(); setQuery(autosuggestQuery); }; return ( <div className="autosuggest-wrapper"> {trendingSearches.length > 0 && (autosuggestQuery === "*" || autosuggestQuery === "") && ( <TrendingQueries headerText="Trending Queries:" trendingQueries={trendingSearches} hideAutosuggest={hideAutosuggest} setAutosuggestQuery={setAutosuggestQuery} HeaderComponent={TrendingQueriesHeader} onItemClick={onItemClick} /> )} {autosuggestQuery !== "*" && autosuggestQuery !== "" && ( <> <div className="inner-wrapper"> <div className="main-tpl"> {products.length > 0 && ( <PopularProducts headerText={`Popular Products:`} autosuggestQuery={hoveredQuery} products={products} hideAutosuggest={hideAutosuggest} HeaderComponent={PopularProductsHeader} onItemClick={onItemClick} /> )} </div> <div className="side-tpl"> {promotedSuggestions.length > 0 && ( <PromotedSuggestions headerText="Promoted Suggestions:" hoveredQuery={hoveredQuery} promotedSuggestions={promotedSuggestions} onHover={handleHover} hideAutosuggest={hideAutosuggest} setAutosuggestQuery={setAutosuggestQuery} HeaderComponent={PromotedSuggestionsHeader} onItemClick={onItemClick} onItemHover={onItemHover} /> )} {topSearchSuggestions.length > 0 && ( <TopQueries headerText="Top Search Suggestions:" topQueries={topSearchSuggestions} hideAutosuggest={hideAutosuggest} setAutosuggestQuery={setAutosuggestQuery} HeaderComponent={TopQueriesHeader} onItemClick={onItemClick} hoveredQuery={hoveredQuery} onHover={handleHover} /> )} {keywordSuggestions.length > 0 && ( <KeywordSuggestions headerText="Keyword Suggestions:" keywordSuggestions={keywordSuggestions} onHover={handleHover} hoveredQuery={hoveredQuery} hideAutosuggest={hideAutosuggest} setAutosuggestQuery={setAutosuggestQuery} HeaderComponent={KeywordSuggestionsHeader} onItemClick={onItemClick} /> )} {inFields.length > 0 && ( <InFields headerText="InField Suggestions:" inFields={inFields} filterField={filterField} onHover={handleHover} hoveredQuery={hoveredQuery} hideAutosuggest={hideAutosuggest} noOfInfields={noOfInfields} HeaderComponent={InFieldsHeader} onItemClick={onItemClick} /> )} </div> {(products.length == 0 && promotedSuggestions.length == 0 && topSearchSuggestions.length == 0 && keywordSuggestions.length == 0 && inFields.length == 0) ? <AutosuggestNoResult autosuggestQuery={hoveredQuery} /> : ""} </div> { !(products.length == 0 && promotedSuggestions.length == 0 && topSearchSuggestions.length == 0 && keywordSuggestions.length == 0 && inFields.length == 0) && (<div className="show-all-products" title={autosuggestQuery.replace(/>/g, " > ")} onMouseDown={handleAllProductsClick}> Show all products for <span className="query"> "<span className="query-text">{autosuggestQuery.replace(/>/g, " > ")}</span>"</span> </div>) } </> )} </div> ); }
-
- It is a React component provided by the user to render the UI when no results are returned for the query.
- Default Value:
const AutosuggestNoResult = ({ autosuggestQuery }) => { return <div className="no-results">No results found for "{autosuggestQuery}"</div>; };
-
- It is a React component provided by the user to render a loader while the suggestion box is in a loading state.
- Default Value:
const AutosuggestLoader = () => { return <div className="autosuggest-loader">Loading...</div>; };
-
- The function executed when a user interacts with an autosuggested product or suggestion by clicking.
- Default Value:
() => {}
.
-
- The function executed when a user hover over an autosuggested product or suggestion.
- Default Value:
() => {}
.
-
- It is the minimum number of characters required to trigger the API call.
- Default Value:
3
.
-
- It is an object used to include additional payload in the API request.
- Default Value:
{}
.
-
-
It is an object that contains additional configurations for trending searches.
-
Default Value:
trendingSearches = { enabled: true, count: 6, Component: TrendingQueries, HeaderComponent: ({ headerText }) => { return <>{headerText}</>; } }
-
Further Configs:
-
- A boolean that determines whether the trending search API call should be made.
- Default Value:
true
.
-
- The number of trending search suggestions to display.
- Default Value:
6
.
-
- This custom component serves as the Trending Searches block header, but only if the default Trending Searches component is being displayed.
- Default Value:
const HeaderComponent = ({ headerText }) => { return <>{headerText}</>; }
-
- A user-provided component for customizing the Trending Searches block.
- Default Value:
const TrendingSearches = ({ HeaderComponent, headerText, trendingQueries, hideAutosuggest, setAutosuggestQuery, onItemClick }) => { const { setQuery } = useQuery({ delay: 0, forceReload: false }); const onQueryClick = (item: { [key: string]: any }) => { const { autosuggest } = item; onItemClick && onItemClick(item); hideAutosuggest(); setQuery(autosuggest); setAutosuggestQuery(autosuggest); }; const renderQueries = (trendingQueries: { [key: string]: any }[]) => { return trendingQueries?.map((query: { [key: string]: any }) => { const { autosuggest } = query; return ( <div key={autosuggest} className="query" onMouseDown={() => { onQueryClick(query); }} > {autosuggest} </div> ); }); }; return ( <div className="trending-queries"> <div className="header"><HeaderComponent headerText={headerText} /></div> <div className="body">{renderQueries(trendingQueries)}</div> </div> ); }
-
-
-
-
It is an object that contains additional configurations for popular products suggestions.
-
Default Value:
popularProducts = { enabled: true, count: 3, fields: [], Component: PopularProducts, HeaderComponent: ({ headerText }) => { return <>{headerText}</>; } }
-
Further Configs:
-
- A boolean that determines whether the popular products must be fetched and displayed.
- Default Value:
true
.
-
- The number of popular products suggestions to display.
- Default Value:
3
.
-
It is an array that specifies the field names to be fetched for popular products.
-
Default Value:
[]
.
Note: For the popular products to be displayed, you need to pass the field: "doctype" in the fields array.
-
This custom component serves as the Popular products block header, but only if the default Popular products component is being displayed.
-
Default Value:
const HeaderComponent = ({ headerText }) => { return <>{headerText}</>; }
-
- A user-provided component for customizing the Popular products block.
- Default Value:
const PopularProducts = ({ headerText, autosuggestQuery, products, hideAutosuggest, HeaderComponent, onItemClick }) => { const { setQuery } = useQuery({ delay: 0 }); const handleAllProductsClick = () => { hideAutosuggest(); setQuery(autosuggestQuery); }; const handleItemClick = (product: { [key: string]: any }) => { onItemClick && onItemClick(product); hideAutosuggest(); }; const renderProducts = (products: any) => { return products?.map((product: { [key: string]: any }) => { let imageUrl = product.imageUrl; if (Array.isArray(product.imageUrl) && product.imageUrl.length > 0) { imageUrl = product.imageUrl[0] } return ( <div key={product.uniqueId} id={product.uniqueId} className="product" onMouseDown={() => handleItemClick(product)}> <div className="image-container"> <img src={imageUrl} alt={product.title} className="image" /> </div> <div className="details"> {product.title && ( <div className="title" title={product.title}> {product.title} </div> )} {product.price && <div className="price">${product.price}</div>} </div> </div> ); }); }; return ( <div className="popular-products"> <div className="header"><HeaderComponent headerText={headerText} /></div> <div className="body"> <div className="popular-products-grid">{renderProducts(products)}</div> </div> </div> ); }
-
-
-
-
It is an object that contains additional configurations for keyword suggestions.
-
Default Value:
keywordSuggestions = { enabled: true, count: 2, prefetch: false, Component: KeywordSuggestions, HeaderComponent: ({ headerText }) => { return <>{headerText}</>; } }
-
Further Configs:
-
- A boolean that determines whether the keyword suggestions must be fetched and displayed.
- Default Value:
true
.
-
- The number of keyword suggestions to display.
- Default Value:
2
.
-
- A boolean that determines whether the search call for keyword suggestions should be made while typing the query itself or no call at all should go.
- Default Value:
false
.
-
- This custom component serves as the Keyword suggestions block header, but only if the default keyword suggestions component is being displayed.
- Default Value:
const HeaderComponent = ({ headerText }) => { return <>{headerText}</>; }
-
- A user-provided component for customizing the Keyword suggestions block.
- Default Value:
const KeywordSuggestions = ({ headerText, hoveredQuery, keywordSuggestions, onHover, hideAutosuggest, setAutosuggestQuery, HeaderComponent, onItemClick }) => { const { query, setQuery } = useQuery({ delay: 0, forceReload: true }); const handleClick = (item: { [key: string]: any }) => { const { autosuggest } = item; onItemClick && onItemClick(item); hideAutosuggest(); if (query !== autosuggest) { setQuery(autosuggest); setAutosuggestQuery(autosuggest); } }; const handleHover = (item: { [key: string]: any }) => { const { autosuggest } = item; onHover(autosuggest, item); }; const renderKeywords = (keywordSuggestions: any) => { return keywordSuggestions.map((keyword: any) => { const { autosuggest }: any = keyword; return ( <div key={autosuggest} className={`keyword ${autosuggest === hoveredQuery && "selected"}`} onMouseEnter={() => { handleHover(keyword); }} onMouseDown={() => { handleClick(keyword); }} > {autosuggest} </div> ); }); }; return ( <div className="keyword-suggestions"> <div className="header"><HeaderComponent headerText={headerText} /></div> <div className="body">{renderKeywords(keywordSuggestions)}</div> </div> ); }
-
-
-
-
It is an object that contains additional configurations for top queries suggestions.
-
Default Value:
topQueries = { enabled: true, count: 2, prefetch: false, Component: TopQueries, HeaderComponent: ({ headerText }) => { return <>{headerText}</>; } }
-
Further Configs:
-
- A boolean that determines whether the top queries suggestions must be fetched and displayed.
- Default Value:
true
.
-
- The number of top queries suggestions to display.
- Default Value:
2
.
-
- A boolean that determines whether the search call for top queries suggestions should be made while typing the query itself or no call at all should go.
- Default Value:
false
.
-
- This custom component serves as the Top queries block header, but only if the default top queries component is being displayed.
- Default Value:
const HeaderComponent = ({ headerText }) => { return <>{headerText}</>; }
-
- A user-provided component for customizing the Top queries block.
- Default Value:
const TopQueries = ({ headerText, topQueries, hoveredQuery, onHover, hideAutosuggest, setAutosuggestQuery, HeaderComponent, onItemClick }) => { const { query, setQuery } = useQuery({ delay: 0, forceReload: true }); const handleClick = (item: { [key: string]: any }) => { const { autosuggest } = item; onItemClick && onItemClick(item); hideAutosuggest(); if (query !== autosuggest) { setQuery(autosuggest); setAutosuggestQuery(autosuggest); } }; const handleHover = (item: { [key: string]: any }) => { const { autosuggest } = item; onHover(autosuggest, item); }; const renderTopQueries = (topQueries: { [key: string]: any }[]) => { return topQueries?.map((query) => { const { autosuggest } = query; return <div key={autosuggest} className={`top-query ${autosuggest === hoveredQuery && "selected"} `} onMouseDown={() => handleClick(query)} onMouseEnter={() => handleHover(query)}> {autosuggest} </div> }); }; return ( <div className="top-queries"> <div className="header"><HeaderComponent headerText={headerText} /></div> <div className="body">{renderTopQueries(topQueries)}</div> </div> ); }
-
-
-
-
It is an object that contains additional configurations for inFields suggestions.
-
Default Value:
inFields = { enabled: true, count: 2, filterField: "category", noOfInfields: 2, prefetch: false, Component: InFields, HeaderComponent: ({ headerText }) => { return <>{headerText}</>; } }
-
Further Configs:
-
- A boolean that determines whether the inFields suggestions must be fetched and displayed.
- Default Value:
true
.
-
- The number of inFields suggestions to display.
- Default Value:
2
.
-
- A boolean that determines whether the search call for inFields suggestions should be made while typing the query itself or no call at all should go.
- Default Value:
false
.
-
- The number of infields for which the products need to be fetched and displayed.
- Default Value:
2
.
-
- The key in the API response from which we get the infield values.
- Default Value:
"category"
.
-
- This custom component serves as the Infields block header, but only if the default infields component is being displayed.
- Default Value:
const HeaderComponent = ({ headerText }) => { return <>{headerText}</>; }
-
- A user-provided component for customizing the Infields block.
- Default Value:
const InFields = ({ headerText, inFields, filterField, onHover, hoveredQuery, hideAutosuggest, noOfInfields, HeaderComponent, onItemClick }) => { const { setQuery } = useQuery({ forceReload: true }); const handleTitleClick = (item: { [key: string]: any }) => { const { clickedField } = item; onItemClick && onItemClick(item); hideAutosuggest(); setQuery(clickedField); }; const handleFieldClick = (item: { [key: string]: any }) => { const { clickedField } = item; onItemClick && onItemClick(item); hideAutosuggest(); const parentField = clickedField.split(">")[0]; setQuery(parentField); }; const handleItemHover = (item: { [key: string]: any }) => { const { hoveredField } = item; onHover(hoveredField, item); }; const renderFields = (inField: { [key: string]: any }) => { const inFields = inField[`${filterField}_in`]?.slice(0, noOfInfields) || []; return inFields?.map((field: string) => { return ( <div className={`field ${hoveredQuery === `${inField.autosuggest}>${field}` ? "selected" : ""}`} key={field} onMouseOver={() => { handleItemHover({ ...inField, hoveredField: `${inField.autosuggest}>${field}` }); }} onMouseDown={()=>{ handleFieldClick({...inField, clickedField: `${inField.autosuggest}>${field}`}); }} > in {field} </div> ); }); }; const renderInfieldsTitle = (inFields: { [key: string]: any }[]) => { return inFields?.map((inField: { [key: string]: any }, key: number) => { return ( <div className="infield" key={key}> <div className={`infield-title ${hoveredQuery === inField.autosuggest ? "selected" : ""}`} onMouseOver={() => { handleItemHover({ ...inField, hoveredField: inField.autosuggest }); }} onMouseDown={() => { handleTitleClick({...inField, clickedField: inField.autosuggest}); }}> {inField.autosuggest} </div> <div className="fields">{renderFields(inField)}</div> </div> ); }); }; return ( <div className="infields-wrapper"> <div className="header"><HeaderComponent headerText={headerText}/></div> <div className="body">{renderInfieldsTitle(inFields)}</div> </div> ); }
-
-
-
-
It is an object that contains additional configurations for promoted suggestions.
-
Default Value:
promotedSuggestions = { enabled: true, count: 3, prefetch: false, Component: PromotedSuggestions, HeaderComponent: ({ headerText }) => { return <>{headerText}</>; } }
-
Further Configs:
-
- A boolean that determines whether the promoted suggestions must be fetched and displayed.
- Default Value:
true
.
-
- The number of promoted suggestions to display.
- Default Value:
3
.
-
- A boolean that determines whether the search call for promoted suggestions should be made while typing the query itself or no call at all should go.
- Default Value:
false
.
-
- This custom component serves as the Promoted suggestions block header, but only if the default promoted suggestions component is being displayed.
- Default Value:
const HeaderComponent = ({ headerText }) => { return <>{headerText}</>; }
-
- A user-provided component for customizing the Promoted suggestions block.
- Default Value:
const PromotedSuggestions = ({ headerText, hoveredQuery, promotedSuggestions, onHover, hideAutosuggest, setAutosuggestQuery, HeaderComponent, onItemClick }) => { const { query, setQuery } = useQuery({ delay: 0, forceReload: true }); const handleClick = (suggestion: { [key: string]: any }) => { const { autosuggest } = suggestion; hideAutosuggest(); onItemClick && onItemClick(suggestion); if (query !== autosuggest) { setQuery(autosuggest); setAutosuggestQuery(autosuggest); } }; const handleHover = (suggestion: { [key: string]: any }) => { const { autosuggest } = suggestion; onHover(autosuggest, suggestion); }; const renderProducts = ()=>{ return promotedSuggestions?.length > 0 && promotedSuggestions.map((suggestion:any)=>{ const { autosuggest }: any = suggestion; return <div key={autosuggest} className={`promoted-suggestion ${autosuggest === hoveredQuery && "selected"}`} onMouseOver={() => { handleHover(suggestion); }} onMouseDown={() => { handleClick(suggestion); }} > {autosuggest} </div> }) } return <div className="promoted-suggestions"> <div className="header"><HeaderComponent headerText={headerText} /></div> <div className="body">{renderProducts()}</div> </div> }
-
-
-
Related Hooks
To use the Unbxd React Search SDK without the pre-built SearchBox component, add the search functionality to your custom component using the useQuery hook and add the autosuggest functionality using the useAutosuggest hook. Refer to the documentation for more details.