Skip to content

Fields

Search Field

A labelled search box with an optional erase button.

When to use it: Use it for a query that filters or finds things.

On this page

Example

Loading example…
Search Field.tsxtsx
import { useState } from "react";
import { Label, SearchField, SearchFieldClear, SearchFieldInput } from "@comp0/react";
import { MagnifyingGlassIcon, XMarkIcon } from "@heroicons/react/16/solid";

export function Example() {
  const [submitted, setSubmitted] = useState("");

  return (
    <SearchField as="div" className="flex max-w-xs flex-col gap-2" onSubmit={setSubmitted}>
      <Label className="text-base font-medium text-zinc-900 sm:text-sm dark:text-zinc-100">
        Search
      </Label>
      <div className="relative">
        <MagnifyingGlassIcon
          className="pointer-events-none absolute top-1/2 left-3 size-4 -translate-y-1/2 text-zinc-400"
          aria-hidden="true"
        />
        <SearchFieldInput
          className="w-full rounded border border-zinc-950/10 bg-white py-2.5 pr-11 pl-9 text-base text-zinc-950 outline-teal-600 focus-visible:outline-2 sm:py-2 sm:text-sm dark:border-white/10 dark:bg-zinc-900 dark:text-zinc-50 dark:outline-teal-400 [&::-webkit-search-cancel-button]:hidden"
          name="query"
          placeholder="Press Enter"
        />
        <SearchFieldClear
          aria-label="Clear search"
          className="absolute top-1/2 right-1 flex size-8 -translate-y-1/2 items-center justify-center rounded text-zinc-500 outline-teal-600 hover:bg-zinc-100 hover:text-zinc-800 focus-visible:outline-2 dark:text-zinc-400 dark:outline-teal-400 dark:hover:bg-zinc-800 dark:hover:text-zinc-100"
        >
          <XMarkIcon className="size-4" aria-hidden="true" />
        </SearchFieldClear>
      </div>
      {submitted && (
        <p className="text-base text-zinc-600 sm:text-sm dark:text-zinc-400">
          Searching for “{submitted}
        </p>
      )}
    </SearchField>
  );
}

Anatomy

Dashed frames are invisible state providers; shaded shapes own real DOM. Numbered pins match the list below.

A wireframe sketch of the assembled component. Each numbered marker matches a part in the list that follows.

  1. SearchField

    Field provider with no DOM by default. Does not add a DOM element.

  2. SearchFieldInput

    Native search input. Owns a DOM element.

  3. SearchFieldClearOptional

    Optional native clear button shown while the query has text. Owns a DOM element.

Step by step

  1. 1

    Add the main part

    Start with SearchField, Label, and SearchFieldInput.

  2. 2

    Add the supporting parts

    Add SearchFieldClear if clearing a query is useful; it appears only while the query has text.

  3. 3

    Make the behavior clear

    Name the input when the query should be submitted.

    Exampletsx
    <SearchField>
      <Label>Search</Label>
      <SearchFieldInput name="q" />
      <SearchFieldClear aria-label="Clear search" />
    </SearchField>;

Keyboard

Submits the surrounding form.
Esc
Erases the query while it has text.
Moves to the clear button while the query has text.

Forms and accessibility

SearchFieldInput submits its native name and query.

Accessibility checklist

  • Label the search purpose, even when the placeholder says Search.
  • Give the clear button understandable text or an aria-label.
  • Announce result counts outside the input when results update.
  • Pass as="search" when this is the page's search landmark; the native element announces it.

API reference

Importtsx
import { Label, SearchField, SearchFieldClear, SearchFieldInput } from "@comp0/react";

SearchField

Context only

Field provider with no DOM by default.

PropTypeDescription
valuestringControlled field value.
defaultValuestringInitial field value.
onChange(value: string) => voidReceives the next value.
disabledbooleanField-wide states shared with every part.
invalidbooleanField-wide states shared with every part.
requiredbooleanField-wide states shared with every part.
onSubmit(value: string) => voidReceives the query when Enter submits.
onClear() => voidRuns when the query is erased.

SearchFieldInput

DOM element

Native search input.

PropTypeDescription
namestringSubmission name for the query.
placeholderstringHint text; never a replacement for Label.

SearchFieldClear

OptionalDOM element

Optional native clear button shown while the query has text.

Style hooks

Attributes that appear while a state is true. Target them with Tailwind data variants such as data-open:bg-zinc-100, or with any CSS selector.

SearchFieldInput

Style hookMeaning
[data-invalid]The field is invalid.
[data-disabled]The field is disabled.

Keep exploring