--- 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 `