KANTO DS v1.12.0
Customise

Theme

Accent

Font

Corners

Density

Text size

Reset to Kanto
Forms

kt-multi-select

GitHub Copy link

Several choices from a list: type to narrow it, pick as many as you need.

Preview

Several choices from a list: type to narrow it, pick as many as you need.

<kt-multi-select label="Regions" placeholder="Any region"></kt-multi-select>select.options = [ { id: 'ne', label: 'North East' }, { id: 'sw', label: 'South West' }, { id: 'nw', label: 'North West' }, ]; select.value = ['ne']; select.addEventListener('kt-change', (e) => filter(e.detail.value));

Against the alternatives

Reach for it when a filter takes several values from a list long enough to search — regions, owners, tags. For two or three options that all fit on screen, a <kt-toggle-button-group multiple> shows them without a click. For one value, <kt-input-menu> or <kt-select>.

One line, whatever is chosen

Each choice shows in the field as a chip: a fill set into the field, the same distance from its top, bottom and left edge, with its own remove button — the family of a chosen option, not an outlined tag. The field keeps to one line: the chips that do not fit collapse into a quiet +N beside the ones that do, or into "3 selected" when not one fits, so the field sits in a row of filters without changing its height. The open list shows every option, the chosen ones ticked — which is where the hidden ones can be seen and taken out. Widen the field and more chips come back.

Choosing

The list stays open after each choice, since the point is to make several. Clicking a chosen option, or pressing Enter on it, takes it out again; the order of value is the order things were chosen. Disabled options can be seen but not chosen.

kt-change fires with the whole new value and the matching options, not the one that changed: a filter usually wants the full set.

Server-side filtering

kt-filter fires on every keystroke, as on <kt-input-menu>: assign the results to options and the list follows. Chosen values stay chosen while their options are filtered out — a chip whose option is no longer in options shows its id.

select.addEventListener('kt-filter', async (e) => { select.options = await search(e.detail.query); });

In a form

A form control, submitted like <select multiple>: one entry per chosen id under name, and nothing at all while empty — read them with formData.getAll(name). required blocks submission until at least one value is chosen, form.reset() puts back the values it started with, and a <fieldset disabled> disables it.

Accessibility

The field is an ARIA combobox over a listbox marked aria-multiselectable, each option aria-selected when chosen. The number chosen is part of the field's description ("2 selected"), since the chips may not all be visible. Each chip's remove button is named after it — "Remove North East".

Keyboard

KeyDoes
↓ / ↑Opens the list, then moves the active option
Home / EndFirst / last match
EnterAdds or removes the active option; the list stays
BackspaceIn an empty field, removes the last chip
EscapeCloses and forgets the query, keeping every choice
TabCloses and moves on

API

PropertyAttributeTypeDefault
options—KtOption[][]
value—(string | number)[][]
placeholderplaceholderstring''
namenamestring''
disableddisabledbooleanfalse
requiredrequiredbooleanfalse
errorerrorstring''
labellabelstring''
emptyTextempty-textstring'No options…'

selectedOptions (read-only) is the chosen options, in the order chosen.

EventDetail
kt-change{ value, options }
kt-filter{ query: string }
PartDescription
controlThe field
chipsThe row of chips
inputThe native <input>
popupThe option list
optionAn option row