Skip to content

HeaderSearch

The header search: a form in a <search> landmark whose field suggests terms, categories and products, and recent and popular searches while it is empty. The form submits to action before hydration as well. Submitting opens a product instead when the suggestions for that exact query hold only that product, or one with that sku. Options are links, so client-side routing needs React Aria's RouterProvider.

import { HeaderSearch } from "@evolve-storefront/layout/header-search";

Preview

DefaultOpen in Storybook ↗

Usage

Terms, categories and products for what is typed, with a row for all results.

<HeaderSearch
action="/search"
loadSuggestions={(query, { signal }) => fetchSuggestions(query, { signal })}
popularSearches={popular}
onSearch={(query) => router.push(`/search?q=${encodeURIComponent(query)}`)}
/>

Props

PropTypeDescription
actionstring

The results page, which the form submits to without JavaScript too.

query?string
defaultQuery?string
onQueryChange?((query: string) => void)
suggestions?SearchSuggestions

Suggestions for the current query, when the caller fetches them itself.

isPending?boolean

Set with suggestions while the caller fetches; emitted as data-pending.

loadSuggestions?LoadSearchSuggestions

Fetches suggestions for a query, debounced; aborted when the query moves on.

popularSearches?string[]

Shown with the recent searches while the field is empty.

onSearch?((query: string) => void)

Called with the query on submit, for client-side navigation; without it the form submits.

minQueryLength?number

Below this length the panel asks for more instead of suggesting.

debounceMs?number
storageKey?string

The localStorage key for recent searches; two sites on one domain each pass their own.

hasSlashShortcut?boolean

"/" outside a text field focuses the search.

Any other props go to the root element, like on a plain HTML element.

Examples

Empty FieldAn empty field offers the recent searches, then the popular ones.
<HeaderSearch action="/search" popularSearches={["schroeven", "werkhandschoenen"]} />
Open in Storybook ↗
Submit With EnterEnter with nothing highlighted searches for what was typed.
<HeaderSearch action="/search" onSearch={(query) => router.push(`/search?q=${encodeURIComponent(query)}`)} />
Open in Storybook ↗
Caller FetchesThe caller fetches: suggestions for the current query, isPending while it waits.
const [query, setQuery] = useState("");
const { data, isPending } = useSuggestionsQuery(query);
<HeaderSearch action="/search" query={query} onQueryChange={setQuery} suggestions={data} isPending={isPending} />;
Open in Storybook ↗
With Default QueryA query from the page, such as the results page's own, fills the field.
<HeaderSearch action="/search" defaultQuery={searchParams.q} />
Open in Storybook ↗