Skip to main content

SearchBar

MD3 search bar: a 56dp docked field that, given results as children, opens a docked search view with suggestions under the bar.

Basic​

Without children the component is a plain search field. onSearch fires on Enter (not while an IME composition is being committed).

<SearchBar aria-label="Search" placeholder="Search messages" onSearch={(query) => runSearch(query)} />

Search view with results​

Pass results as children — typically a List of clickable ListItems. The view opens on focus (or ArrowDown) and closes on Escape, an outside click, or a scrim click. It renders in the top layer, pinned under the bar, so ancestors' overflow can't clip it.

const [query, setQuery] = useState('')
const [open, setOpen] = useState(false)

<SearchBar
aria-label="Search fruit"
value={query}
onChange={(event, next) => setQuery(next)}
open={open}
onOpenChange={setOpen}
>
<List>
{matches.map((fruit) => (
<ListItem key={fruit} headline={fruit} onClick={() => { setQuery(fruit); setOpen(false) }} />
))}
</List>
</SearchBar>

The open state follows the usual pattern: open + onOpenChange for controlled, defaultOpen for uncontrolled. Likewise the query: value + onChange(event, value), or defaultValue.

Leading and trailing slots​

startIcon replaces the default search glyph and endIcon adds a trailing control. Both are 48dp slots, so an IconButton (back, menu, voice search, clear…) fits and stays in the tab order. Mark a purely decorative custom icon aria-hidden yourself.

<SearchBar
aria-label="Search"
startIcon={<IconButton variant="standard" aria-label="Back" icon={<ArrowBack />} />}
endIcon={<IconButton variant="standard" aria-label="Voice search" icon={<Mic />} />}
/>

Disabled​

The native input​

ref and extra props land on the root (role="search" landmark). Use inputRef for the native <input>, and inputProps for attributes without a dedicated prop — the component's own wiring wins on conflicts.

<SearchBar inputRef={inputRef} inputProps={{ 'aria-label': 'Search docs', maxLength: 80 }} />

Accessibility​

  • The root is a role="search" landmark. With results the input becomes an APG combobox (aria-expanded, aria-controls, aria-autocomplete="list"); otherwise it is a native search input.
  • Keyboard: ArrowDown opens the view and moves into the results; ArrowUp / ArrowDown / Home / End move between result items (ArrowUp from the first returns to the input); Escape closes the view and returns focus to the input; Enter calls onSearch. Moving focus out closes the view.
  • Opening the view is announced through a polite live region with suggestionsLabel (default 'Suggestions below') — localize it with the rest of your strings.
  • A consumer onKeyDown that calls preventDefault() opts out of the built-in handling for that key.

Props​

PropTypeDefaultDescription
childrenReactNode—Suggestion / result content shown in the open search view.
defaultOpenbooleanfalseUncontrolled initial open state.
defaultValuestring—Uncontrolled initial value.
disabledbooleanfalseDisables the input and applies disabled styling.
endIconReactNode—Trailing icon / control (48dp slot, e.g. a mic or clear `IconButton`).
inputPropsInputHTMLAttributes<HTMLInputElement>—Extra attributes spread on the native `<input>` — the escape hatch for attributes without a dedicated prop (e.g. a distinct `aria-label` for the searchbox, `maxLength`, `pattern`, extra `aria-*`, …). Precedence: the component's own wiring always wins over conflicting `inputProps` keys — the controlled `value` / `onChange` and internal `onFocus` / `onKeyDown` handling, `type="search"`, `className`, and every dedicated input prop the component sets (`placeholder`, `name`, `disabled`, …).
inputRefRef<HTMLInputElement>—Ref to the native `<input>` element (the forwarded `ref` points at the root).
namestring—Native input `name`.
onBlurFocusEventHandler<HTMLInputElement>—Blur handler for the native input.
onChange((event: ChangeEvent<HTMLInputElement, Element>, value: string) => void)—Fires with the native event and the new query.
onFocusFocusEventHandler<HTMLInputElement>—Focus handler for the native input.
onKeyDownKeyboardEventHandler<HTMLInputElement>—Key handler for the native input.
onOpenChange((open: boolean) => void)—Notified when the open state should change.
onSearch((value: string) => void)—Fires when the user submits (Enter).
openboolean—Controlled open (search-view) state.
placeholderstringSearchNative input `placeholder`.
startIconReactNode—Leading content (defaults to a decorative search glyph). Rendered in a 48dp slot, so it may be a navigation `IconButton` (back / menu) — it stays in the tab order and the accessibility tree. A purely decorative custom icon should carry `aria-hidden` itself.
suggestionsLabelstringSuggestions belowText announced (polite live region) when the search view opens — the equivalent of Compose's "Suggestions below" state description. Localize it with the rest of your UI strings.
valuestring—Controlled query value.