<u-combobox>
<u-combobox> extends <datalist> with support for multiselect, separate label and programmatic value and clear button. While these features are not yet part of any official ARIA pattern or HTML element, <u-combobox> adhere closely to HTML conventions.
Quick intro:
- Use
<data>as direct child elements - these are the removable items - Use
<input>as direct child and<u-datalist>to allow adding and suggesting items - Use
data-multipleto allow selecting multiple items - Use
data-creatableto allow creating items not in the list - Use
--sr-*CSS custom properties to translate screen reader texts - Use matching
idon<input>andforattribute on<label>to connect - Optionally use
<select>as child forFormDataor form submission compatibility - Optionally use
<button type="reset">afterinputto create a clear button - Optionally use
<button aria-expanded="false">afterinputto create a toggle button - Use
comboboxbeforeselect,comboboxafterselectandcomboboxbeforematchevents to manipulate state - MDN Web Docs: <data> (HTMLDataElement) / <input> (HTMLInputElement) / <datalist> (HTMLDatalistElement) / <option> (HTMLOptionElement)
Example
<label for="my-input">
Choose flavor of ice cream
</label>
<u-combobox data-multiple>
<data>Coconut</data>
<data>Banana</data>
<data>Pineapple</data>
<data>Orange</data>
<input id="my-input" list="my-list" />
<button type="button" aria-expanded="false"></button>
<button type="reset"></button>
<u-datalist hidden id="my-list" style="--sr-singular: '%d flavor'; --sr-plural: '%d flavours'">
<u-option>Coconut</u-option>
<u-option>Strawberries</u-option>
<u-option>Chocolate</u-option>
<u-option>Vanilla</u-option>
<u-option>Licorice</u-option>
<u-option>Pistachios</u-option>
<u-option>Mango</u-option>
<u-option>Hazelnut</u-option>
</u-datalist>
</u-combobox>
<style>
/* Styling just for example: */
u-combobox { border: 1px solid; display: flex; flex-wrap: wrap; gap: .5em; padding: .5em; position: relative }
u-option[selected] { font-weight: bold }
u-datalist { position: absolute z-index: 9; inset: 100% -1px auto; border: 1px solid; background: white; padding: .5em }
</style>
Install
npm add -S @u-elements/u-comboboxpnpm add -S @u-elements/u-comboboxyarn add @u-elements/u-comboboxbun add -S @u-elements/u-combobox<script type="module" src="https://unpkg.com/@u-elements/u-combobox@latest/dist/u-combobox.js"></script>Attributes and props
<u-combobox>
- Attributes: all global HTML attributes such as
id,class,data-data-multipleallows selecting multiple itemsdata-creatableallows creating items not in the list
- Screen reader texts: set through
--sr-*CSS custom properties - DOM interface:
UHTMLComboboxElementextendsHTMLElementUHTMLComboboxElement.controlreturnsHTMLInputElement | nullUHTMLComboboxElement.itemsreturnsHTMLCollectionOf<HTMLDataElement>UHTMLComboboxElement.listreturnsHTMLDataListElement | nullUHTMLComboboxElement.optionsreturnsHTMLCollectionOf<HTMLOptionElement>UHTMLComboboxElement.valuesreturnsstring[]withvalueof each item
<data>
- Attributes: all global HTML attributes such as
id,class,data-valueoptionally specify the machine-readable translation of the text content.
- DOM interface:
HTMLDataElementHTMLDataElement.valuestring reflecting thevalueHTML attribute.
Events
In addition to the usual events supported by HTML elements, the <u-combobox> elements dispatches custom events allowing you to affect state:
comboboxbeforeselect
myCombobox.addEventListener('comboboxbeforeselect', (event) => {
event.target // UHTMLComboboxElement
event.detail // HTMLDataElement to add or remove
event.detail.isConnected // true if removing, false if adding
event.preventDefault() // Optionally prevent action
})comboboxafterselect
myCombobox.addEventListener('comboboxafterselect', (event) => {
event.target // UHTMLComboboxElement
event.detail // HTMLDataElement added or removed
event.detail.isConnected // false if removing, true if adding
})comboboxbeforematch
Dispatched on Enter, and in single mode also on blur, when the input has text and a datalist is present. Never dispatched while typing, when empty input or when missing datalist. Hidden and disabled options are not matched. Prevent the event and set option.selected on all options to change or reject match.
myCombobox.addEventListener('comboboxbeforematch', (event) => {
event.target // UHTMLComboboxElement
event.detail // HTMLOptionElement | undefined match in option list
// You can change match by looping options and setting option.selected:
// for (const opt of event.target.options) opt.selected = your-condition-here;
})Styling
<u-combobox>renders asdisplay: block, while<data>renders asdisplay: inline-blockwith a::afterelement to render the removal×.- Customize or hide the removal
×via--x: ''on<u-combobox>; don’t change CSScontent, as this can break screen reader announcements - Style the wrapper around
<data>-elements can be styled using::part(items). <data>elements uses a::beforewithposition: absolutefor screen reader announcements- If
<button type="reset">is empty, a×renders with::before - If
<button aria-expanded="false"></button>is empty, a▼renders with::before
Screen reader texts
Screen reader texts are set through CSS custom properties. They inherit, so a translation can be set once for a page or a language, i.e. :lang(nb) { --sr-clear: "Tøm" }.
--sr-addedprefixes announcements about additions. Defaults to"Added"--sr-removedprefixes announcements about removals. Defaults to"Removed"--sr-removeannounces ability to remove. Defaults to"Press to remove"--sr-emptyannounces no selected items. Defaults to"No selected"--sr-foundannounces where to find amount of selected items. Defaults to"Navigate left to find %d selected"--sr-invalidannounces if trying to select invalid value. Defaults to"Invalid value"--sr-itemsaria-label for listbox containing selected items. Defaults to"Selected"--sr-clearname of clear button. Defaults to"Clear input"--sr-togglename of toggle list button. Defaults to"Options"--sr-singularand--sr-pluralannounce hits, see<u-datalist>
Note:
If you are using a strict Content Security Policy (CSP), inline style HTML attributes are blocked. Set the properties in your CSS, or through element.style.setProperty('--sr-clear', '"New string"') (note that the string must be quoted) or a framework style binding.
Example: Norwegian
<label for="my-norwegian-input">
Velg type iskrem
</label>
<u-combobox id="my-norwegian">
<data>Kokkos</data>
<input id="my-norwegian-input" list="my-norwegian-list" />
<button type="button" aria-expanded="false"></button>
<button type="reset"></button>
<u-datalist hidden id="my-norwegian-list">
<u-option>Kokkos</u-option>
<u-option>Jordbær</u-option>
<u-option>Sjokolade</u-option>
<u-option>Vanilje</u-option>
<u-option>Lakris</u-option>
<u-option>Pistasj</u-option>
<u-option>Mango</u-option>
<u-option>Hasselnøtt</u-option>
</u-datalist>
</u-combobox>
<style>
/* Screen reader texts inherit, so they also apply to the u-datalist inside. Set them on :root or :lang() to translate a whole page */
#my-norwegian {
--sr-added: "La til";
--sr-clear: "Fjern tekst";
--sr-empty: "Ingen valgte";
--sr-found: "Naviger til venstre for å finne %d valgte";
--sr-invalid: "Ugyldig verdi";
--sr-items: "Valgte";
--sr-plural: "%d smaker";
--sr-remove: "Trykk for å fjerne";
--sr-removed: "Fjernet";
--sr-singular: "%d smak";
--sr-toggle: "Valg";
}
/* Styling just for example: */
u-combobox { border: 1px solid; display: flex; flex-wrap: wrap; gap: .5em; padding: .5em; position: relative }
u-option[selected] { font-weight: bold }
u-datalist { position: absolute; z-index: 9; inset: 100% -1px auto; border: 1px solid; background: white; padding: .5em }
</style>
Example: Custom matching
<label for="my-matching-input">
Matches from start of word
</label>
<br>
<small>Try typing "c" and hitting "Enter"</small>
<u-combobox id="my-matching-combobox">
<input id="my-matching-input" list="my-matching-list" />
<button type="button" aria-expanded="false"></button>
<button type="reset"></button>
<u-datalist id="my-matching-list">
<u-option>Coconut</u-option>
<u-option>Strawberries</u-option>
<u-option>Chocolate</u-option>
<u-option>Vanilla</u-option>
</u-datalist>
</u-combobox>
<script type="module">
const combobox = document.getElementById('my-matching-combobox');
combobox.addEventListener('comboboxbeforematch', (event) => {
event.preventDefault();
const input = combobox.control;
const query = input.value.toLowerCase().trim();
for(const opt of input.list.options) {
opt.selected = !!query && opt.label.toLowerCase().trim().startsWith(query);
}
});
</script>
<style>
/* Styling just for example: */
u-combobox { border: 1px solid; display: flex; flex-wrap: wrap; gap: .5em; padding: .5em; position: relative }
u-option[selected] { font-weight: bold }
u-datalist { position: absolute; z-index: 9; inset: 100% -1px auto; border: 1px solid; background: white; padding: .5em }
</style>
Example: Custom filtering
Notice: <u-datalist> has data-nofilter to allow custom filtering
<label for="my-filtering-input">
Filters case sensitive
</label>
<br>
<small>Try typing "v" versus "V"</small>
<u-combobox id="my-filtering-combobox">
<input id="my-filtering-input" list="my-filtering-list" />
<button type="button" aria-expanded="false"></button>
<button type="reset"></button>
<u-datalist hidden data-nofilter id="my-filtering-list">
<u-option>Coconut</u-option>
<u-option>Strawberries</u-option>
<u-option>Chocolate</u-option>
<u-option>Vanilla</u-option>
</u-datalist>
</u-combobox>
<script type="module">
const combobox = document.getElementById('my-filtering-combobox');
combobox.addEventListener('input', (event) => {
event.preventDefault();
const input = combobox.control;
const query = input.value.trim();
for(const opt of input.list.options) {
opt.hidden = !!query && !opt.label.trim().includes(query);
}
});
</script>
<style>
/* Styling just for example: */
u-combobox { border: 1px solid; display: flex; flex-wrap: wrap; gap: .5em; padding: .5em; position: relative }
u-option[selected] { font-weight: bold }
u-datalist { position: absolute; z-index: 9; inset: 100% -1px auto; border: 1px solid; background: white; padding: .5em }
</style>
Example: API results
<label for="my-api-input">
Search for a recipe
</label>
<u-combobox id="my-api-combobox">
<input id="my-api-input" list="my-api-list" />
<button type="button" aria-expanded="false"></button>
<button type="reset"></button>
<u-datalist hidden id="my-api-list" data-nofilter>
<u-option value="">Type to search...</u-option>
</u-datalist>
</u-combobox>
<script type="module">
const combobox = document.getElementById('my-api-combobox');
const xhr = new XMLHttpRequest(); // Easy to abort
let debounceTimer; // Debounce so we do not spam API
// Same handler every time
xhr.addEventListener('load', () => {
const list = combobox.control.list;
try {
list.replaceChildren(...JSON.parse(xhr.responseText).recipes.map((recipe) => {
const option = document.createElement('u-option');
option.text = recipe.name;
return option;
}));
} catch (err) {
list.innerHTML = '<u-option value="">No results</u-option>';
}
});
combobox.addEventListener('input', (event) => {
const { list, value } = combobox.control;
const query = encodeURIComponent(value.trim());
list.innerHTML = query ? '<u-option value="">Loading</u-option>' : '';
xhr.abort();
clearTimeout(debounceTimer);
if (query) {
debounceTimer = setTimeout(() => {
xhr.open('GET', `https://dummyjson.com/recipes/search?q=${query}`, true);
xhr.send();
}, 600);
}
});
</script>
<style>
/* Styling just for example: */
u-combobox { border: 1px solid; display: flex; flex-wrap: wrap; gap: .5em; padding: .5em; position: relative }
u-option[selected] { font-weight: bold }
u-datalist { position: absolute; z-index: 9; inset: 100% -1px auto; border: 1px solid; background: white; padding: .5em }
</style>
Example: Only filter during typing
<label for="my-typing-input">
All results will be visible on load and after selection:
</label>
<u-combobox id="my-typing-combobox">
<input id="my-typing-input" list="my-typing-list" />
<button type="button" aria-expanded="false"></button>
<button type="reset"></button>
<u-datalist hidden id="my-typing-list" data-nofilter>
<u-option>Coconut</u-option>
<u-option>Strawberries</u-option>
<u-option>Chocolate</u-option>
<u-option>Vanilla</u-option>
</u-datalist>
</u-combobox>
<script type="module">
const combobox = document.getElementById('my-typing-combobox');
combobox.addEventListener('input', (event) => {
// Only user can cause trusted typing events
combobox.list.toggleAttribute('data-nofilter', !event.isTrusted);
});
</script>
<style>
/* Styling just for example: */
u-combobox { border: 1px solid; display: flex; flex-wrap: wrap; gap: .5em; padding: .5em; position: relative }
u-option[selected] { font-weight: bold }
u-datalist { position: absolute; z-index: 9; inset: 100% -1px auto; border: 1px solid; background: white; padding: .5em }
</style>
Example: Creatable
<label for="my-creatable-input">
Type a new item:
</label>
<u-combobox id="my-creatable-combobox" data-creatable data-multiple>
<input id="my-creatable-input" list="my-creatable-list" />
<button type="button" aria-expanded="false"></button>
<button type="reset"></button>
<u-datalist hidden id="my-creatable-list">
<u-option value="https://u-elements.github.io/u-elements/elements/u-datalist">u-datalist</u-option>
<u-option value="https://u-elements.github.io/u-elements/elements/u-progress">u-progress</u-option>
<u-option value="https://u-elements.github.io/u-elements/elements/u-details">u-details</u-option>
<u-option value="https://u-elements.github.io/u-elements/elements/u-combobox">u-combobox</u-option>
<u-option value=""></u-option>
</u-datalist>
</u-combobox>
<script type="module">
const combobox = document.getElementById('my-creatable-combobox');
const handleAddButton = () => {
const value = combobox.control.value.trim();
const options = combobox.list.options;
const add = options[options.length - 1];
add.hidden = !value || combobox.values.includes(value);
add.value = value;
add.label = value;
add.textContent = `Add "${value}"`
};
combobox.addEventListener('comboboxafterselect', handleAddButton);
combobox.addEventListener('input', handleAddButton);
</script>
<style>
/* Styling just for example: */
u-combobox { border: 1px solid; display: flex; flex-wrap: wrap; gap: .5em; padding: .5em; position: relative }
u-option[selected] { font-weight: bold }
u-datalist { position: absolute; z-index: 9; inset: 100% -1px auto; border: 1px solid; background: white; padding: .5em }
</style>
Example: Links
<label for="my-link-input">
Click on a result:
</label>
<u-combobox id="my-link-combobox">
<input id="my-link-input" list="my-link-list" />
<button type="button" aria-expanded="false"></button>
<button type="reset"></button>
<u-datalist hidden id="my-link-list">
<u-option value="https://u-elements.github.io/u-elements/elements/u-datalist">u-datalist</u-option>
<u-option value="https://u-elements.github.io/u-elements/elements/u-progress">u-progress</u-option>
<u-option value="https://u-elements.github.io/u-elements/elements/u-details">u-details</u-option>
<u-option value="https://u-elements.github.io/u-elements/elements/u-combobox">u-combobox</u-option>
</u-datalist>
</u-combobox>
<script type="module">
const combobox = document.getElementById('my-link-combobox');
combobox.addEventListener('click', (event) => {
const { ctrlKey, metaKey, target } = event;
const option = target instanceof Element && target.closest('u-option');
if (option) {
event.preventDefault(); // Prevent filling input
if (ctrlKey || metaKey) window.open(option.value);
else window.location.href = option.value;
}
});
</script>
<style>
/* Styling just for example: */
u-combobox { border: 1px solid; display: flex; flex-wrap: wrap; gap: .5em; padding: .5em; position: relative }
u-option[selected] { font-weight: bold }
u-datalist { position: absolute; z-index: 9; inset: 100% -1px auto; border: 1px solid; background: white; padding: .5em }
</style>
Example: React controlled render
u-combobox adds and removes <data> elements, which can be confusing for frameworks such as React.
If you encounter issues, it’s recommended to call event.preventDefault() inside the comboboxbeforeselect handler,
and then manually add or remove <data> elements as needed:
<label for="my-controlled-input">
Controlled render:
</label>
<u-combobox id="my-controlled-combobox" data-multiple>
<!--
Your framework rendering here, i.e. React:
{values.map(({ value, label }) => (
<data key={value} value={value}>
{label}
</data>
))}
-->
<input id="my-controlled-input" list="my-controlled-list" />
<button type="button" aria-expanded="false"></button>
<button type="reset"></button>
<u-datalist hidden id="my-controlled-list">
<u-option>Coconut</u-option>
<u-option>Strawberries</u-option>
<u-option>Chocolate</u-option>
<u-option>Vanilla</u-option>
</u-datalist>
</u-combobox>
<script type="module">
const combobox = document.getElementById('my-controlled-combobox');
const [values, setValues] = useState([]);
combobox.addEventListener('comboboxbeforeselect', (event) => {
event.preventDefault(); // Stops u-combobox
const data = event.detail;
const label = data.textContent;
const value = data.value;
const isAdd = !data.isConnected;
// Add/remove:
if (isAdd) setValues([...values, { label, value }]);
else setValues(values.filter((item) => item.value !== value));
});
</script>
<style>
/* Styling just for example: */
u-combobox { border: 1px solid; display: flex; flex-wrap: wrap; gap: .5em; padding: .5em; position: relative }
u-option[selected] { font-weight: bold }
u-datalist { position: absolute; z-index: 9; inset: 100% -1px auto; border: 1px solid; background: white; padding: .5em }
</style>
Accessibility
| Screen reader | <u-combobox> |
|---|---|
| VoiceOver (Mac) + Chrome | ✅ |
| VoiceOver (Mac) + Edge | ✅ |
| VoiceOver (Mac) + Firefox | ✅ |
| VoiceOver (Mac) + Safari | ✅ |
| VoiceOver (iOS) + Safari | ✅ |
| Jaws (PC) + Chrome | ✅ |
| Jaws (PC) + Edge | ✅ |
| Jaws (PC) + Firefox | ✅ |
| NVDA (PC) + Chrome | ✅ |
| NVDA (PC) + Edge | ✅ |
| NVDA (PC) + Firefox | ✅ needs focus mode to announce item removal |
| Narrator (PC) + Chrome | ⚠️ Needs "scanning off" mode |
| Narrator (PC) + Edge | ⚠️ Needs "scanning off" mode |
| Narrator (PC) + Firefox | ⚠️ Needs "scanning off" mode |
| TalkBack (Android) + Chrome | ✅ |
| TalkBack (Android) + Firefox | ✅ |
| TalkBack (Android) + Samsung Internet | ✅ |
Specifications
- DOM interface: HTMLElement
- HTML Standard: The <div> element
- DOM interface: HTMLDataElement
- HTML Standard: The <data> element
Server side rendering
You can server side render <u-combobox> by using Declarative Shadow DOM.
Styling and markup needed is exported as UHTMLComboboxShadowRoot. Example:
import { UHTMLComboboxShadowRoot } from '@u-elements/u-combobox';
import { UHTMLDataListShadowRoot } from '@u-elements/u-datalist';
const renderToStaticMarkup = (data: string, options: string) =>
`<label for="my-ssr-input">Server side rendered</label>
<u-combobox>
${UHTMLComboboxShadowRoot}
${data}
<input id="my-ssr-input" />
<u-datalist>
${UHTMLDataListShadowRoot}
${options}
</u-datalist>
</u-combobox>`Hydration: Attributes are dynamically added in the browser, so the client DOM will differ from the server markup. Use suppressHydrationWarning in React, data-allow-mismatch="attribute" in Vue, or similar for your framework on these elements, to avoid hydration warnings.
Notes
<datalist>or<u-datalist>must be a child of<u-combobox>. Thelistattribute on<input>is managed automatically- Without a datalist, single mode is free text: the input is never overwritten, blur does nothing, and
Enteronly creates an item whendata-creatableis set. The item is removed through the clear button - Single mode acts on the first
<data>only - The toggle button is hidden when using native
<datalist>, as the native suggestion popup can not be detected programmatically - In controlled mode,
changeis dispatched by the input sync that follows the<data>change. A deferred render (i.e. ReactstartTransition, a debounced state update) still dispatcheschangewhen it renders the item the user picked or matched. On blur, the input shows the previous item until the deferred render lands, as a prevented match can not be told apart from a deferred one - ARC Toolkit incorrectly reports
aria-descriptionas an invalid ARIA-attribute - ARC Toolkit does not correctly read the relation between items with
role="option"and the ShadowDOM wrapping containerrole="listbox" - See full behavior spec in u-combobox source
Changelog
- 3.0.0: Framework compatibility and matching changes
- How to upgrade:
- Update
@u-elements/u-datalistto 3.0.0 or newer - Ensure
<input>is a direct child of<u-combobox> - Ensure clear button is a
<button type="reset"></button> - Replace
data-sr-*attributes with--sr-*CSS custom properties - Remove
comboboxprogrammaticinputlisteners - the event is removed
- Update
- Single mode:
- Important: No longer matches while typing, only on
Enterand blur Enterno longer reverts text on match; text is kept until blurinput.valueis only synced to the<data>if a datalist is presentvaluesreturns at most one value, matching the mirrored<data>- Mirrors only the first
<data>into<select>, so submitted value matches the input
- Important: No longer matches while typing, only on
- Multiple mode:
Enteronly adds. A matched option that is already an item is kept, as removal is intended through a pick or an explicit item removal
- Changes in both single and multiple mode:
- Better support for async rendering and events in frameworks
- Better performance when frameworks syncs attributes
changeis only dispatched when the input sync follows a user commit (option pick,Enter, blur, clear or item removal), never on mount, programmatic<data>changes or form reset, aligning with conventions from other native elementsEntermatch onkeyupinstead ofkeydownto support native datalist in Safari- A prevented
keydownis respected, so a preventedEnternever matches form.reset()syncs the clear and toggle buttons- Toggle button is hidden when the input is
disabledorreadonly - Firefox spell check and autofill are not seen as option-picks
- Synthetic
InputEvent(i.e. testing-library) does not cause incorrect option click - Framework typings for Qwik 1, Qwik 2 and Preact 11 uses
HTMLElementTagNameMap
- How to upgrade:
- 2.1.5: Fix state handling when mode is multiple and controlled (i.e. React)
- 2.1.4: Fix internal state when preventing a selection or setting value programmatically
- 2.1.3: Fix issue where item behind datalist could receive focus
- 2.1.2: Prevent unnecessary matching after option
clickin single mode - 2.1.1: Fix support for rendering without datalist
- 2.1.0: Add support for toggle button and prevent horizontal scroll on items
- 2.0.5: Fix issue where VoiceOver is confused by display: contents on selected listbox
- 2.0.4: Fix issue when moving focus between multiple u-combobox inputs
- 2.0.3: Use document.activeElement instead of .matches(":focus-within") for JSDOM testing compatibility
- 2.0.2: Respect existing aria-label on clear button
- 2.0.1: Fix single mode value sync for React users
- 2.0.0: Plays nice with strict CSP and with axe tests, and uses
u-datalist@2.0.0 - 1.0.7: Fixes so display: flex on u-combobox renders as expected
- 1.0.6: Fixes FormsMode compatibility for JAWS and NVDA
- 1.0.5: Allow clicks even when
ctrlKey,altKeyorshiftKey - 1.0.4: Prevent focus trap on Safari caused by
tabindex="-1"on<del> - 1.0.3: Let
Deletekey do native text deletion instead of chip removal - 1.0.2: Fix sync issue when single mode and deleting
<data>element - 1.0.1: Support setting
aria-labelon input and enable declarative shadow root support and exportUHTMLComboboxShadowRootfor easier server side rendering - 1.0.0: Renamed events to avoid conflict with native events:
afterchange=>comboboxafterselectbeforechange=>comboboxbeforeselectbeforematch=>comboboxbeforematch- 0.0.20: Clean up unused comma from
aria-labelwhen single mode - 0.0.19: Respects input
disabledandreadonlyand moves caret to end of text onarrow up - 0.0.18: Input value is now reverted instead of cleared when no match on blur/enter
- 0.0.17: Input now gets new
listattributeidofdatalistchanges - 0.0.15: Sync input value when data-elements change and only trigger
beforechangeandafterchangeon click, enter or blur, but not while typing in single mode - 0.0.14: Fix issue where removing single element programmatically caused focus
- 0.0.13: Update sync state when options are changed
- 0.0.12: Always sync
<del>with input value on mount - 0.0.11: Improved performance
- 0.0.10: Only remove
<data>during change event for React compatiliby - 0.0.9: Improve browser compatibility by avoiding
toggleAttribute - 0.0.8: Avoid hiding
<del>when clicking option withoutvalue - 0.0.7: Add support for
<del>element to clear the input - 0.0.6: Ensure correct value of hidden
<select> - 0.0.5: Prevent
inputvalue change whenbeforechangeis prevented - 0.0.4: Bugfix
- 0.0.3: Prevent add if
u-optionhas empty value attribute - 0.0.2: Reset value when clicking option in multiple mode
- 0.0.1: Support async
u-optioninitialization - 0.0.0: Beta release