Skip to Content

SearchField

Free-text search with a clear button. For selecting from a constrained list, use ComboBox.

Usage

Use SearchField for free-text queries (filtering a results list, searching across multiple sources). Use ComboBox when search results come from a known, constrained list.

import { SearchField } from "@opengovsg/oui"
<SearchField aria-label="Search" />

Alternatively, install the component as local source via the shadcn CLI:

pnpm dlx shadcn@latest add https://oui.open.gov.sg/r/search-field.json

The SearchField component provides an accessible search input with a built-in search icon and clear button. The clear button automatically appears when the field has a value and hides when empty.

If the component does not have a visible label (by passing a label prop), an aria-label or aria-labelledby prop must be passed instead to identify it to assistive technology.

Examples

With Label and Description

Provide clear instructions to users with labels and descriptions.

Enter a keyword to search for documents.

With Error Message

Combine isInvalid and errorMessage props to show validation errors.

Please enter a valid search query.

Disabled

Use the isDisabled prop to disable the search field.

Sizes

Use the size prop to change the size of the field. Defaults to "md".

With Placeholder

Use the inputProps prop to pass additional props to the underlying input element, such as a placeholder.

Custom Search Icon

Use the searchIcon prop to replace the default search icon with a custom one.

Hidden Search Icon

Set the searchIcon prop to null to hide the icon entirely.

Custom Clear Icon

Use the clearIcon prop to replace the default clear (X) icon. This is useful for showing a loading spinner during async search operations.

With Action Element

Use the actionElement prop to render an element beside the input group, such as a search button or filter button.

Controlled

Use the value and onChange props to control the input value. The onSubmit callback is invoked when the user presses Enter.

Input value:

Submitted value:

Validation

See the Forms guide for end-to-end patterns including React Hook Form + Zod.

SearchField supports React Aria's form validation system:

  • Built-in constraints: Use isRequired, minLength, maxLength, or pattern for native HTML validation. Errors display after the user commits a value or submits the form.
  • Custom validation: Use the validate prop to provide a function that returns an error message string, or null/true if valid.
  • Realtime validation: Use the isInvalid prop with errorMessage for immediate feedback as the user types.
  • Validation behavior: The validationBehavior prop controls enforcement — "native" (default) prevents form submission when invalid, while "aria" only marks the field via ARIA attributes and allows submission.

Events

SearchField supports the following event handlers, inherited from React Aria's SearchField:

  • onChange — Called when the value changes, receiving the new string value.
  • onSubmit — Called when the user presses Enter, receiving the current value.
  • onClear — Called when the user clears the field (by pressing the clear button or Escape).
  • onFocus / onBlur — Called when the input gains or loses focus.
  • onFocusChange — Called when the focus state changes, receiving a boolean.
  • onKeyDown / onKeyUp — Called on keyboard events.

Accessibility

  • Built on a native <input type="search"> element for full browser and assistive technology support.
  • Label, description, and error message are linked to the input via aria-labelledby and aria-describedby.
  • If no visible label is provided, an aria-label or aria-labelledby prop must be set.
  • The clear button is keyboard-accessible; pressing Escape while the field has a value clears it.
  • Required and invalid states are exposed to assistive technology.

Slots

Slots are named regions of the component you can target with custom Tailwind classes via the classNames prop. Each slot below corresponds to a key on the classNames object.

  • base: The root container wrapping the entire field (label, input group, description, error).
  • label: The label element rendered above the input.
  • fieldWrapper: The flex wrapper containing the input group and the optional action element.
  • group: The bordered input group containing the search icon, input, and clear button.
  • searchIcon: The leading search icon.
  • input: The native <input type="search"> element.
  • clearButton: The trailing clear button.
  • description: The description text rendered below the input.
  • error: The error message text rendered below the input.

Props

SearchField

PropTypeDefaultDescription
labelReactNode-The visible label for the field
descriptionReactNode-Description text rendered below the input
errorMessageReactNode | ((v: ValidationResult) => ReactNode)-The error to display when invalid; accepts a render prop for custom error messages
valuestring-The current value (controlled)
defaultValuestring-The default value (uncontrolled)
onChange(value: string) => void-Called when the value changes
onSubmit(value: string) => void-Called when the user presses Enter
onClear() => void-Called when the user clears the field
isDisabledbooleanfalseWhether the field is disabled
isReadOnlybooleanfalseWhether the field is read-only
isRequiredbooleanfalseWhether the field is required
isInvalidbooleanfalseWhether the field should display as invalid
validate(value: string) => ValidationError | true | null | undefined-Custom validation function
validationBehavior"native" | "aria""native"Native HTML validation vs ARIA-only
size"xs" | "sm" | "md""md"The size of the field
variant"outline" | "unstyled""outline"The visual variant of the input
actionElementReactNode-An element rendered beside the input group (e.g., a search button)
searchIconReactNode | null<SearchIcon />Custom leading icon, or null to hide
clearIconReactNode<XIcon />Custom clear-button icon (e.g., a spinner during async search)
inputPropsPartial<InputProps>-Additional props forwarded to the underlying <input> (e.g., placeholder)
classNamesSlotsToClasses<SearchFieldSlots>-Per-slot Tailwind classes for custom styling

Inherits all remaining props from React Aria's SearchField. Notable ones: autoFocus, excludeFromTabOrder, name, autoComplete.