SearchField
A search box that is a GET form.
Why it exists
Six of these existed — Mint's toolbar, Mint's search page, Mint's search box, Harvest's list chrome, Harvest's search page, Harvest's forms — and every one had independently discovered the same non-obvious requirement, in four different ways.
A bare GET form replaces the whole query string
The other filters ride along
Everything in params except this field and page is re-submitted as a hidden input. Switch to the code tab: the form below is carrying a status and a team it never displays.
And page is dropped, not carried
A new search on page 4 of the old results is a page that does not exist yet. The pager then reads “No records on page 4” for a query with plenty of matches — a failure that looks like the search found nothing.
In both themes
light
dark
Guidance
Use it when
- Any filtered list. Pass the page's searchParams straight in.
- A placeholder that names what is searchable — “A name, a company, an email address” beats “Search…”.
- drop for anything else a new query invalidates: a cursor, a selection, a sub-tab.
Reach for something else when
- An onChange that pushes to the router. It fires per keystroke, fills the history stack, and re-runs the query on every letter.
- A bare <input>. It loses the ring, the themed border and the disabled styling, and none of that is visible in review — tests/accessibility.test.ts asserts this one composes Azalea's Input.
- Searching client-side over a paged list. It searches the page, not the list, and looks like the data is missing.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| params | Record<string, string | string[]> | — | The current query string — Next's searchParams. Re-submitted as hidden inputs. |
| name | string | "q" | The parameter this field owns. |
| drop | string[] | — | Reset by a new search. page is always dropped. |
| placeholder | string | — | Required. Also the accessible name unless label is given. |
| action | string | "" | Where the form posts. Defaults to the current URL. |
| children | ReactNode | — | Rendered inside the form after the input — a submit button, an extra filter. |
Accessibility
role="search" on the form makes it a landmark, so it is reachable directly rather than by tabbing to it. type="search" gets the platform's own clear button and, on iOS, a keyboard whose return key says “Search”. There is an sr-only submit button: Enter submits natively and needs no button, but touch has no Enter key, and a form whose only way to submit is a key that does not exist is a form nobody on a phone can use.