SearchCombobox
A searchable choice from a list your application already has, with a search field in the menu and the option's value as identity.
Use Search when the reader has to search a known list to choose one item: a scheme, a
category, a role. The button shows the choice; the menu opens with a search field on top and a list
that filters while typing. For a short fixed list where searching does not help, use
Select; when the server has to search, use
AsyncCombobox.
Value: db-average
// apps/docs/examples/ui/search-combobox.tsx'use client';
import {useState} from 'react';
import {SearchCombobox} from '@workspace/active-ui/components/composed/search-combobox';import { Field, FieldDescription, FieldLabel,} from '@workspace/active-ui/components/primitives/field';
// A local list: the component filters it. `keywords` is searched, not shown.const SCHEMES = [ {value: 'dc-2024', label: 'Defined contribution 2024', keywords: 'DC'}, {value: 'db-final', label: 'Final salary', keywords: 'DB'}, {value: 'db-average', label: 'Career average', keywords: 'DB CA'}, {value: 'dc-2019', label: 'Defined contribution 2019', keywords: 'DC'}, {value: 'anw', label: 'Surviving dependants', keywords: 'ANW gap'}, {value: 'closed', label: 'Early retirement (closed)', disabled: true},];
/** * A searchable choice from a local list. Type on the focused button to * start searching; the search ignores case and accents and also matches the * hidden codes (try "DB"). The value is the option's `value`, never its label. */export default function SearchComboboxExample() { const [scheme, setScheme] = useState<string | null>('db-average'); return ( <Field className="w-full max-w-xs"> <FieldLabel htmlFor="scheme">Pension scheme</FieldLabel> <SearchCombobox id="scheme" options={SCHEMES} value={scheme} onValueChange={setScheme} placeholder="Choose a scheme" searchLabel="Search schemes" searchPlaceholder="Search…" emptyText="No scheme found." locale="en" aria-describedby="scheme-value" /> <FieldDescription id="scheme-value"> Value: <code>{scheme ?? 'null'}</code> </FieldDescription> </Field> );}What the composition adds#
Search is the Combobox primitive with a button as trigger
and the search field inside the menu. It adds:
identity by
value: two options with the same label stay distinct, and changing the language does not change the stored value;filtering per language: case- and accent-insensitive, anywhere in the label, with the collator of the
localeyou pass. Underes,Espanadoes not findEspaña; underenit does;keywords: extra text that is searched but not shown, such as a code;typing on the button starts a search: a key typed on the focused, closed button opens the menu and becomes the start of the query, instead of choosing the first matching option;
readshows the choice but does not open;Only requiredmarks the button for assistive technology.
No groups, no clear button, no multiple choice (SearchMultiCombobox), no result limit or virtualisation, and no loading state.
Usage#
import {SearchCombobox} from '@workspace/active-ui/components/composed/search-combobox';
<SearchCombobox id="scheme" options={[{value: 'db-final', label: 'Final salary', keywords: 'DB'}]} value={scheme} // the option's value, or null onValueChange={setScheme} placeholder="Choose a scheme" searchLabel="Search schemes" searchPlaceholder="Search…" emptyText="No scheme found." locale="en"/>;What your application provides#
The complete list, with stable values and translated labels; the component filters it, so do not filter it as well.
The reader's language as
locale, every text translated, and the form binding.What
nullmeans for the field, and the validation.
Accessibility and keyboard#
The button is the field: name it with
FielditsLabel html For id;aria-anddescribedby aria-go to the button.invalid Enter,SpaceorArrowopen the menu; the search field is named byDown search.Label In the menu,
ArrowandUp Arrowmove through the hits,Down Enterchooses,Escapecloses and returns focus to the button.
API#
Import from @workspace/
Props
- Type
string
Text when the search returns nothing. Supplied translated.
- Type
string
The reader's language, for matching the query against labels.
Required, because matching is a language question: under es the query Espana does not find España (ñ is its own letter), under en it does. Without it Base UI's collator falls back to the runtime locale, which need not be the reader's language. Pass the locale the page already resolved.
- Type
readonly SearchCombobox Option[]
The complete, locally available option list. The component filters itself; the caller does not filter as well.
This component is not meant for options that must be searched server-side; see the notes on Search.
- Type
string
Text on the button while nothing is selected. Supplied translated.
- Type
string
Accessible name of the search field inside the menu. Supplied translated.
Required: the field has no visible label, and its placeholder is not a name. The caller owns the wording, so two pickers on one page can be told apart ("Search category", "Search participant").
- Type
string
Text in the search field inside the menu. Supplied translated.
- Type
string | null
The selected value, or null when nothing is selected.
- Type
boolean- Default
false
Shows the choice but ignores edits: the menu does not open and the value cannot change, while the button stays focusable and readable (unlike disabled, which takes it out of the tab order's meaning and greys it).
- Type
boolean- Default
false
Marks the choice as required for assistive technology. Validation itself stays with the caller's schema; this component does not block anything.
Events
Called by the component when something happens.
- Type
(value: string | null) => void
Receives the new value, or null.
null is part of the contract because an empty field is a valid state; what it means (uncategorised, no choice, validation error) is the caller's call.
Other props, such as the standard attributes of the underlying element, className and ref, are passed through.
Types
interface SearchComboboxOption {
value: string;
label: string;
disabled?: boolean;
keywords?: string;
}The props of Search, each described in its prop list on this page.
interface SearchComboboxProps extends Omit<
React.ComponentProps<'button'>,
'value' | 'defaultValue' | 'onChange' | 'children'
> {
options: readonly SearchComboboxOption[];
value: string | null;
onValueChange: (value: string | null) => void;
placeholder: string;
searchLabel: string;
searchPlaceholder: string;
emptyText: string;
locale: LocaleCode;
readOnly?: boolean;
required?: boolean;
}