Autocomplete
Overview
The Autocomplete component provides an input field with dropdown suggestions that filter based on user input. It supports both string arrays and object data, keyboard navigation, and custom templates.
Import
import { Autocomplete } from '@allxsmith/bestax-bulma';
Props
| Prop | Type | Default | Description |
|---|---|---|---|
data | AutocompleteItem[] | string[] | — | The options data to display (required). |
value | string | — | The current input value (controlled). |
selected | AutocompleteItem | string | null | — | The selected item (controlled). |
placeholder | string | — | Placeholder text for the input. |
field | string | 'label' | Object property to use as the display field. |
clearable | boolean | false | Whether to show a clear button. |
openOnFocus | boolean | false | Open dropdown when input is focused. |
keepFirst | boolean | false | Keep first option highlighted. |
keepOpen | boolean | false | Keep dropdown open after selection. |
selectOnClickOutside | boolean | false | Select highlighted item on click outside. |
maxHeight | number | 200 | Maximum dropdown height in pixels. |
dropdown | boolean | false | Render as dropdown style. |
loading | boolean | false | Show loading state. |
disabled | boolean | false | Whether the input is disabled. |
color | 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger' | — | Input color variant. |
size | 'small' | 'medium' | 'large' | — | Size variant. |
onInput | (value: string) => void | — | Callback when input value changes. |
onSelect | (item: AutocompleteItem | string | null) => void | — | Callback when item is selected. |
onActiveChange | (active: boolean) => void | — | Callback when dropdown active state changes. |
onInfiniteScroll | () => void | — | Callback when scrolled to bottom. |
checkInfiniteScroll | boolean | false | Enables infinite scroll detection in the dropdown. |
infiniteScrollDistance | number | 50 | Distance in pixels from the bottom to trigger onInfiniteScroll. |
itemTemplate | (item: AutocompleteItem | string) => React.ReactNode | — | Custom render for items. |
header | React.ReactNode | — | Custom header in dropdown. |
footer | React.ReactNode | — | Custom footer in dropdown. |
empty | React.ReactNode | — | Content to show when no results. |
className | string | — | Additional CSS classes. |
ref | React.Ref<HTMLElement> | — | Ref forwarded to the input element. |
| ... | All standard HTML and Bulma helper props | (See Helper Props) |
AutocompleteItem
| Prop | Type | Description |
|---|---|---|
value | string | The item value. |
label | string | Display label (optional). |
disabled | boolean | Whether item is disabled. |
Usage
Basic Autocomplete
Simple autocomplete with string array.
function example() { const [selected, setSelected] = useState(null); const fruits = [ 'Apple', 'Banana', 'Cherry', 'Date', 'Elderberry', 'Fig', 'Grape', ]; return ( <Block> <Autocomplete data={fruits} placeholder="Search fruit..." onSelect={setSelected} /> {selected && <Paragraph mt="2">Selected: {selected}</Paragraph>} </Block> ); }
Open on Focus
Dropdown opens immediately when input is focused.
function example() { const [selected, setSelected] = useState(null); const countries = [ 'United States', 'United Kingdom', 'Canada', 'Australia', 'Germany', 'France', ]; return ( <Autocomplete data={countries} placeholder="Select a country..." openOnFocus onSelect={setSelected} /> ); }
With Clear Button
Autocomplete with clearable input.
function example() { const [selected, setSelected] = useState(null); const options = ['Option 1', 'Option 2', 'Option 3', 'Option 4']; return ( <Autocomplete data={options} placeholder="Search options..." clearable onSelect={setSelected} /> ); }
Color and Size Variants
Autocomplete with different colors and sizes.
<Block display="flex" flexDirection="column" gap="4"> <Autocomplete data={['Apple', 'Banana', 'Cherry']} placeholder="Primary small" color="primary" size="small" /> <Autocomplete data={['Apple', 'Banana', 'Cherry']} placeholder="Info normal" color="info" /> <Autocomplete data={['Apple', 'Banana', 'Cherry']} placeholder="Success medium" color="success" size="medium" /> <Autocomplete data={['Apple', 'Banana', 'Cherry']} placeholder="Danger large" color="danger" size="large" /> </Block>
With Object Data
Autocomplete with object items.
function example() { const [selected, setSelected] = useState(null); const users = [ { value: '1', label: 'John Doe', email: '[email protected]' }, { value: '2', label: 'Jane Smith', email: '[email protected]' }, { value: '3', label: 'Bob Johnson', email: '[email protected]' }, ]; return ( <Block> <Autocomplete data={users} field="label" placeholder="Search users..." openOnFocus onSelect={setSelected} /> {selected && ( <Paragraph mt="2"> Selected: {selected.label} ({selected.email}) </Paragraph> )} </Block> ); }
Custom Item Template
Autocomplete with custom item rendering.
function example() { const [selected, setSelected] = useState(null); const users = [ { value: '1', label: 'John Doe', role: 'Admin' }, { value: '2', label: 'Jane Smith', role: 'Editor' }, { value: '3', label: 'Bob Johnson', role: 'Viewer' }, ]; return ( <Autocomplete data={users} field="label" placeholder="Search users..." openOnFocus onSelect={setSelected} itemTemplate={item => ( <Block display="flex" justifyContent="space-between"> <Span>{item.label}</Span> <Tag color="info" light> {item.role} </Tag> </Block> )} /> ); }
With Empty State
Custom content when no results match.
function example() { const options = ['Apple', 'Banana', 'Cherry']; return ( <Autocomplete data={options} placeholder="Try searching 'xyz'..." empty={ <Paragraph textColor="grey"> <Icon name="search" variant="solid" mr="2" /> No results found </Paragraph> } /> ); }
Loading State
Autocomplete showing loading indicator.
<Autocomplete data={[]} placeholder="Loading..." loading />
Keep First Highlighted
First option stays highlighted while typing.
function example() { const fruits = [ 'Apple', 'Apricot', 'Avocado', 'Banana', 'Blackberry', 'Blueberry', ]; return ( <Autocomplete data={fruits} placeholder="Type to filter..." keepFirst /> ); }
Context-Aware Rendering
The Autocomplete component is context-aware: it detects whether it is already inside a Field and adjusts its rendering accordingly. This means you can use it standalone with a label prop (it wraps itself in a Field), or inside a Field (it skips rendering its own).
Autocomplete does not use ControlContext, so the "With Field and Control Wrappers" example below uses Field wrapping only. The Control wrapper is shown for layout consistency but does not change the component's internal rendering.
Default (with label)
The simplest usage — the component automatically renders its own Field wrapper.
<Autocomplete label="Fruit" data={['Apple', 'Banana', 'Cherry']} placeholder="Search fruit..." />
With Field Wrapper
When you need manual control over the Field layout (e.g., horizontal forms), wrap the component in Field. The component detects it's inside a Field and skips rendering its own.
function example() { return ( <Field horizontal label="Fruit"> <Field.Body> <Field> <Autocomplete data={['Apple', 'Banana', 'Cherry']} placeholder="Search fruit..." /> </Field> </Field.Body> </Field> ); }
With Field and Control Wrappers
For full manual composition with icons, wrap in both Field and Control. Autocomplete does not consume ControlContext, but the Field wrapper is still detected and its own Field is skipped.
function example() { return ( <Field horizontal label="Fruit"> <Field.Body> <Field> <Control iconLeftName="search"> <Autocomplete data={['Apple', 'Banana', 'Cherry']} placeholder="Search fruit..." /> </Control> </Field> </Field.Body> </Field> ); }
Keyboard Navigation
| Key | Action |
|---|---|
↓ | Open dropdown / Move down |
↑ | Move up |
Enter | Select highlighted item |
Tab | Select highlighted and move focus |
Escape | Close dropdown |
Form Submission
Autocomplete is an HTML form element. Pass a name prop and the typed/selected text is forwarded to the inner <input> so the value submits with the surrounding form, exactly like a native text input.
| Prop | Description |
|---|---|
name | Form field name. Forwarded to the inner <input>. |
form | Optional id of the form the input belongs to. |
required | Marks the field as required for native HTML form validation. |
function AutocompleteFormDemo() { const [submitted, setSubmitted] = React.useState(''); return ( <form onSubmit={e => { e.preventDefault(); const fd = new FormData(e.currentTarget); setSubmitted(JSON.stringify(Array.from(fd.entries()), null, 2)); }} > <Autocomplete name="city" data={['New York', 'London', 'Paris', 'Tokyo', 'Sydney']} placeholder="Search a city…" /> <div style={{ marginTop: '1rem' }}> <button type="submit" className="button is-primary"> Submit </button> </div> {submitted && <pre style={{ marginTop: '1rem' }}>{submitted}</pre>} </form> ); }
Accessibility
- Uses
role="combobox"witharia-expanded - Has
aria-haspopup="listbox"andaria-autocomplete="list" - Dropdown items use
role="option"witharia-selected - Disabled items have
aria-disabled - Full keyboard navigation support
Related Components
- Taginput - For multiple tag selection with autocomplete
- Select - For simple dropdown selection
- Input - For basic text input
Additional Resources
Use keepFirst combined with Enter to quickly select the first matching result without using the mouse.