A form-associated combobox built on m-listbox and m-search-list
Basic Usage
Code
<form class="form">
<m-combobox name="fruit" label="Choose a fruit">
<m-option value="apple">Apple</m-option>
<m-option value="pear">Pear</m-option>
<m-option value="orange">Orange</m-option>
<m-option value="banana">Banana</m-option>
<m-option value="grape">Grape</m-option>
<m-option value="mango">Mango</m-option>
</m-combobox>
</form> Form Participation
Code
<form id="fruit-form" class="form">
<m-combobox name="favorite-fruit" label="Favorite fruit">
<m-option value="apple">Apple</m-option>
<m-option value="pear">Pear</m-option>
<m-option value="orange">Orange</m-option>
<m-option value="banana">Banana</m-option>
</m-combobox>
<div id="form-result" class="box" data-variant="surface" data-span="2">
<strong>Form Data:</strong>
<pre id="form-result-text" style="margin: 0.5rem 0 0 0;"></pre>
</div>
<button type="submit">Submit</button>
<button type="reset">Reset</button>
</form>
<script>
const form = document.getElementById('fruit-form');
const resultText = document.getElementById('form-result-text');
form.addEventListener('submit', (e) => {
e.preventDefault();
const data = Object.fromEntries(new FormData(form));
resultText.textContent = JSON.stringify(data, null, 2);
});
</script> Selection Modes
Code
<div class="form">
<m-combobox name="single" label="Single select">
<m-option value="red">Red</m-option>
<m-option value="green">Green</m-option>
<m-option value="blue">Blue</m-option>
</m-combobox>
<m-combobox name="multiple" label="Multiple select" multiple>
<m-option value="red">Red</m-option>
<m-option value="green">Green</m-option>
<m-option value="blue">Blue</m-option>
<m-option value="yellow">Yellow</m-option>
</m-combobox>
</div> Pre Selected Values
Code
<div class="form">
<m-combobox name="selected-attr" label="Using selected attribute">
<m-option value="apple">Apple</m-option>
<m-option value="pear" selected>Pear</m-option>
<m-option value="orange">Orange</m-option>
</m-combobox>
<m-combobox name="value-attr" label="Using value attribute" value="orange">
<m-option value="apple">Apple</m-option>
<m-option value="pear">Pear</m-option>
<m-option value="orange">Orange</m-option>
</m-combobox>
</div> Clearable Input
Code
<div class="form">
<m-combobox
name="clearable-example"
label="Clearable combobox (default)"
value="orange"
>
<m-option value="apple">Apple</m-option>
<m-option value="orange">Orange</m-option>
<m-option value="pear">Pear</m-option>
</m-combobox>
<m-combobox
name="not-clearable"
label="Not clearable"
value="pear"
clearable="false"
>
<m-option value="apple">Apple</m-option>
<m-option value="orange">Orange</m-option>
<m-option value="pear">Pear</m-option>
</m-combobox>
</div> Disabled State
Code
<div class="form">
<m-combobox name="disabled" label="Disabled combobox" disabled>
<m-option value="apple">Apple</m-option>
<m-option value="pear" selected>Pear</m-option>
<m-option value="orange">Orange</m-option>
</m-combobox>
<m-combobox name="partial-disabled" label="Disabled options">
<m-option value="apple">Apple</m-option>
<m-option value="pear" disabled>Pear (disabled)</m-option>
<m-option value="orange">Orange</m-option>
</m-combobox>
</div> Validation
Code
<form id="validation-form" class="form">
<m-combobox name="country" label="Country (required)" required>
<m-option value="us">United States</m-option>
<m-option value="uk">United Kingdom</m-option>
<m-option value="ca">Canada</m-option>
<m-option value="au">Australia</m-option>
</m-combobox>
<div id="validation-output" class="box" data-variant="surface" data-span="2">
<strong>Validation Status:</strong>
<pre id="validation-text" style="margin: 0.5rem 0 0 0;">Not yet validated</pre>
</div>
<button type="submit">Submit</button>
<button type="reset">Reset</button>
</form>
<script>
const validationForm = document.getElementById('validation-form');
const combobox = document.querySelector('[name="country"]');
const validationText = document.getElementById('validation-text');
combobox.addEventListener('m-invalid', (e) => {
validationText.textContent = `Invalid: ${e.detail.validationMessage}`;
validationText.style.color = 'var(--color-destructive-fill-mid)';
});
combobox.addEventListener('change', () => {
if (combobox.value) {
validationText.textContent = `Valid: "${combobox.value}" selected`;
validationText.style.color = 'var(--color-success-fill-mid)';
}
});
validationForm.addEventListener('submit', (e) => {
e.preventDefault();
validationText.textContent = 'Form submitted successfully!';
validationText.style.color = 'var(--color-success-fill-mid)';
});
</script> Events
Event Log:
Code
<div class="stack" data-gap="2">
<m-combobox id="event-combobox" name="event-example" label="Select fruits" multiple>
<m-option value="apple">Apple</m-option>
<m-option value="pear">Pear</m-option>
<m-option value="orange">Orange</m-option>
<m-option value="banana">Banana</m-option>
</m-combobox>
<div id="event-log" class="box" data-variant="surface">
<strong>Event Log:</strong>
<ul id="event-log-list" style="margin: 0.5rem 0 0 0; padding-left: 1.5rem; max-height: 200px; overflow-y: auto;"></ul>
</div>
</div>
<script>
const eventCombobox = document.getElementById('event-combobox');
const eventLogList = document.getElementById('event-log-list');
function logEvent(message, color = 'var(--color-neutral-fill-mid)') {
const li = document.createElement('li');
li.textContent = message;
li.style.color = color;
eventLogList.prepend(li);
if (eventLogList.children.length > 10) {
eventLogList.removeChild(eventLogList.lastChild);
}
}
eventCombobox.addEventListener('m-combobox-change', (e) => {
logEvent(`m-combobox-change: [${e.detail.selected.join(', ') || 'none'}]`, 'var(--color-primary-fill-mid)');
});
eventCombobox.addEventListener('m-combobox-select', (e) => {
logEvent(`m-combobox-select: "${e.detail.option.value}"`, 'var(--color-success-fill-mid)');
});
eventCombobox.addEventListener('m-combobox-unselected', (e) => {
logEvent(`m-combobox-unselected: "${e.detail.option.value}"`, 'var(--color-destructive-fill-mid)');
});
eventCombobox.addEventListener('m-combobox-focus-change', (e) => {
const value = e.detail.option?.value || 'none';
logEvent(`m-combobox-focus-change: "${value}"`, 'var(--color-neutral-fill-mid)');
});
</script> Search And Filtering
Code
<div class="form">
<m-combobox name="countries" label="Search countries" debounce="300">
<m-option value="us">United States</m-option>
<m-option value="uk">United Kingdom</m-option>
<m-option value="ca">Canada</m-option>
<m-option value="au">Australia</m-option>
<m-option value="de">Germany</m-option>
<m-option value="fr">France</m-option>
<m-option value="it">Italy</m-option>
<m-option value="es">Spain</m-option>
<m-option value="jp">Japan</m-option>
<m-option value="cn">China</m-option>
</m-combobox>
</div> Focus Management
Focused: None
Selected: None
Selected: None
Code
<div class="stack" data-gap="2">
<m-combobox id="focus-demo" name="focus-demo" label="Focus demo">
<m-option value="item-1">Item 1</m-option>
<m-option value="item-2">Item 2</m-option>
<m-option value="item-3">Item 3</m-option>
<m-option value="item-4">Item 4</m-option>
</m-combobox>
<div class="box" data-variant="surface" style="padding: var(--size-2);">
<strong>Focused:</strong> <span id="focus-output">None</span><br>
<strong>Selected:</strong> <span id="select-output">None</span>
</div>
</div>
<script>
const focusDemo = document.getElementById('focus-demo');
const focusOutput = document.getElementById('focus-output');
const selectOutput = document.getElementById('select-output');
focusDemo.addEventListener('m-combobox-focus-change', (e) => {
focusOutput.textContent = e.detail.option?.value || 'None';
});
focusDemo.addEventListener('m-combobox-change', (e) => {
selectOutput.textContent = e.detail.selected.join(', ') || 'None';
});
</script> Keyboard Navigation
Code
<div class="form">
<m-combobox name="keyboard-demo" label="Try keyboard navigation">
<m-option value="option-1">Option 1</m-option>
<m-option value="option-2">Option 2</m-option>
<m-option value="option-3">Option 3</m-option>
<m-option value="option-4">Option 4</m-option>
<m-option value="option-5">Option 5</m-option>
<m-option value="option-6">Option 6</m-option>
</m-combobox>
</div> Slots
Code
<div class="form">
<m-combobox name="with-icon" label="With search icon">
<svg slot="after" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 21-4.34-4.34"/><circle cx="11" cy="11" r="8"/></svg>
<m-option value="apple">Apple</m-option>
<m-option value="pear">Pear</m-option>
<m-option value="orange">Orange</m-option>
</m-combobox>
</div> Accessibility
Code
<div class="form">
<m-combobox
name="accessible"
label="Preferred contact method (required)"
required
>
<m-option value="email">Email</m-option>
<m-option value="phone">Phone</m-option>
<m-option value="sms">SMS</m-option>
<m-option value="mail">Postal Mail</m-option>
</m-combobox>
</div> - multiple boolean false
- Whether multiple selection is enabled
- debounce number 150
- placeholder string | undefined —
- clearable boolean true
- autocomplete string | undefined —
- size number | undefined —
- autofocus boolean false
- options MOption[] —
- * ---------------------------- Property Getters -----------------------------
- selectedOptions MOption[] —
- selectedValues string[] —
- focusedElement MOption | null —
- adoptedStyleSheets array [baseStyleSheet]
- value string | string[] | null —
- The value from the listbox
- form HTMLFormElement | null —
- The associated form element
- name string —
- The form control name
- setFocus void
- * ---------------------------- Focus Management - Delegated to OptionListManager -----------------------------
- focusFirst void
- focusLast void
- focusNext void
- focusPrev void
- focusBlur void
- select void
- selectFocused void
- selectFirst void
- selectLast void
- selectNext void
- selectPrev void
- formResetCallback void
- * ---------------------------- Form Lifecycle -----------------------------
- change Event
- m-combobox-change CustomEvent
- Fired when the selection changes
- (default)
- Default slot for m-option elements
- after
- Content after the input element (icons, buttons)