Skip to content

TkxComboBox

A multi-select combobox: selected values render as removable token chips before the text input, typing filters the option list, and selecting keeps the list open so you can pick several values in a row. Built for recipients, tags, and filter pickers.

Same accessible label / hint / error / isRequired chrome as TkxInput.

import { TkxComboBox } from 'tekivex-ui';
<TkxComboBox
label="Tags"
placeholder="Add tags…"
options={[
{ value: 'bug', label: 'Bug' },
{ value: 'docs', label: 'Docs' },
{ value: 'perf', label: 'Performance' },
]}
onChange={(values, selected) => console.log(values, selected)}
/>

value (a string[]) makes the selection controlled; defaultValue seeds an uncontrolled one. onChange always receives both the value array and the matching option objects.

const [tags, setTags] = useState<string[]>([]);
<TkxComboBox label="Tags" options={options} value={tags} onChange={setTags} />

maxSelected caps how many values can be picked. Once the cap is reached the remaining options are visibly muted, marked aria-disabled, and cannot be selected — but already-selected options stay interactive so they can be deselected.

<TkxComboBox label="Assignees" options={people} maxSelected={3} />

Pass name to render a hidden input that joins the selected values with ,, so the component works in a plain <form> post without JavaScript glue.

<TkxComboBox label="Categories" name="categories" options={categories} />
// posts: categories=bug,docs

Focus stays on the text input the whole time — the active option is conveyed via aria-activedescendant, not roving DOM focus.

KeyAction
TypeFilters options (case-insensitive substring) and opens the list.
ArrowDown / ArrowUpMove the active option; disabled options are skipped.
EnterToggles the active option. The list stays open (multi-select convention) and the query is cleared.
EscapeCloses the list.
Backspace (empty input)Removes the last chip.

Each chip’s remove control is a real <button> labelled Remove <label>. Clicking outside closes the list.

<TkxComboBox label="Recipients" isRequired error="Pick at least one recipient" />

error sets aria-invalid, renders a role="alert" message, and links it via aria-describedby — the same wiring as TkxInput.

PropTypeDefaultDescription
labelstringRequired. Accessible label.
optionsComboBoxOption[][]{ value, label, disabled? } items. Safe to omit — a bare mount renders an empty list.
valuestring[]Controlled selection.
defaultValuestring[]Uncontrolled initial selection.
onChange(values: string[], selectedOptions: ComboBoxOption[]) => voidFires on every selection change.
placeholderstringShown while nothing is selected.
hintstringHelper text below the field.
errorstringError message; sets aria-invalid + role="alert".
isInvalidbooleanfalseForce the invalid style without an error string.
isRequiredbooleanfalseAdds aria-required + asterisk.
disabledbooleanfalseDisables the input and chip removal.
clearablebooleantrueShow a “Clear all” affordance when something is selected.
maxSelectednumberCap the number of selected values.
idstringautoId for the inner input (label association).
namestringRenders a hidden input with comma-joined values for form posts.
className / styleApplied to the outer wrapper.

The component forwards its ref to the inner <input>.