Combobox
A searchable select. Click the trigger to open a popup with a built-in search input that filters the list as you type.
Basic
Show code Hide code
import { Combobox, type ComboboxOption } from '@mylighthouse/prism-react';
import { useState } from 'react';
export default function BasicExample(): React.JSX.Element {
const [value, setValue] = useState<string | null>(null);
const options = [
{ label: 'Amsterdam', value: 'amsterdam' },
{ label: 'Athens', value: 'athens' },
{ label: 'Barcelona', value: 'barcelona' },
{ label: 'Berlin', value: 'berlin' },
{ label: 'Brussels', value: 'brussels' },
{ label: 'Budapest', value: 'budapest' },
{ label: 'Copenhagen', value: 'copenhagen' },
{ label: 'Dublin', value: 'dublin' },
{ label: 'Lisbon', value: 'lisbon' },
{ label: 'London', value: 'london' },
{ label: 'Madrid', value: 'madrid' },
{ label: 'Milan', value: 'milan' },
{ label: 'Paris', value: 'paris' },
{ label: 'Prague', value: 'prague' },
{ label: 'Rome', value: 'rome' },
{ label: 'Stockholm', value: 'stockholm' },
{ label: 'Vienna', value: 'vienna' },
{ label: 'Warsaw', value: 'warsaw' },
];
return (
<Combobox onChange={setValue} options={options} value={value}>
<Combobox.Trigger placeholder="Select a city…" />
<Combobox.Menu>
{(option: ComboboxOption<string>) => (
<Combobox.Option key={option.value} value={option.value}>
{option.label}
</Combobox.Option>
)}
</Combobox.Menu>
</Combobox>
);
} Custom content
Pass any React content as children to Combobox.Option, the text is extracted from that content for search filtering. To customise what appears in the trigger for the selected value, pass a render function as children to Combobox.Trigger.
Show code Hide code
import { Badge, Combobox, Icon } from '@mylighthouse/prism-react';
import { useState } from 'react';
type City = { country: string; label: string; value: string };
const options: City[] = [
{ label: 'Amsterdam', value: 'amsterdam', country: 'NL' },
{ label: 'Barcelona', value: 'barcelona', country: 'ES' },
{ label: 'London', value: 'london', country: 'GB' },
{ label: 'Paris', value: 'paris', country: 'FR' },
{ label: 'Rome', value: 'rome', country: 'IT' },
];
export default function CustomTriggerExample(): React.JSX.Element {
const [value, setValue] = useState<string | null>(null);
return (
<Combobox onChange={setValue} options={options} value={value}>
<Combobox.Trigger placeholder="Select a city…">
{(selectedValue) => {
const city = options.find((o) => o.value === selectedValue);
return city ? (
<span style={{ alignItems: 'center', display: 'flex', gap: '8px' }}>
<Icon aria-hidden="true" name="location-pin" size="small" />
{city.label}
</span>
) : null;
}}
</Combobox.Trigger>
<Combobox.Menu>
{(option: City) => (
<Combobox.Option key={option.value} value={option.value}>
<span style={{ alignItems: 'center', display: 'flex', gap: '8px' }}>
<Icon aria-hidden="true" name="location-pin" size="small" />
{option.label}
</span>
<Badge isSmall>{option.country}</Badge>
</Combobox.Option>
)}
</Combobox.Menu>
</Combobox>
);
} Validation states
Use hasError for critical validation failures and hasWarning for non-blocking issues. Pass disabled to prevent all interaction.
Show code Hide code
import { Combobox, type ComboboxOption } from '@mylighthouse/prism-react';
import { useState } from 'react';
const options: ComboboxOption<string>[] = [
{ label: 'Amsterdam', value: 'amsterdam' },
{ label: 'Barcelona', value: 'barcelona' },
{ label: 'London', value: 'london' },
{ label: 'Paris', value: 'paris' },
{ label: 'Rome', value: 'rome' },
];
const optionsWithDisabled: ComboboxOption<string>[] = [
{ label: 'Amsterdam', value: 'amsterdam' },
{ label: 'Barcelona', value: 'barcelona', disabled: true },
{ label: 'London', value: 'london' },
{ label: 'Paris', value: 'paris', disabled: true },
{ label: 'Rome', value: 'rome' },
];
export default function ValidationStatesExample(): React.JSX.Element {
const [errorValue, setErrorValue] = useState<string | null>('amsterdam');
const [warningValue, setWarningValue] = useState<string | null>('amsterdam');
const [disabledValue] = useState<string | null>('amsterdam');
const [disabledOptionsValue, setDisabledOptionsValue] = useState<
string | null
>(null);
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
<Combobox
hasError
onChange={setErrorValue}
options={options}
value={errorValue}
>
<Combobox.Trigger placeholder="Error state" />
<Combobox.Menu>
{(option: ComboboxOption<string>) => (
<Combobox.Option key={option.value} value={option.value}>
{option.label}
</Combobox.Option>
)}
</Combobox.Menu>
</Combobox>
<Combobox
hasWarning
onChange={setWarningValue}
options={options}
value={warningValue}
>
<Combobox.Trigger placeholder="Warning state" />
<Combobox.Menu>
{(option: ComboboxOption<string>) => (
<Combobox.Option key={option.value} value={option.value}>
{option.label}
</Combobox.Option>
)}
</Combobox.Menu>
</Combobox>
<Combobox disabled options={options} value={disabledValue}>
<Combobox.Trigger placeholder="Disabled state" />
<Combobox.Menu>
{(option: ComboboxOption<string>) => (
<Combobox.Option key={option.value} value={option.value}>
{option.label}
</Combobox.Option>
)}
</Combobox.Menu>
</Combobox>
<Combobox
onChange={setDisabledOptionsValue}
options={optionsWithDisabled}
value={disabledOptionsValue}
>
<Combobox.Trigger placeholder="Disabled options" />
<Combobox.Menu>
{(option: ComboboxOption<string>) => (
<Combobox.Option
disabled={option.disabled}
key={option.value}
value={option.value}
>
{option.label}
</Combobox.Option>
)}
</Combobox.Menu>
</Combobox>
</div>
);
} Small
Use isSmall for a more compact control.
Show code Hide code
import { Combobox, type ComboboxOption } from '@mylighthouse/prism-react';
import { useState } from 'react';
const options = [
{ label: 'Amsterdam', value: 'amsterdam' },
{ label: 'Barcelona', value: 'barcelona' },
{ label: 'London', value: 'london' },
{ label: 'Paris', value: 'paris' },
{ label: 'Rome', value: 'rome' },
];
export default function SmallExample(): React.JSX.Element {
const [value, setValue] = useState<string | null>(null);
return (
<Combobox isSmall onChange={setValue} options={options} value={value}>
<Combobox.Trigger placeholder="Select a city…" />
<Combobox.Menu>
{(option: ComboboxOption<string>) => (
<Combobox.Option key={option.value} value={option.value}>
{option.label}
</Combobox.Option>
)}
</Combobox.Menu>
</Combobox>
);
} API Reference
Combobox
| Name | Default | Type | Description |
|---|---|---|---|
options * | -- | ComboboxOption<Value>[] | -- |
defaultValue | -- | Value | -- |
disabled | -- | boolean | -- |
hasError | -- | boolean | -- |
hasWarning | -- | boolean | -- |
isSmall | -- | boolean | -- |
name | -- | string | -- |
onChange | -- | (value: Value) => void | -- |
unsafe_open | -- | boolean | Do not use this prop in production. Only used for testing and documentation purposes. |
value | -- | Value | -- |
Combobox.Trigger
| Name | Default | Type | Description |
|---|---|---|---|
aria-label | -- | string | -- |
id | -- | string | -- |
placeholder | -- | string | -- |
Combobox.Menu
| Name | Default | Type | Description |
|---|---|---|---|
placeholder | -- | string | -- |
searchLabel | -- | string | Accessible label for the search input. Defaults to "Search". Override for localisation or context-specific labels. |
Combobox.Option
| Name | Default | Type | Description |
|---|---|---|---|
value * | -- | Value | -- |
disabled | -- | boolean | -- |