SearchInput
Search-shaped input built on Input — leading search icon, clear button, debounced onSearch, and Enter-to-submit.
Renders type="search"; Escape clears the field; clear button has an accessible label.
Preview
tsx
import { SearchInput } from '@arshad-shah/cynosure-react';
export default function Example() {
return (
<div style={{ width: '320px' }}>
<SearchInput aria-label="Search" placeholder="Search docs…" />
</div>
);
}
Three sizes are available: sm, md (default), and lg.
Preview
tsx
import { SearchInput } from '@arshad-shah/cynosure-react';
export default function Example() {
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem', width: '320px' }}>
<SearchInput aria-label="Small" size="sm" placeholder="Search…" />
<SearchInput aria-label="Medium" size="md" placeholder="Search…" />
<SearchInput aria-label="Large" size="lg" placeholder="Search…" />
</div>
);
}
Debounced search
Section titled “Debounced search”onSearch fires debounceMs (default 200) after the user stops typing — useful for kicking off network calls without thrashing the server.
Preview
tsx
import { SearchInput } from '@arshad-shah/cynosure-react';
import { useState } from 'react';
export default function Example() {
const [query, setQuery] = useState('');
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem', width: '320px' }}>
<SearchInput
aria-label="Search (debounced)"
debounceMs={300}
onSearch={setQuery}
placeholder="Type to search…"
/>
<span style={{ fontSize: '0.875rem', color: 'var(--c-fg-muted)' }}>
Debounced query: {query || '(empty)'}
</span>
</div>
);
}
Submit on Enter
Section titled “Submit on Enter”onSubmit fires when the user presses Enter.
Preview
tsx
import { SearchInput } from '@arshad-shah/cynosure-react';
import { useState } from 'react';
export default function Example() {
const [submitted, setSubmitted] = useState<string | null>(null);
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem', width: '320px' }}>
<SearchInput
aria-label="Search"
onSubmit={setSubmitted}
placeholder="Press Enter to submit"
/>
<span style={{ fontSize: '0.875rem', color: 'var(--c-fg-muted)' }}>
Last submitted: {submitted ?? '(none)'}
</span>
</div>
);
}
States
Section titled “States” Preview
tsx
import { SearchInput } from '@arshad-shah/cynosure-react';
export default function Example() {
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem', width: '320px' }}>
<SearchInput aria-label="Default" placeholder="Search…" />
<SearchInput aria-label="With value" defaultValue="cynosure" />
<SearchInput aria-label="Invalid" defaultValue="bad query" invalid />
<SearchInput aria-label="Disabled" defaultValue="locked" disabled />
</div>
);
}
PropTypeDefaultDescription
variant
"outline"|"filled"|"ghost"|"flat"
"outline"
Visual treatment forwarded to the underlying `<Input>`.
placeholder
string
"Search…"
Placeholder text.
onSearch
((query: string) => void)
—
Debounced callback — fires `debounceMs` after the user stops typing.
debounceMs
number
200
Debounce delay in milliseconds for `onSearch`.
onSubmit
((query: string) => void)
—
Submit handler — fires on Enter.
className
string
—
style
CSSProperties
—
size
"sm"|"md"|"lg"
"md"
Control size — affects height, padding, and font size.
value
string
—
Controlled value. Pair with `onChange`.
defaultValue
string
—
Uncontrolled initial value.
onChange
((value: string) => void)
—
Called with the next value whenever the user changes the field.
disabled
boolean
—
Disables interaction and dims the field.
name
string
—
Submitted form field name.
readOnly
boolean
—
Renders the field as read-only — value is visible and selectable but not editable.
required
boolean
—
Marks the field as required for form submission.
autoFocus
boolean
—
Focuses the control on mount.
id
string
—
Element id — auto-generated via `useId` when omitted.
invalid
boolean
—
Renders the invalid state (red border, error styling) and sets `aria-invalid`.
Accessibility
Section titled “Accessibility”- Renders
type="search"— assistive tech announces the field as a searchbox. - The clear button (rendered automatically when the field has a value) carries an accessible label and is keyboard reachable.
- Pressing Escape clears the value and keeps focus on the input.
- Provide an
aria-labelwhen there is no visible caption.
Recipes
Section titled “Recipes”- Tune
debounceMsfor your latency budget — 150–300 ms is a good default range. - Use
onSubmitto trigger an explicit search on Enter (e.g. navigation), whileonSearchpowers live filtering. - Place above a list and pipe the debounced query through your data fetching to filter results in place.