Skip to content

ComponentsForms

Search Field

A text input for search queries, with a search icon, a clear button, Escape to clear and an optional keyboard shortcut hint. Works for live filtering, submit-on-Enter, async search and native search forms.

React AriaSource

Installation

pnpm dlx shadcn@latest add @desyne/search-field

The CLI installs dependencies and any other components this one uses.

Usage

tsx
import { SearchField } from "@/components/ui/search-field";
tsx
<SearchField aria-label="Search" onSubmit={(query) => search(query)} />

Use value and onChange to filter as the user types, or onSubmit to run the search when they press Enter. The clear button and Esc reset the value and call onClear.

onSubmit replaces form submission

When onSubmit is set, Enter calls it and does not submit a surrounding <form>. Leave onSubmit off (and give the field a name) when you want Enter to submit the form natively.

When to use

  • Search Field — a query that filters or searches content elsewhere on the page or site.
  • Combo Box — the result is picking one option from a list shown under the input.
  • Command Palette — a global, keyboard-first launcher for navigation and actions.
  • Text Field — ordinary text entry that isn't a query.

Anatomy

tsx
<SearchField>          {/* root: <div>, owns the query and state attributes */}
  <Label />            {/* from `label` */}
  <FieldGroup>         {/* the visible box */}
    <SearchIcon />     {/* decorative */}
    <FieldInput />     {/* <input type="search"> */}
    <Keyboard />       {/* from `shortcut`, only while empty */}
    <Button />         {/* clear button, only while not empty */}
  </FieldGroup>
  <Description />      {/* from `description` */}
  <FieldError />       {/* shown only while invalid */}
</SearchField>
PartRendersNotes
SearchField<div>Root. Carries data-slot="search-field", the group/field class and data-empty while the query is empty.
Label<label>Rendered when label is set.
FieldGroup<div>The visible box, styled by fieldVariants.
Search icon<svg>Decorative (aria-hidden).
FieldInput<input type="search">The native input. The browser's own cancel button is hidden in favour of the clear button.
Shortcut<kbd>Rendered when shortcut is set, visible only while the field is empty. It's a hint; you bind the key.
Clear button<button>Labelled "Clear search", skipped in the tab order, hidden while empty. React Aria wires it through context, so don't place other React Aria buttons inside the field.
Description<span slot="description">Rendered when description is set.
FieldError<span slot="errorMessage">Rendered only while invalid.

Examples

Variants

outline (default), filled for toolbars, headers and tinted surfaces, and underlined for minimal layouts.

Sizes

sm (28px) suits toolbars and table headers, md (32px) is the default, lg (40px) suits hero and landing-page search.

With label and description

Most search fields rely on aria-label, but a visible label helps in forms and filter panels. The default placeholder is "Search…".

Press Escape or the × button to clear.

Keyboard shortcut

shortcut shows a hint while the field is empty. Binding the key is up to you: listen on window and focus the input. The root doesn't expose the input, so reach it through a wrapper ref.

Press ⌘K (or Ctrl K) anywhere on the page to focus the field.

Submit and clear

onSubmit runs on Enter with the current query, and onClear runs when the clear button or Esc empties the field. Set enterKeyHint="search" to label the enter key on mobile keyboards.

  • Type a query and press Enter.

Live filtering

Control the value with value and onChange to filter a list as the user types. React Aria's useFilter gives you locale-aware contains, startsWith and endsWith matchers that ignore case and accents with sensitivity: "base". Announce the result count with an aria-live region.

17 of 17 components

  • Button
  • Calendar
  • Checkbox
  • Combo Box
  • Date Picker
  • Dialog
  • Menu
  • Number Field
  • Popover
  • Radio Group
  • Search Field
  • Select
  • Slider
  • Switch
  • Tabs
  • Text Field
  • Tooltip

Fetch results in an effect keyed on the query and abort stale requests, so fast typing never shows out-of-order results. Show a Spinner while loading and an empty state when nothing matches.

    Disabled and read only

    isDisabled dims the field and disables the clear button. isReadOnly keeps a saved query visible and selectable, and also disables clearing.

    Search is unavailable while logs are being indexed.

    Search form

    Without onSubmit, Enter submits the surrounding form natively and the query is sent under its name, like a classic ?q= search. isRequired and minLength use native validation. Give the form role="search" so it's exposed as a search landmark.

    Recipes

    App header

    A small filled search in a top bar, focused with / from anywhere on the page, next to icon actions.

    NT

    Filterable member list

    A search in a card header filtering a list by name and email, with an empty state that clears the query.

    • OM

      Olivia Martin

      olivia@acme.dev

      Owner
    • JL

      Jackson Lee

      jackson@acme.dev

      Admin
    • IN

      Isabella Nguyen

      bella@acme.dev

      Member
    • WK

      William Kim

      will@acme.dev

      Member
    • SD

      Sofia Davis

      sofia@acme.dev

      Viewer

    Accessibility

    • The input has type="search", so assistive technology announces it as a search field.
    • Always provide a label: label, aria-label, or aria-labelledby. The search icon is decorative.
    • The clear button is labelled "Clear search" (localized). It's skipped in the tab order because Esc does the same thing, and pressing it keeps focus in the input so the mobile keyboard stays open.
    • The shortcut hint is visual only. If you bind a global shortcut, avoid keys users type into other inputs; the header recipe ignores / while an input is focused.
    • Wrap search areas in role="search" (on a <form> or a <div>) to create a search landmark.
    • For live results, announce counts or "no results" with an aria-live="polite" region.

    Keyboard

    KeyAction
    EnterCalls onSubmit, or submits the surrounding form when there's no onSubmit
    EscClears the field and calls onClear. When already empty, the key passes through, for example to close a dialog

    Styling

    Data attributes

    On the SearchField root. Children can react with group-data-*/field: variants; the component itself uses group-data-empty/field: to swap the shortcut hint and the clear button.

    AttributePresent when
    data-emptyThe query is empty
    data-disabledisDisabled is true
    data-readonlyisReadOnly is true
    data-requiredisRequired is true
    data-invalidValidation failed, or isInvalid is true

    On the FieldGroup: data-hovered, data-focus-within, data-focus-visible, data-invalid and data-disabled.

    Slots

    data-slotElement
    search-fieldRoot
    label, description, field-errorField text
    field-groupVisible box
    field-input<input>

    The box comes from fieldVariants in field.tsx; see Text Field. className also accepts a function of the render state (isEmpty, isDisabled, isInvalid, isReadOnly, isRequired, state).

    API Reference

    SearchField

    Prop

    Type

    Also accepts every prop of React Aria's SearchField.

    • Combo Box — search that ends in choosing an option.
    • Command Palette — a global search and command launcher.
    • Text Field — the shared field building blocks.
    • Kbd — for showing shortcuts elsewhere.