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

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.
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.
disabled / invalid / 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.

[data-invalid]

on SearchFieldInput

The field is invalid.
[data-disabled]

on SearchFieldInput

The field is disabled.

Keep exploring