Skip to content

Components · Search and discovery

SearchInput

Search box with icon, clear button, debounce, pending state and shortcut hint.

@rookcom/monarch-reactComponent

Debounced, pending

8 results

Usage examples

Shortcut, sizes and Field

Purpose

A single-line search box for filtering a list or querying a server. It adds the parts every search field re-implements: a leading icon, a clear button, a debounced search callback, a pending state while results load and an optional keyboard shortcut.

Use when

  • Filtering a table, list or grid as the user types.
  • Querying a server, where debounce keeps requests to one per pause.
  • A page-level search reached with a shortcut such as "/" or ⌘K.

Avoid when

  • The user picks one value from a list: use Combobox.
  • Free text that is not a query (a name, a title): use Input.
  • A command palette with grouped actions and results: use a command menu.

Design principles

  • One callback per concern: onValueChange for every keystroke, onSearch for when to run the query.
  • Clearing is always one step: the clear button or Escape, and both return focus to the field.
  • Pending replaces the magnifier with a spinner in the same place, so the layout never shifts.
  • The shortcut hint is decorative; shortcutKeys is what binds the key and announces it.

API reference

import { SearchInput } from '@rookcom/monarch-react';
ExportKindRenderingRoot class
SearchInputcomponentclient.mn-search-input

Renders a .mn-search-input wrapper (styled as .mn-input) around a native <input type="search">. The ref and all native input props go to the input; className goes to the wrapper.

Reads Field context through useFieldControl, like Input.

Generated from the TypeScript declarations of packages/react/src/components/search/search-input.

Properties

onChange still receives the native change event; onValueChange receives the string.

SearchInput

A search box: leading icon, clear button, optional debounce for fetching, a pending state, and an optional keyboard shortcut that focuses it. Renders a native `type="search"` input, so give it a visible label (Field) or an `aria-label`.

PropTypeDescription
childrenReactNode
classNamestringClass for the outer wrapper (the input itself is `.mn-search-input__input`).
clearablebooleanShow a clear button while there is text. Default true.
clearLabelstringAccessible name of the clear button. Default "Clear search".
debouncenumberMilliseconds to wait after the last keystroke before calling `onSearch`. Default 0 (no wait).
defaultValuestringInitial query text when uncontrolled.
disabledboolean
iconReactNodeReplaces the leading magnifier icon. Decorative. Pass `null` for none.
idstring
invalidbooleanMarks the value invalid. Inside a Field, the Field's `invalid` is used.
onClear(() => void)Called after the field is cleared by the button or Escape.
onSearch((query: string) => void)Called with the query to run: after `debounce` ms of no typing, at once on Enter, and with `''` when the field is cleared. Use this for fetching.
onValueChange((value: string) => void)Called on every keystroke and on clear, with the new text.
pendingbooleanA search is in flight: the leading icon becomes a spinner and the input is `aria-busy`.
shortcutReactNodeHint shown at the trailing edge while the field is empty, e.g. "/" or "⌘K". Decorative.
shortcutKeysstringThe key combination that focuses the field from anywhere on the page, in `aria-keyshortcuts` syntax ("/", "Meta+K", "Control+K"). Setting it binds the listener and sets `aria-keyshortcuts`; single keys are ignored while typing in another field.
size"sm" | "md" | "lg"
valuestringThe query text (controlled).

Variants

PropValuesDescription
size'sm''md''lg'Control height from --mn-control-*, as for Input. Default md.

States

StateExposed asBehaviour
Pendingdata-pending on the wrapper, aria-busy="true" on the inputThe leading icon becomes a spinner while a search is in flight.
Has text–The clear button appears; the shortcut hint hides.
Invaliddata-invalid on the wrapper, aria-invalid="true" on the inputDanger border, from invalid or the surrounding Field.
Disableddata-disabled on the wrapper, disabled on the inputMuted surface; no clear button.
Focus–The whole wrapper shows the Monarch focus ring while the input has focus.

Interaction behaviour

  • Typing calls onValueChange at once and onSearch after debounce ms without typing (at once when debounce is 0).
  • Enter calls onSearch immediately and cancels the waiting debounce.
  • Clearing calls onValueChange(""), onSearch("") and onClear, and keeps focus in the field.
  • With shortcutKeys, pressing the combination anywhere focuses the field and selects its text. Single-key shortcuts such as "/" are ignored while another field has focus.
  • Controlled with value + onValueChange, or uncontrolled with defaultValue.

Keyboard support

KeysAction
EnterRuns the search now.
EscapeClears the text and stops the event. On an empty field Escape is not handled and bubbles. Inside a Monarch Dialog or Popover, the overlay sees Escape first (Radix listens in the capture phase) and closes.
TabMoves to the clear button while there is text, then onward.
`shortcutKeys`Focuses the field from anywhere on the page.

Accessibility

Role
searchbox (native input type="search")
Accessible name
A FieldLabel, or aria-label when the context makes the purpose clear ("Search documents"). The placeholder is not a label.
  • The clear button is a real button named by clearLabel (default "Clear search").
  • Icons, the spinner and the shortcut hint are aria-hidden; aria-keyshortcuts announces the shortcut instead.
  • aria-busy is set while pending. Announce the result count yourself in a polite live region, as in the example.
  • Wrap a page-level search in <search> or role="search" yourself; the component does not add a landmark, because filters inside cards should not create one.

Responsive behaviour

  • Fills its container; the icon, clear button and hint keep their size and the text field shrinks.
  • enterkeyhint="search" shows a Search key on mobile keyboards.

Theme support

  • Colours, border and focus ring are Monarch semantic tokens, so light, dark and more-contrast themes apply automatically.
  • The native WebKit cancel button is hidden so only the Monarch clear button shows.
  • The clear button hover transition is removed under prefers-reduced-motion.

Do and don't

Do

  • Use debounce (250–400 ms) when each search hits a server.
  • Show pending from the moment the user types until results arrive.
  • Announce the number of results in a polite live region.

Don't

  • Do not rely on the placeholder as the only label.
  • Do not bind a single-key shortcut on pages where the user mostly types; prefer a modifier combination.
  • Do not fetch in onValueChange when onSearch with debounce does it once per pause.
  • Input: Plain Input for text that is not a query.
  • Combobox: Pick one value from a filtered list.
  • FilterBar: A row of filters that usually starts with a SearchInput.
  • Kbd: The shortcut hint is a Kbd.

Dependencies

KindDepends on
npm packagesreact
Monarch componentsField, Spinner, Kbd

Uses the .mn-input styles from text-field for the wrapper.

Testing coverage

  • Renders a labelled native searchbox.
  • Debounces onSearch while reporting every keystroke through onValueChange.
  • Enter searches at once and cancels the waiting debounce; no debounce searches on every change.
  • The clear button clears, calls onSearch("") and onClear, and keeps focus.
  • Escape clears; a second Escape on an empty field reaches the page.
  • Controlled mode.
  • Pending sets aria-busy and shows the spinner.
  • Single-key and modifier shortcuts focus the field; single keys are ignored while typing elsewhere.
  • Reads Field label, error and disabled state; no clear button when disabled.
CheckCovered
Axe in jsdomYes
Server renderingYes
Browser suitesVisual baselines: /__gallery; Cross-browser axe: /components/search-input

Tests: packages/react/src/components/search/search-input