Combobox
Multi-select and tags input with creatable chips, async search and drag reorder.
npm install @devix-labs/combobox
A tags input and combobox on the @devix/select engine. Free text becomes chips on Enter, comma, Tab or paste; double-click a chip to fix it; drag chips into the order you mean; validate() cleans up or refuses text before it ever becomes a tag. Suggestions come from a list or your server, with folded matching for accents, Arabic and Urdu. The field never turns back into raw text, and the value posts with your form.
What you get
Chips you can fix
Double-click a chip and its text comes back into the field, selected, ready to correct.
Chips you can order
Drag them. The value follows and a change event is announced, so the order you see is the order you save.
Any separator, and paste
Enter, comma, Tab or your own. Pasting “design, urgent” makes two chips and leaves anything unfinished in the field.
validate() is the whole story
Return the value to keep or null to refuse it — trimming, casing, length and pattern rules with no extra UI. Duplicates never land twice.
Suggestions, local or remote
Folded matching for accents, Arabic and Urdu, keywords and descriptions; remote loading is debounced, aborted and cached.
10 KB, zero dependencies
Half of tagify, a third of a react-select Creatable page, and the same engine as Devix Select.
Combobox & Tags Input — overview
Why it exists
Tagging is where select widgets usually break: select2's field turns back into text on Backspace, react-select's Creatable is awkward to edit, Choices only creates on Enter, and tagify is 20 kB with a React wrapper that fights controlled components. All four are really one widget with the free-text switch turned on — so this is that widget, from an engine built for it.
What it does differently
- 10.0 kB gzip, no dependencies. Half of tagify.
- Chips you can fix. Double-click puts the text back in the field, selected.
- Chips you can order. Drag them; the value follows and a change is announced.
- Separators you choose. Enter, comma, Tab, or your own — and paste splits a list.
validate(text)is the whole validation story: return the value to keep, ornullto refuse.- The same search as
@devix/select: folded text for accents, Arabic and Urdu, keywords, descriptions, ranked and highlighted. - A real form value. A hidden input for plain forms,
name[]from the web component.
Shape of the package
| Entry | What |
|---|---|
@devix/combobox |
createCombobox, plus everything @devix/select exports |
@devix/combobox/react, /vue, /svelte, /element |
wrappers over the same core |
@devix/combobox/styles.css, /styles.layer.css |
the shared theme, plain or inside @layer devix |
Not in 1.0
Grouped chips, per-chip colours as a first-class option, and a "paste a CSV column" importer are Pro-edition shapes, not gaps in the free core.
Demos
All demos →Tags
Enter, comma or paste makes a chip. Double-click one to fix it, drag to reorder, Backspace to undo.
Validation
validate() cleans up what it keeps and refuses the rest — no extra UI, no invalid tag ever added.
Suggestions from your server
Type to search, pick from what comes back, or invent your own — debounced, aborted and cached.
How it compares
Questions
How does the value reach my server?
A hidden input keeps the tags comma-separated for a plain form post; the <dx-combobox> web component posts name[] repeated, like a multi-select. In JavaScript, getValue() returns an array.
Can I stop people typing anything they like?
Yes. validate(text) returns the value to keep or null to refuse it, so length, pattern and casing rules live in one place — and creatable: false turns free text off entirely, leaving a picker over your suggestions.
What happens to duplicates?
They are ignored: the same value never lands twice, whatever validate() returns.
Is this a separate widget from Devix Select?
No — it is the same engine with tag defaults, so everything in Select's docs about searching, theming, remote data and accessibility applies here too. Install whichever name matches what you are building.
Does it work with React's controlled components?
Yes. The wrapper renders a plain <input>, takes value and onChange, and writes through the native value setter, so React's change tracking never goes stale — the thing tagify's React wrapper has had open as issue #489.
More from Devix
All resources →Phone Input
UI component
International phone field with as-you-type formatting, validation and lazy per-country metadata.
Date Picker
UI component
Timezone-safe date picker with Hijri calendars, natural-language typing and a mobile sheet.
Date Range Picker
UI component
Ranges with presets, compare periods and multi-month views.