Search
A text input for search queries, with a search icon. Use it to filter a list or start a search.
Code
demo.tsx
import {Search} from '@earendil-works/elanor-react';
export default function SearchDemo() {
return <Search aria-label="Search projects" placeholder="Search projects" />;
} Usage
import {Search} from '@earendil-works/elanor-react';
<Search aria-label="Search projects" placeholder="Search projects" />;
The placeholder isn’t a label; name the input with aria-label or a visible Field label. className styles the input and rootClassName the wrapper.
Density
Use compact beside compact controls, such as Dropdown filters in a search and filter bar. The touch target keeps the default height, as on compact Dropdown triggers.
Code
density.tsx
import {Search, Stack} from '@earendil-works/elanor-react';
export default function SearchDensity() {
return (
<Stack align="stretch">
<Search aria-label="Search projects, default" placeholder="Default" />
<Search density="compact" aria-label="Search projects, compact" placeholder="Compact" />
</Stack>
);
} Filtering with a clear button
Search hides the browser’s built-in clear button, so it looks the same in every browser. To add one, pass it as endAdornment, which places content after the input. Return focus to the input after clearing, and announce the result count in a status region.
3 matching projects
- Website redesign
- Design system
- Release notes
Code
filter.tsx
import {CloseIcon} from '@earendil-works/elanor-icons-react';
import {IconButton, Search, Stack, Text} from '@earendil-works/elanor-react';
import {useRef, useState} from 'react';
const projects = ['Website redesign', 'Design system', 'Release notes'];
export default function SearchFilter() {
const [query, setQuery] = useState('');
const inputRef = useRef<HTMLInputElement>(null);
const matches = projects.filter((project) =>
project.toLowerCase().includes(query.trim().toLowerCase()),
);
return (
<Stack gap="medium">
<Search
ref={inputRef}
aria-label="Search projects"
placeholder="Search projects"
value={query}
onValueChange={setQuery}
endAdornment={
query ? (
<IconButton
aria-label="Clear search"
onClick={() => {
setQuery('');
inputRef.current?.focus();
}}
>
<CloseIcon />
</IconButton>
) : null
}
/>
<Text role="status">
{matches.length
? `${matches.length} matching ${matches.length === 1 ? 'project' : 'projects'}`
: 'No matching projects.'}
</Text>
{matches.length > 0 ? (
<ul>
{matches.map((project) => (
<li key={project}>{project}</li>
))}
</ul>
) : null}
</Stack>
);
} API
Search
| Prop | Type | Default | Description |
|---|---|---|---|
type | 'search' | 'text' | 'search' | |
icon | ReactNode | - | Decorative icon before the input. Defaults to a search icon. |
endAdornment | ReactNode | - | Content after the input, such as a clear button. |
rootClassName | string | - | Class name for the outer wrapper; className styles the input. |
density | 'compact' | 'default' | 'default' | compact removes block padding but keeps the touch target height. |
Also accepts Base UI Input props.