Basic
<select> <option value="" disabled selected>Choose one</option> <option value="ford">Ford</option> <option value="honda">Honda</option> ... </select>
The placeholder clears when the dropdown opens and reappears when it closes without a selection.
Search
<select data-searchable="true">
<option value="" disabled selected>
Choose a country
</option>
<option>Australia</option>
<option>Canada</option>
...
</select>
Matches are highlighted. Screen readers receive a live announcement of the result count.
Disabled
<select disabled> <option selected>North America</option> <option>Europe</option> <option>Asia Pacific</option> </select>
Native disabled attribute. No widget-specific API needed.
Listbox
<select size="6" data-searchable="true"> <option>Critical</option> <option>High</option> <option>Medium</option> ... </select>
size > 1 triggers listbox mode — the native attribute stays native.
Multi-select
<select multiple size="8"
data-searchable="true">
<option>Delaware</option>
<option>Maryland</option>
...
</select>
multiple stays native. Space or Enter toggles individual options.
Dynamic options
const select = document.querySelector('select');
// Add
const opt = document.createElement('option');
opt.textContent = 'Delta';
select.appendChild(opt);
// Remove
select.remove(select.options.length - 1);
A MutationObserver keeps the widget in sync — no manual refresh call needed.
Form integration
The native <select> stays in the DOM. FormData, form submission, and constraint validation work without any extra wiring.