A search input with an accessible results dropdown.
import { SearchAutocomplete, SearchAutocompleteItem } from '@backstage/ui';
<SearchAutocomplete
inputValue={inputValue}
onInputChange={setInputValue}
>
{items.map(item => (
<SearchAutocompleteItem key={item.id} id={item.id} textValue={item.name}>
{item.name}
</SearchAutocompleteItem>
))}
</SearchAutocomplete>| Prop | Type | Default | Description |
|---|---|---|---|
| aria-label | string | - | Accessible label for the search input. |
| aria-labelledby | string | - | ID of the element that labels the search input. |
| inputValue | string | - | The current input value (controlled). |
| onInputChange | (value: string) => void | - | Handler called when the input value changes. |
| placeholder | string | Search | Placeholder text shown when the input is empty. Also used as the accessible label when neither aria-label nor aria-labelledby is provided. |
| size | smallmedium | small | Visual size of the input. Use small for inline or dense layouts, medium for standalone fields. |
| isLoading | boolean | false | Whether results are currently loading. Dims existing results and announces loading state to screen readers. |
| popoverWidth | string | - | Width of the results popover. Accepts any CSS width value. Matches the input width when not set. |
| popoverPlacement | bottom startbottom endtop starttop end | bottom start | Placement of the results popover relative to the input. |
| defaultOpen | boolean | false | Whether the results popover is open by default. |
| children | ReactNode | - | The result items to render inside the autocomplete. |
| className | string | - | Additional CSS class name for custom styling. |
| style | CSSProperties | - | Inline CSS styles object. |
Inherits all React Aria Autocomplete props.
Individual result item within the autocomplete list.
| Prop | Type | Default | Description |
|---|---|---|---|
| id | string | - | Unique identifier for the item. |
| textValue | string | - | Plain text value used for keyboard navigation and accessibility. |
| onAction | () => void | - | Handler called when the item is selected. |
| children | ReactNode | - | Content to render inside the item. |
| className | string | - | Additional CSS class name for custom styling. |
Here's a view when items include a title and description.
const fruits = [
{ id: 'apple', name: 'Apple', description: 'A round fruit' },
{ id: 'banana', name: 'Banana', description: 'A yellow curved fruit' },
{ id: 'cherry', name: 'Cherry', description: 'A small red stone fruit' },
];
function Example() {
const [inputValue, setInputValue] = useState('');
const filtered = fruits.filter(fruit =>
fruit.name.toLowerCase().includes(inputValue.toLowerCase()),
);
return (
<SearchAutocomplete
placeholder="Search fruits..."
inputValue={inputValue}
onInputChange={setInputValue}
>
{filtered.map(fruit => (
<SearchAutocompleteItem
key={fruit.id}
id={fruit.id}
textValue={fruit.name}
>
<Text weight="bold">{fruit.name}</Text>
<Text variant="body-small" color="secondary">
{fruit.description}
</Text>
</SearchAutocompleteItem>
))}
</SearchAutocomplete>
);
}Use popoverWidth to control the dropdown width when placed in constrained layouts like PluginHeader.
<PluginHeader
title="Title"
customActions={
<>
<SearchAutocomplete
size="small"
inputValue={inputValue}
onInputChange={setInputValue}
popoverWidth="400px"
>
{filtered.map(fruit => (
<SearchAutocompleteItem
key={fruit.id}
id={fruit.id}
textValue={fruit.name}
>
{fruit.name}
</SearchAutocompleteItem>
))}
</SearchAutocomplete>
</>
}
/>Use onAction on items to handle selection and reset the input.
function Example() {
const [inputValue, setInputValue] = useState('');
const [selected, setSelected] = useState<string | null>(null);
const filtered = fruits.filter(fruit =>
fruit.name.toLowerCase().includes(inputValue.toLowerCase()),
);
return (
<Flex direction="column" gap="4">
<SearchAutocomplete
placeholder="Search fruits..."
inputValue={inputValue}
onInputChange={setInputValue}
>
{filtered.map(fruit => (
<SearchAutocompleteItem
key={fruit.id}
id={fruit.id}
textValue={fruit.name}
onAction={() => {
setSelected(fruit.name);
setInputValue('');
}}
>
{fruit.name}
</SearchAutocompleteItem>
))}
</SearchAutocomplete>
<Text>Last selected: {selected ?? 'none'}</Text>
</Flex>
);
}Our theming system is based on a mix between CSS classes, CSS variables and data attributes. If you want to customise this component, you can use one of these class names below.
bui-SearchAutocompletebui-SearchAutocompleteSearchFieldbui-SearchAutocompleteInputbui-SearchAutocompleteClearbui-SearchAutocompletePopoverbui-SearchAutocompleteInnerbui-SearchAutocompleteListBoxbui-SearchAutocompleteLoadingStatebui-SearchAutocompleteEmptyStateOur theming system is based on a mix between CSS classes, CSS variables and data attributes. If you want to customise this component, you can use one of these class names below.
bui-SearchAutocompleteItembui-SearchAutocompleteItemContent