- Accordion
- Action Bar
- Action Toast
- Alert Banner
- Alert Dialog
- Alert
- Alphabet Index
- Amount Field
- Aspect Ratio
- Attachment
- Availability List
- Avatar
- Badge
- Bank Card
- Breadcrumb
- Bubble
- Button Group
- Button
- Calendar
- Camera Frame
- Card Design Picker
- Card Details
- Card Peek
- Card Stack
- Card
- Carousel
- Chart
- Chat Thread
- Checkbox
- Chip Group
- Choice Tile
- Code Block
- Code Dots
- Collapsible
- Combobox
- Command
- Context Menu
- Copy Field
- Countdown
- Country Select
- Data Table
- Date Field
- Date Picker
- Date Range Picker
- Dialog
- Direction
- Document Paper
- Drawer
- Dropdown Menu
- Empty
- Entity Avatar
- Field
- File Trigger
- File Upload Item
- Hover Card
- Input Group
- Input OTP
- Input
- Item
- Kbd
- Key Value
- Keypad
- Label
- Live Region
- Marker
- Message Scroller
- Message
- Money Amount
- Native Select
- Number Field
- Pagination
- Percent Split Editor
- Phone Field
- Popover
- Progress
- QR Code
- Questionnaire
- Radio Group
- Range Histogram
- Rating
- Resizable
- Scroll Area
- Search Field
- Select
- Separator
- Share Bar
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Sortable List
- Spinner
- Status Timeline
- Step Header
- Steps List
- Swipe Row
- Switch
- Table
- Tabs
- Text Field
- Textarea
- Tier Ladder
- Toggle Group
- Toggle
- Token Search Field
- Tooltip
- Trace
- Transaction Row
- Usage Meter
- Maya Chen
- Leo Park
- Ana Ruiz
- Sam Okafor
- Ivy Novak
"use client"
import * as React from "react"Use a search field to filter a list or start a search, such as finding a contact to pay or a past payment. It is a pill with a search icon and a clear button that shows while there is text. Pick TokenSearchField when people filter with operators like amount or date, and a TextField when the value is data to save rather than a query.
Installation#
pnpm dlx shadcn@latest add @dots/search-field
Usage#
import {
SearchField,
SearchFieldDescription,
SearchFieldError,
SearchFieldInput,
SearchFieldLabel,
} from "@/components/ui/search-field"<SearchField aria-label="Search payments">
<SearchFieldInput placeholder="Search payments" />
</SearchField>Composition#
Use the following composition to build a search field:
SearchField
├── SearchFieldLabel
├── SearchFieldInput
│ └── addons (children)
├── SearchFieldDescription
└── SearchFieldErrorFeatures#
- Built on React Aria
SearchField: Escape clears the text, Enter callsonSubmit - A clear button that renders only while there is text and the field is editable
- Optional label, description and error, wired to the input for screen readers
- Extra addons, such as a keyboard hint, through
SearchFieldInputchildren - Controlled or uncontrolled with
valueordefaultValue
Label and description#
Add a SearchFieldLabel when the screen does not already say what is searched, and a SearchFieldDescription for a short hint.
import {
SearchField,
SearchFieldDescription,Submit#
Use onSubmit to run a search when the user presses Enter, and onClear to reset it.
Press Enter to search
"use client"
import * as React from "react"Keyboard hint#
Pass an InputGroupAddon as children of SearchFieldInput to show a shortcut or a filter button at the end of the pill. The hint is only a label: bind the key yourself and focus the input through a ref. In this demo, pressing / focuses the field.
"use client"
import * as React from "react"const inputRef = React.useRef<HTMLInputElement>(null)
React.useEffect(() => {
function onKeyDown(event: KeyboardEvent) {
const target = event.target as HTMLElement | null
if (event.key !== "/" || target?.closest("input, textarea")) return
event.preventDefault()
inputRef.current?.focus()
}
document.addEventListener("keydown", onKeyDown)
return () => document.removeEventListener("keydown", onKeyDown)
}, [])
<SearchFieldInput ref={inputRef}>
<InputGroupAddon align="inline-end">
<Kbd>/</Kbd>
</InputGroupAddon>
</SearchFieldInput>Invalid#
Set isInvalid and add a SearchFieldError that says what to fix.
import {
SearchField,
SearchFieldError,Disabled#
Set isDisabled to turn the field off. The clear button is hidden and the label and description are dimmed.
import {
SearchField,
SearchFieldDescription,Accessibility#
React Aria gives the input type="search", connects the label, description and error to it, clears on Escape and submits on Enter. The clear button has the localized name "Clear search" by default.
Name the field#
Give every search field a name. Use a SearchFieldLabel, or aria-label when a visible label would repeat the screen title.
<SearchField aria-label="Search contacts">
<SearchFieldInput placeholder="Search contacts" />
</SearchField>Extra buttons#
React Aria hands every button inside SearchField the clear action. Buttons passed as SearchFieldInput children are shielded from it. Any other button placed directly under SearchField needs slot={null}, and an icon-only button needs an aria-label.
<SearchField aria-label="Search payments">
<SearchFieldInput />
<Button slot={null} variant="ghost" aria-label="Filters">
<FilterIcon />
</Button>
</SearchField>Placeholder is not a label#
The placeholder disappears as soon as the user types. Do not use it as the only name of the field.
API Reference#
SearchField#
The root. Renders a React Aria SearchField and accepts all of its props.
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | - | The text, when controlled. |
defaultValue | string | - | The starting text, when uncontrolled. |
onChange | (value: string) => void | - | Called when the text changes. |
onSubmit | (value: string) => void | - | Called when the user presses Enter. |
onClear | () => void | - | Called when the field is cleared. |
isDisabled | boolean | - | Turns the field off. |
isReadOnly | boolean | - | The text can be selected but not changed. |
isInvalid | boolean | - | Shows the field as invalid and reveals the error. |
validationBehavior | "native" | "aria" | "native" | Whether validation blocks form submission. |
className | string | - | Additional classes to apply to the root. |
...props | SearchFieldProps | - | Other React Aria SearchField props. |
SearchFieldLabel#
The visible name of the field. Renders a Label and accepts all of its props.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional classes to apply to the label. |
SearchFieldInput#
The pill with the search icon, the input and the clear button. Accepts all InputGroupInput props, which go to the input.
| Prop | Type | Default | Description |
|---|---|---|---|
placeholder | string | "Search" | Hint text shown while the field is empty. |
clearLabel | string | - | Accessible name of the clear button. "Clear search" by default. |
children | React.ReactNode | - | Extra addons after the input. Buttons here do not clear the field. |
className | string | - | Additional classes to apply to the pill around the input. |
SearchFieldDescription#
Help under the field, read with it. Renders a React Aria Text with slot="description".
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional classes to apply to the description. |
SearchFieldError#
Says what to fix. Shown while the field is invalid. Renders a React Aria FieldError.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional classes to apply to the error. |