Search Input
SearchInput is a text input tuned for search: a leading search icon, a built-in 300ms debounce so callbacks don’t fire on every keystroke, and optional match-navigation controls.
The example below tracks the current value with React state.
Variations
With navigation
Set showPrevNextButtons to add match-navigation controls. Previous, next, and clear buttons appear once there’s text in the field.
Navigation:
- Click the ↑ button or press Shift+Enter to go to the previous result
- Click the ↓ button or press Enter to go to the next result
- Click the × button to clear the search
- Click the ⌘F badge or press ⌘F (Mac) / Ctrl+F (Windows/Linux) to focus the search input
Installation
import { SearchInput } from '@harnessio/ui/components'
//...
return ( <SearchInput placeholder="Type to search..." onChange={(value) => setSearchValue(value)} />)Anatomy
SearchInput is a single input with a leading search icon. It manages its own value internally — read changes through onChange (which receives the string value, debounced), and drive a controlled value with searchValue.
<SearchInput placeholder="Type to search..." onChange={(value) => setQuery(value)}/>- Debounce —
onChangeis debounced 300ms by default. Pass a number to change the delay, orfalseto fire on every keystroke. - Navigation — with
showPrevNextButtons, previous / next / clear buttons appear when there’s text. WireonNext/onPrev(or a singleonEnter(text, reverse)), and show progress withcounter. - Suffix — use
suffixfor a trailing affordance, such as a keyboard-shortcut badge.
Best practices
Do
- Keep the default debounce for live-filtering large lists or issuing network requests; only lower it when instant feedback matters.
- Show a
counter(e.g.3/128) whenever you enable navigation, so people know where they are in the results. - Provide an accessible name (see Accessibility) since the field has no visible label.
Don’t
- Don’t add navigation buttons for a simple filter that has no notion of “current match”.
- Don’t debounce when the input drives purely local, cheap state where users expect instant response.
Content
- Use a placeholder that hints at the scope of the search (“Search pipelines…”), not just “Search”.
- Keep the
countercompact — “current/total” (3/128).
Accessibility
Keyboard
EntertriggersonEntermoving forward (next match);Shift + Entertriggers it in reverse (previous match).- The optional previous / next / clear buttons are standard buttons, reachable and activatable from the keyboard.
⌘F/Ctrl+Fis not handled by the component. The demo wires its own window listener; add one yourself if you want that shortcut.
Labeling
- The field renders as a plain text input with no visible label and no built-in
aria-label. Providearia-label(or associate a label) so its purpose is announced. - The navigation buttons carry
aria-labels (“Previous match”, “Next match”, “Clear search”).
Properties
Prop | Required | Default | Type |
|---|---|---|---|
| onChange | false | (value: string) => void | |
| searchValue | false | string | |
| debounce | false | true | number | boolean |
| placeholder | false | 'Search' | string |
| showPrevNextButtons | false | false | boolean |
| counter | false | string | |
| onEnter | false | (text: string, reverse?: boolean) => void | |
| onPrev | false | (text: string) => void | |
| onNext | false | (text: string) => void | |
| onKeyDown | false | (event: React.KeyboardEvent<HTMLInputElement>) => void | |
| theme | false | 'default' | 'default' | 'success' | 'danger' | 'warning' |
| size | false | 'md' | 'md' | 'sm' |
| prefix | false | ReactNode | |
| suffix | false | ReactNode | |
| disabled | false | false | boolean |
| readOnly | false | false | boolean |
| id | false | string | |
| className | false | string | |
| inputContainerClassName | false | string |
The component forwards its ref to the underlying <input>, so you can call ref.current?.focus() (as the navigation example does).