---
name: combobox-usage
description: >
Use after component-usage-ux when an app needs @techsio/ui-kit Combobox for
searchable selection with Zag.js collection behavior, controlled value/input,
multiple mode, validation status, clear trigger, and token styling.
metadata:
component_version: "1.3.0"
type: "core"
library: "@techsio/ui-kit"
library_version: "0.3.2"
requires: "component-usage-ux app-token-overrides ux-guidelines"
sources: "libs/ui/src/molecules/combobox.tsx libs/ui/src/tokens/components/molecules/_combobox.css libs/ui/stories/molecules/combobox.stories.tsx libs/ui/src/molecules/combobox.figma.ts https://zagjs.com/components/react/combobox"
---
# @techsio/ui-kit Combobox Usage
Use Combobox for searchable select-like input. Use Select when search/filtering
is not needed.
## UX/UI guidelines
House rules come from the `ux-guidelines` skill (writing, formatting, states,
where actions and feedback live). This section applies them to `Combobox`.
**Use it when**
- Choosing one or more values from a long list where typing is the fastest way to find it (countries, customers, products, tags).
- Lists loaded asynchronously as the user types.
**Use something else when**
| Need | Use instead |
| --- | --- |
| Fewer than ~10 known options | Select (or RadioGroup for 2–5 visible options) |
| Search that navigates to pages/products | SearchSuggestions / SearchForm |
| Running app commands | Command |
| Hierarchical values | CascadeSelect |
**Do**
- Show a helpful empty state (`No customers match “nor”`) and, when allowed, a create option (`Create “Nora”`).
- Debounce remote search and show loading inside the listbox, not a page spinner.
- Keep selected values visible (tags for multiple) and removable by keyboard.
- Highlight the matched part of each option.
**Don't**
- Allow free text when the value must come from the list — validate or restrict.
- Open the list with hundreds of items before the user types; show recent or popular items instead.
**Copy and states**
- Placeholder is an example or instruction (`Search customers…`), never the label.
## Setup
```tsx
import { Combobox } from "@techsio/ui-kit/molecules/combobox"
```
Supported props:
```text
items: { id, label, value, disabled, data, href }[]
groups: { id, label?, items }[] (alternative to items; never pass both)
value/defaultValue: string | string[]
inputValue, multiple, clearable, closeOnSelect, allowCustomValue
validateStatus: default | error | success | warning
inputBehavior: autohighlight | autocomplete | none
onChange, onInputValueChange, onOpenChange
filterBehavior: local | external
loading, loadingMessage, error, onRetry, retryLabel, noResultsMessage
renderItem, footer, portalled (default true)
mode: selection | navigation (default selection)
navigate: Zag navigation callback for Enter and unmodified clicks
```
`onChange` receives Zag's selected value array, including in single selection.
Scalar `value` and `defaultValue` are normalized to arrays internally.
Use `SearchSuggestions` from `@techsio/ui-kit/templates/search-suggestions` for
grouped catalog navigation. It derives this API and chooses navigation defaults.
### Groups and Navigation
Group IDs and item values must be unique within the control. Unlabelled groups
are allowed; empty groups are omitted. Local filtering searches item labels;
external filtering displays exactly the supplied items.
`mode="navigation"` renders the option itself as an anchor using its `href`.
It preserves the query and does not expose selection or call `onChange`.
Disabled/read-only items omit href. `navigate` handles Enter and normal clicks;
modified clicks retain browser behavior. With no callback, navigation is native.
Keep routers in the consumer. Do not put links/buttons inside `renderItem`:
it customizes presentation within the existing option. The accessible name is
always `item.label`; include important identifying details in that label.
`footer` and retry controls sit outside the listbox. Use `portalled={false}` when
they need to follow the input in natural Tab order or the control is in a Dialog.
The default portal remains available for clipping-sensitive selection menus.
Status priority is loading, error, results, then empty (when a query is present).
Loading/error remove stale results from the keyboard collection.
## Core Patterns
### Use Combobox for search
Choose Combobox when the user needs to type and filter options. For short
static enum choices use Select, RadioGroup, or RadioCard.
### Keep items as collection data
Do not render a custom `