Search Input
A token-safe search field with a consistent clear action across browsers.
- Status
- Since
0.11.0- Accessibility pattern
- native search input with labelled clear button
Last updated
Install
Configure registry credentials first using the Quickstart. Before copying this item or any transitive registry dependency, verify the signed manifest and save the exact bytes for Search Input before installation. Retain the digest printed by this command.
pnpm exec vegastack-design verify search-inputInstall with the pinned shadcn CLI. Bare shadcn does not verify VegaStack signature or integrity.
pnpm dlx shadcn@4.21.0 add @vegastack/search-inputRun the exact offline --post-write command printed by the preflight, using its saved item path and independently retained --expected-integrity digest. Use the saved preflight for every transitive registry dependency too; stop on any mismatch before using the components.
The same command installs the registry items it composes: @vegastack/input-group, @vegastack/button.
Usage
import { SearchInput } from "@/components/ui/search-input";
<SearchInput
value={query}
onValueChange={setQuery}
aria-label="Search projects"
placeholder="Search projects…"
/>;SearchInput composes InputGroup and replaces the browser-owned
search cancel glyph with one semantic, token-colored clear button. className styles the group
root; the forwarded ref and native input attributes target the inner HTMLInputElement.
Examples
States
The clear button appears only while a mutable field has a value. Empty, disabled, and read-only fields expose no clear action; invalid styling comes from the shared InputGroup contract.
Settled value
onValueChange fires on every keystroke, so the field stays instant. onValueCommitted fires with
the settled value: after debounceMs of quiet (default TIMINGS.searchDebounceMs, 300 ms), and
at once on Enter and on clear. Send the query from it, so one word is one request.
Requests sent: none yet
Collapsible
collapsible folds the field to a Search icon button while it is empty and unfocused. Pressing the
button opens the field with focus in it; it stays open while it holds a query and folds back once it
is empty and focus leaves it, or on Esc (focus returns to the button).
onExpandedChange reports both, so a toolbar can lay the open field over its neighbours — the
ListToolbar does this as its search's last collapse step.
Native form semantics
Names, labels, descriptions, submission, and reset stay on the inner native search input. In
uncontrolled mode, reset restores defaultValue and updates the clear action.
API Reference
SearchInput
| Prop | Type | Default | Description |
|---|---|---|---|
clearLabel | string | 'Clear search' | Accessible name for the clear action. |
collapsible | boolean | false | Fold to a Search icon button while empty and unfocused. Pressing the button opens the field
with focus in it; the field stays open while it holds a query, and folds back once it is empty
and focus leaves it, or on Escape (focus returns to the button). The button's name is the
field's aria-label (or its placeholder). |
data-slot | string | 'search-input' | Slot name applied to the InputGroup root. |
debounceMs | number | TIMINGS.searchDebounceMs (300) | Quiet time after the last keystroke before onValueCommitted fires. |
defaultValue | string | '' | The initial value when the search field is uncontrolled. |
onExpandedChange | ((expanded: boolean) => void) | — | Called when a collapsible field opens or folds — a toolbar lays the open field over its
neighbours. |
onValueChange | ((value: string) => void) | — | Called with the next value after typing or clearing. |
onValueCommitted | ((value: string) => void) | — | Called with the SETTLED value: after debounceMs of quiet, and at once on
Enter and on clear. The field itself stays instant — onValueChange still
fires on every keystroke. Use this one to send the query. |
value | string | — | The controlled search value. |
Data attributes and CSS variables on SearchInput
| Attribute | Values |
|---|---|
data-collapsible | "" |
data-slot | "search-input-clear" |
Accessibility
- Give the search field an accessible name with a visible
Label,aria-label, oraria-labelledby. - The clear action is a native button named
Clear searchby default. UseclearLabelwhen the page contains several search fields. - Tab moves from the input to the clear button. Enter, Space, or Escape clears a filled mutable field and returns focus to the input.
- The clear button has a real 24×24px border box and mirrors to the logical end in RTL.
| Contract | States tested |
|---|---|
| Behaviour | controlled, uncontrolled, empty, disabled, readonly, invalid, debounced, committed |
| Accessibility | native-search-semantics, browser-accessibility-test, labeled, disabled, invalid |
| Visual | default, hover, focus, disabled, invalid |