HeroSearch
ImplementedHomepage hero search — GET form (what + where) with a submit button; stacks vertically on mobile. An optional third « Quand » segment (ADR-057) renders when whenPlaceholder is supplied. Either field can be turned into a DS combobox with the optional onSearch (What) / onLocationSearch (Where, ADR-074) / onSelectSuggestion / suggestionLabels API; the outer GET form always stays the no-JS fallback.
patterns/molecules/herosearch.htmlTwo-segment GET-form search bar (what + where) with a submit button, for hero sections. Pill-shaped and inline on ≥ sm breakpoints, stacks vertically on mobile.
HeroSearch
Commerce — Family 7
Server-renderable uncontrolled GET form — no client JS required. Enter submits, and the browser navigates to `action` with both terms as query params.
This component supports light and dark mode.
Usage
Uncontrolled GET form — no state, no client JS. The submitted term arrives as ?<searchInputName>=… on the action route.
import { HeroSearch } from '@epasslive/design-system'
// /events reads the `q` param — pass searchInputName="q" so the term is not dropped
<HeroSearch
searchPlaceholder={t('hero.searchEventsPlaceholder')}
locationPlaceholder={t('hero.searchLocationPlaceholder')}
submitButtonLabel={t('hero.searchButton')}
action="/events"
searchInputName="q"
/>Props
searchPlaceholder*stringPlaceholder and accessible name for the search ("what") input.
locationPlaceholder*stringPlaceholder and accessible name for the location ("where") input.
submitButtonLabel*stringVisible text of the submit button.
actionstring'/events'GET form action URL — the results route the form navigates to.
searchInputNamestring'search'Query param name for the search term. Must match the param the target route reads — see Usage.
locationInputNamestring'location'Query param name for the location term.
classNamestringAdditional CSS classes appended to the form element.
idstringid attribute on the form element.
Props
HeroSearch
searchPlaceholderstring—Placeholder (and accessible name) of the query segment.
locationPlaceholderstring—Placeholder (and accessible name) of the location segment.
submitButtonLabelstring—Visible text of the submit button.
actionstring'/events'GET form action URL the hero submits to.
searchInputNamestring'search'Query-param name of the query input — must match the target route's expected param.
locationInputNamestring'location'Query-param name of the location input.
classNamestring—Additional CSS classes on the form.
idstring—Stable root id.
whenPlaceholderstring—ADR-057 (HV2 / R4). Optional third segment « Quand ». Rendered only when supplied, so the historical two-field form is unchanged; its value posts into whenInputName.
whenInputNamestring'when'Query-param name of the optional date segment (the /events when filter contract: ISO date, ISO range from..to, or today|weekend|month).
whenSlotReactNode—ADR-068 amendment (2026-11-04). Replaces the built-in When input with consumer-owned content (the hero datepicker) while the labeled cell structure stays; the slot's control should carry id hero-${whenInputName} so the label binds. whenPlaceholder still renders the historical input when the slot is absent.
searchLabelstring—Visible 13px label for the What field (plan §5 flat typography); renders a real <label> bound to the input and becomes the accessible name.
locationLabelstring—Visible 13px label for the Where field; renders a real <label> bound to the input and becomes the accessible name.
whenLabelstring—Visible 13px label for the third field; renders a real <label> bound to the input and becomes the accessible name.
variant'default' | 'flat''default'ADR-057 (HV2 / R4). 'flat' removes the card surface and the resting shadow, uses square edges and 56px typographic rows with a 1px underline (editorial homepage). Additive: unknown values fall back to 'default'; tap targets and focus rings are identical in both.
onSearch(query: string) => Promise<SearchInputGroup[]>—Turns the What field into the DS SearchInput combobox (renderForm={false} mode). The outer GET form stays the no-JS fallback and still submits the query param.
onLocationSearch(query: string) => Promise<SearchInputGroup[]>—ADR-074. Turns the Where field into the same DS SearchInput combobox (chromeless, renderForm={false}, map icon, 250ms debounce, minChars 2, shared suggestionLabels), mirroring the What field. No onSelect is wired: picking a suggestion only fills the Where input, it never navigates.
onSelectSuggestion(value: string, option: SearchInputOption) => void—Called with the picked suggestion; the consumer navigates (event href or the query param).
suggestionLabels{ shortQuery?: string; loading?: string; noResults?: string }EnglishCombobox status copy (short-query hint, loading copy, no-results copy). Omitted keys fall back to the DS English defaults.
<HeroSearch />Accessibility
Type
1 ruleARIA
1 ruleUsage
Import
import { HeroSearch } from "@epasslive/design-system"Example 1
<HeroSearch searchPlaceholder={t("searchEventsPlaceholder")} locationPlaceholder={t("searchLocationPlaceholder")} submitButtonLabel={t("searchButton")} action="/events" searchInputName="q" />Example 2
<HeroSearch searchPlaceholder="Search events" locationPlaceholder="Montreal" submitButtonLabel="Search" />Anti-patterns
— Do not hardcode data in molecules
— Avoid complex business logic in molecules