Combobox
Editable input opening a filterable listbox popover. Typing filters, arrows rove, Enter picks and fills the input.
INSTALL
1pnpm dlx @sayagodev/mo add comboboxOr import the files from the package (no copy):
1import "@sayagodev/mo/css/combobox.css";2import "@sayagodev/mo/js/combobox.js";
Also copied as dependency: shared.css
EXAMPLES
Basic
- No items found.
1<mo-combobox>2 <div data-combobox>3 <input role="combobox" aria-expanded="false" aria-controls="cb-frameworks" aria-autocomplete="list" placeholder="Select a framework..." autocomplete="off" aria-label="Framework" />4 <button type="button" class="icon ghost" data-combobox-toggle aria-label="Toggle options">5 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6" /></svg>6 </button>7 </div>8 <ul popover id="cb-frameworks" role="listbox" aria-label="Frameworks">9 <li><button type="button" role="option">Next.js</button></li>10 <li><button type="button" role="option">SvelteKit</button></li>11 <li><button type="button" role="option">Nuxt.js</button></li>12 <li><button type="button" role="option">Remix</button></li>13 <li><button type="button" role="option">Astro</button></li>14 <li data-combobox-empty hidden>No items found.</li>15 </ul>16</mo-combobox>17
Groups
-
Americas
-
Europe
-
Asia/Pacific
- No timezones found.
1<mo-combobox>2 <div data-combobox>3 <input role="combobox" aria-expanded="false" aria-controls="cb-timezones" aria-autocomplete="list" placeholder="Select a timezone..." autocomplete="off" aria-label="Timezone" />4 <button type="button" class="icon ghost" data-combobox-toggle aria-label="Toggle options">5 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6" /></svg>6 </button>7 </div>8 <ul popover id="cb-timezones" role="listbox" aria-label="Timezones">9 <li role="group" aria-labelledby="cb-tz-americas">10 <div data-label id="cb-tz-americas">Americas</div>11 <button type="button" role="option">(GMT-5) New York</button>12 <button type="button" role="option">(GMT-8) Los Angeles</button>13 <button type="button" role="option">(GMT-6) Chicago</button>14 <button type="button" role="option">(GMT-5) Toronto</button>15 <button type="button" role="option">(GMT-3) São Paulo</button>16 </li>17 <hr />18 <li role="group" aria-labelledby="cb-tz-europe">19 <div data-label id="cb-tz-europe">Europe</div>20 <button type="button" role="option">(GMT+0) London</button>21 <button type="button" role="option">(GMT+1) Paris</button>22 <button type="button" role="option">(GMT+1) Berlin</button>23 <button type="button" role="option">(GMT+1) Madrid</button>24 <button type="button" role="option">(GMT+1) Amsterdam</button>25 </li>26 <hr />27 <li role="group" aria-labelledby="cb-tz-apac">28 <div data-label id="cb-tz-apac">Asia/Pacific</div>29 <button type="button" role="option">(GMT+9) Tokyo</button>30 <button type="button" role="option">(GMT+8) Shanghai</button>31 <button type="button" role="option">(GMT+8) Singapore</button>32 <button type="button" role="option">(GMT+11) Sydney</button>33 <button type="button" role="option">(GMT+9) Seoul</button>34 </li>35 <li data-combobox-empty hidden>No timezones found.</li>36 </ul>37</mo-combobox>38
Disabled
- No items found.
1<mo-combobox>2 <div data-combobox>3 <input role="combobox" aria-expanded="false" aria-controls="cb-disabled" aria-autocomplete="list" placeholder="Select a framework..." autocomplete="off" aria-label="Framework" />4 <button type="button" class="icon ghost" data-combobox-toggle aria-label="Toggle options">5 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6" /></svg>6 </button>7 </div>8 <ul popover id="cb-disabled" role="listbox" aria-label="Frameworks">9 <li><button type="button" role="option">Next.js</button></li>10 <li><button type="button" role="option">SvelteKit</button></li>11 <li><button type="button" role="option" disabled>Nuxt.js</button></li>12 <li><button type="button" role="option">Remix</button></li>13 <li data-combobox-empty hidden>No items found.</li>14 </ul>15</mo-combobox>16
Fully disabled
- No items found.
1<mo-combobox>2 <div data-combobox>3 <input role="combobox" aria-expanded="false" aria-controls="cb-fully-disabled" aria-autocomplete="list" placeholder="Disabled" autocomplete="off" aria-label="Framework" disabled />4 <button type="button" class="icon ghost" data-combobox-toggle aria-label="Toggle options" disabled>5 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6" /></svg>6 </button>7 </div>8 <ul popover id="cb-fully-disabled" role="listbox" aria-label="Frameworks">9 <li><button type="button" role="option">Next.js</button></li>10 <li><button type="button" role="option">SvelteKit</button></li>11 <li><button type="button" role="option">Nuxt.js</button></li>12 <li><button type="button" role="option">Remix</button></li>13 <li data-combobox-empty hidden>No items found.</li>14 </ul>15</mo-combobox>16
Clear
- No items found.
1<mo-combobox>2 <div data-combobox>3 <input role="combobox" aria-expanded="false" aria-controls="cb-clearable" value="Next.js" aria-autocomplete="list" placeholder="Select a framework..." autocomplete="off" aria-label="Framework" />4 <button type="button" class="icon ghost" data-combobox-clear aria-label="Clear selection">5 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 6 6 18" /><path d="m6 6 12 12" /></svg>6 </button>7 <button type="button" class="icon ghost" data-combobox-toggle aria-label="Toggle options">8 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6" /></svg>9 </button>10 </div>11 <ul popover id="cb-clearable" role="listbox" aria-label="Frameworks">12 <li><button type="button" role="option">Next.js</button></li>13 <li><button type="button" role="option">SvelteKit</button></li>14 <li><button type="button" role="option">Nuxt.js</button></li>15 <li><button type="button" role="option">Remix</button></li>16 <li><button type="button" role="option">Astro</button></li>17 <li data-combobox-empty hidden>No items found.</li>18 </ul>19</mo-combobox>20
Invalid
- No items found.
1<mo-combobox>2 <div data-combobox>3 <input role="combobox" aria-expanded="false" aria-controls="cb-invalid" aria-invalid="true" aria-autocomplete="list" placeholder="Select a framework..." autocomplete="off" aria-label="Framework" />4 <button type="button" class="icon ghost" data-combobox-toggle aria-label="Toggle options">5 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6" /></svg>6 </button>7 </div>8 <ul popover id="cb-invalid" role="listbox" aria-label="Frameworks">9 <li><button type="button" role="option">Next.js</button></li>10 <li><button type="button" role="option">SvelteKit</button></li>11 <li><button type="button" role="option">Nuxt.js</button></li>12 <li><button type="button" role="option">Remix</button></li>13 <li><button type="button" role="option">Astro</button></li>14 <li data-combobox-empty hidden>No items found.</li>15 </ul>16</mo-combobox>17
USAGE
1<mo-combobox>2 <div data-combobox>3 <input role="combobox" aria-expanded="false" placeholder="Select…" />4 <button type="button" class="icon ghost" data-combobox-toggle>▾</button>5 </div>6 <ul popover id="cb1" role="listbox">7 <li><button type="button" role="option" value="apple">Apple</button></li>8 </ul>9</mo-combobox>
API
NAMEKINDDESCRIPTION
<mo-combobox>elementFiltering, roving selection, placement with flip
[data-combobox]attributeInput + toggle frame
[data-combobox-empty]attributeRow shown when nothing matches the filter
mo-combobox-changeelementEvent, detail { value } on pick
FILES
src/css/combobox.csssrc/js/combobox.jsdep: src/css/shared.cssInstall:
mo add comboboxTHEMING · PLAYGROUND
This is the exact component from the examples above, wearing a completely different theme. Edit the tokens and --mo-* hooks in the editor — autocomplete knows them all — and the preview obeys in real time. Your CSS always wins.
Global tokens
--accent--accent-foreground--border--destructive--foreground--input--muted-foreground--popover--popover-foreground--radius--ringComponent hooks
--mo-combobox-height--mo-combobox-max-height--mo-combobox-min-width--mo-combobox-radiusPreview
Your CSS
Try it: type --mo- for the component hooks, or edit any value — the preview obeys in real time.