useCombobox
useCombobox owns a combobox's open state, value, input, highlight and ids. Components own the chrome: Field for the input, Popover, BottomSheet or Dialog for the surface, OptionList for the list. There is no Combobox.* export. The Combobox recipe shows single, multi, sheet, async and create.
presentation defaults to 'auto', which picks a sheet on a coarse pointer or a narrow viewport through useSheetPresentation. Force popover or sheet to keep it fixed, as the demo below forces popover. dialog puts the input and list in a Dialog, as the Command palette does. Composition lists which getter goes on which part.
When to use
When: Searchable select — typeahead + list. Hook owns open/value/input; Field + Popover/BottomSheet + OptionList own chrome, as the recipe shows. Auto sheet on coarse/narrow.
When not: Static on-page exclusive → Radio. Non-search list → usePopover + OptionList only. Action menu → Menu. Exporting Combobox.* chrome (forbidden).
Props
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| selectionMode | "single" | "multiple" | no | "single" | Single uses TextInput. Multiple uses ChipInput. |
| options | readonly ComboboxOption[] | no | — | Sync options. Ignored when loadOptions is set. |
| loadOptions | (query: string, signal: AbortSignal) => Promise<readonly ComboboxOption[]> | no | — | Async options. Stale responses are discarded. An inline function is fine; it is read at call time. |
| loadKey | string | number | no | — | Reloads options when it changes. Use it when loadOptions depends on state outside the query, such as a category. |
| presentation | "popover" | "sheet" | "dialog" | "auto" | no | "auto" | auto uses useSheetPresentation. dialog is for Dialog.Root, through getDialogProps. |
| allowCreate | boolean | no | false | Show a create row when the query has no case-insensitive label match. With loadOptions, the row waits until the load for that query settles. |
| value | string | null | readonly string[] | no | — | Controlled value. Null for empty single. Array for multiple. |
| open | boolean | no | — | Controlled open. |
| inputValue | string | no | — | Controlled filter text. |