- ds
- Components
- Combobox and tags
Combobox and tags
Type to filter, pick many, remove with a click.
Combobox
Code
<div class="combo">
<div class="inp-group">
<svg class="i">…</svg>
<input class="inp mono" role="combobox" aria-expanded="true" aria-controls="cb-list" aria-autocomplete="list" aria-activedescendant="cb-1" />
</div>
<div class="menu" role="listbox" id="cb-list">
<div class="mi" role="option" id="cb-0" aria-selected="true"><span><mark>order</mark>s</span></div>
<div class="mi" role="option" id="cb-1" data-active><span><mark>order</mark>_items</span></div>
</div>
</div>An input that filters a list. It reuses the menu surface and items, opened under the input at the same width. The matching part of each option is in the accent; the chosen one gets a check. Focus stays in the input the whole time: arrow keys move aria-activedescendant, Enter picks, Escape closes.
Tags
Enter or comma adds a label. Backspace in an empty field removes the last one.
Code
<label class="fld" for="ti"><span>Labels</span></label>
<div class="tags-input" id="tags">
<span class="chip">team:data<button class="rm" type="button" aria-label="Remove team:data"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg></button></span>
<span class="chip">env:prod<button class="rm" type="button" aria-label="Remove env:prod"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg></button></span>
<span class="chip warm">pii<button class="rm" type="button" aria-label="Remove pii"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg></button></span>
<input id="ti" placeholder="Add a label" autocomplete="off" />
</div>
<span class="hint">Enter or comma adds a label. Backspace in an empty field removes the last one.</span>Chips and a bare input in one frame that looks and focuses like an .inp. Each chip has a remove button with its own label. Use .warm chips for values that mark data, such as PII.
Filter chips
status: failed
owner: priya
Code
<div class="chips">
<span class="chip on">status: failed<button class="rm" type="button" aria-label="Clear status filter"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg></button></span>
<span class="chip on">owner: priya<button class="rm" type="button" aria-label="Clear owner filter"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg></button></span>
<button class="chip" type="button"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="M5 12h14"/><path d="M12 5v14"/></svg>Add filter</button>
</div>Active filters above a table are the same chip with .on. The remove button sits inside the chip, so the chip itself can still open an editor for that filter.
API
| Class | On | What it does |
|---|---|---|
.combo | div | Wraps the input and positions the .menu under it at full width. |
[role=option] | .mi | An option. aria-selected="true" adds the check; data-active marks the keyboard position. |
mark | .mi | The part of the option that matches the query. |
.menu-empty | p | Shown in the menu when nothing matches. |
.tags-input | div | Chips and a bare <input> in one frame. |
.rm | button in .chip | The remove button. Needs an aria-label. |
Do
- A combobox past about ten options, a select below.
- Say what happens with no match: "No table named ordrs. Create it?"
- Keep typed text when the menu closes.
Don't
- Autoselecting the first match on blur.
- Tags without a remove button.
- Free text in a field that only accepts known values.
Accessibility
- The input has
role="combobox",aria-expandedandaria-controls; the list hasrole="listbox". Focus never leaves the input. - Announce the result count in a polite live region when it changes: "3 tables".