What you get
tngMultiAutocomplete keeps query text, selected values, chips, and listbox state in sync without imposing a visual shell. You own the trigger, chip markup, overlay surface, and option content directly.
Installation
Primitive imports
ts
import {
TngMultiAutocomplete,
TngMultiAutocompleteTrigger,
TngMultiAutocompleteChip,
TngMultiAutocompleteContent,
TngMultiAutocompleteOverlay,
TngMultiAutocompleteListbox,
TngMultiAutocompleteOption,
} from '@tailng-ui/primitives';Basic usage
Headless attachment
html
<section
tngMultiAutocomplete
[open]="open()"
(openChange)="open.set($event)"
[query]="query()"
(queryChange)="query.set($event)"
[value]="selectedMarkets()"
(valueChange)="selectedMarkets.set(toValueArray($event))"
>
@for (code of selectedMarkets(); track code) {
<span tngMultiAutocompleteChip [tngValue]="code">{{ resolveMarketLabel(code) }}</span>
}
<input
tngMultiAutocompleteTrigger
type="text"
[value]="query()"
(input)="onInput($event)"
placeholder="Type Ind to filter"
aria-label="Launch markets"
/>
<div tngMultiAutocompleteContent class="contents">
<div tngMultiAutocompleteOverlay>
<ul tngMultiAutocompleteListbox [value]="selectedMarkets()">
@for (market of filteredMarkets(); track market.code) {
<li tngMultiAutocompleteOption [tngValue]="market.code">
{{ market.label }}
</li>
}
</ul>
</div>
</div>
</section>Style variants
The primitive contract stays the same whether you wrap it in a plain-CSS shell or a Tailwind shell.
Launch market tags (Plain-CSS)
Launch markets
Primitive-first shell with visible chips and an owned overlay surface.
Selected: India, Japan
Launch market tags (Tailwind CSS)
Launch markets
Primitive-first composition with a light shell and explicit chip treatment.
- CanadaNorth America
- GermanyEurope
- IndonesiaAsia Pacific
- IndiaAsia Pacific
- JapanAsia Pacific
- MexicoNorth America
- SpainEurope
Selected: Canada, Spain
Accessibility baseline
- The host owns the Tab stop and chips remain individually focusable for removal.
- The trigger query is separate from the selected values array, so filtering does not discard chips.
- Give the content wrapper its own class so copied plain-CSS examples can position it without depending on utility classes.