Tailwind CSS Combobox
Use the combobox component to pair a text field with a filterable list of options, like a country picker, a timezone field, or a tag input with chips. For a short static set of options, reach for the select, and for a menu of actions, the dropdown.
<div class="field w-full max-w-sm">
<label class="label" for="cb-demo-input">Framework</label>
<div class="input-group" id="cb-demo-field">
<input class="input" id="cb-demo-input" placeholder="Select a framework" />
<span class="input-group-addon input-group-addon-end">
<button class="btn btn-ghost btn-xs btn-icon" type="button" tabindex="-1" aria-label="Open list"><svg class="text-muted-foreground" 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"><path d="m6 9 6 6 6-6"/></svg></button>
</span>
</div>
<p class="field-description">The framework your project is built on.</p>
</div>
<div class="combobox" data-sp-toggle="#cb-demo-field">
<div class="combobox-empty">No items found.</div>
<div class="combobox-list">
<div class="combobox-item"><input type="radio" name="cb-demo" value="next" /> Next.js</div>
<div class="combobox-item"><input type="radio" name="cb-demo" value="sveltekit" /> SvelteKit</div>
<div class="combobox-item"><input type="radio" name="cb-demo" value="nuxt" /> Nuxt.js</div>
<div class="combobox-item"><input type="radio" name="cb-demo" value="remix" /> Remix</div>
<div class="combobox-item"><input type="radio" name="cb-demo" value="astro" /> Astro</div>
</div>
</div>Usage
Add the combobox class to the panel and point data-sp-toggle at the field: an input group holding a regular input (single select), or a combobox-chips container (multi select). Each option wraps a hidden radio or checkbox that holds its state, so forms, change events, and :checked queries work like any native control.
<!-- This is the field -->
<div class="input-group" id="my-field">
<input class="input" placeholder="Select an option" />
</div>
<!-- This is the combobox -->
<div class="combobox" data-sp-toggle="#my-field">
<div class="combobox-empty">No items found.</div>
<div class="combobox-list">
<div class="combobox-item"><input type="radio" name="option" value="one" /> Option one</div>
<div class="combobox-item"><input type="radio" name="option" value="two" /> Option two</div>
</div>
</div>Examples
Basic combobox
Type in the field to filter the list. Choosing an option fills the field and checks its hidden input.
<div class="input-group w-full max-w-sm" id="cb-basic-field">
<input class="input" placeholder="Select a framework" />
<span class="input-group-addon input-group-addon-end">
<button class="btn btn-ghost btn-xs btn-icon" type="button" tabindex="-1" aria-label="Open list"><svg class="text-muted-foreground" 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"><path d="m6 9 6 6 6-6"/></svg></button>
</span>
</div>
<div class="combobox" data-sp-toggle="#cb-basic-field">
<div class="combobox-empty">No items found.</div>
<div class="combobox-list">
<div class="combobox-item"><input type="radio" name="cb-basic" value="next" /> Next.js</div>
<div class="combobox-item"><input type="radio" name="cb-basic" value="sveltekit" /> SvelteKit</div>
<div class="combobox-item"><input type="radio" name="cb-basic" value="nuxt" /> Nuxt.js</div>
<div class="combobox-item"><input type="radio" name="cb-basic" value="remix" /> Remix</div>
<div class="combobox-item"><input type="radio" name="cb-basic" value="astro" /> Astro</div>
</div>
</div>Preselected value
Author checked on the options and the selection renders before JavaScript loads. For single select, mirror the label into the field's value. For multi select, author one chip per checked option.
<div class="flex w-full max-w-sm flex-col gap-4">
<div class="input-group" id="cb-preselected-field">
<input class="input" placeholder="Select a framework" value="Nuxt.js" />
<span class="input-group-addon input-group-addon-end">
<button class="btn btn-ghost btn-xs btn-icon" type="button" tabindex="-1" aria-label="Open list"><svg class="text-muted-foreground" 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"><path d="m6 9 6 6 6-6"/></svg></button>
</span>
</div>
<div class="combobox-chips" id="cb-preselected-chips">
<span class="combobox-chip">SvelteKit <button class="combobox-chip-remove" type="button" aria-label="Remove SvelteKit"></button></span>
<span class="combobox-chip">Astro <button class="combobox-chip-remove" type="button" aria-label="Remove Astro"></button></span>
<input placeholder="Add framework" />
</div>
<div class="combobox" data-sp-toggle="#cb-preselected-field">
<div class="combobox-empty">No items found.</div>
<div class="combobox-list">
<div class="combobox-item"><input type="radio" name="cb-preselected" value="next" /> Next.js</div>
<div class="combobox-item"><input type="radio" name="cb-preselected" value="sveltekit" /> SvelteKit</div>
<div class="combobox-item"><input type="radio" name="cb-preselected" value="nuxt" checked /> Nuxt.js</div>
<div class="combobox-item"><input type="radio" name="cb-preselected" value="remix" /> Remix</div>
<div class="combobox-item"><input type="radio" name="cb-preselected" value="astro" /> Astro</div>
</div>
</div>
<div class="combobox" data-sp-toggle="#cb-preselected-chips">
<div class="combobox-empty">No items found.</div>
<div class="combobox-list">
<div class="combobox-item"><input type="checkbox" name="cb-preselected-multi" value="next" /> Next.js</div>
<div class="combobox-item"><input type="checkbox" name="cb-preselected-multi" value="sveltekit" checked /> SvelteKit</div>
<div class="combobox-item"><input type="checkbox" name="cb-preselected-multi" value="nuxt" /> Nuxt.js</div>
<div class="combobox-item"><input type="checkbox" name="cb-preselected-multi" value="remix" /> Remix</div>
<div class="combobox-item"><input type="checkbox" name="cb-preselected-multi" value="astro" checked /> Astro</div>
</div>
</div>
</div>Multiple selection
Point the combobox at a combobox-chips field and use checkbox inputs: every choice renders as a removable chip, and Backspace in the empty input removes the newest one.
<div class="combobox-chips w-full max-w-sm" id="cb-multi-chips">
<span class="combobox-chip">Next.js <button class="combobox-chip-remove" type="button" aria-label="Remove Next.js"></button></span>
<span class="combobox-chip">Nuxt.js <button class="combobox-chip-remove" type="button" aria-label="Remove Nuxt.js"></button></span>
<input placeholder="Add framework" />
</div>
<div class="combobox" data-sp-toggle="#cb-multi-chips" data-sp-auto-highlight="true">
<div class="combobox-empty">No items found.</div>
<div class="combobox-list">
<div class="combobox-item"><input type="checkbox" name="cb-multi" value="next" checked /> Next.js</div>
<div class="combobox-item"><input type="checkbox" name="cb-multi" value="sveltekit" /> SvelteKit</div>
<div class="combobox-item"><input type="checkbox" name="cb-multi" value="nuxt" checked /> Nuxt.js</div>
<div class="combobox-item"><input type="checkbox" name="cb-multi" value="remix" /> Remix</div>
<div class="combobox-item"><input type="checkbox" name="cb-multi" value="astro" /> Astro</div>
</div>
</div>Clear button
Add a combobox-clear button to the field. It shows while something is selected.
<div class="input-group w-full max-w-sm" id="cb-clear-field">
<input class="input" placeholder="Select a framework" value="Next.js" />
<span class="input-group-addon input-group-addon-end">
<button class="btn btn-ghost btn-xs btn-icon combobox-clear" type="button" aria-label="Clear selection"><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"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg></button>
</span>
</div>
<div class="combobox" data-sp-toggle="#cb-clear-field">
<div class="combobox-empty">No items found.</div>
<div class="combobox-list">
<div class="combobox-item"><input type="radio" name="cb-clear" value="next" checked /> Next.js</div>
<div class="combobox-item"><input type="radio" name="cb-clear" value="sveltekit" /> SvelteKit</div>
<div class="combobox-item"><input type="radio" name="cb-clear" value="nuxt" /> Nuxt.js</div>
<div class="combobox-item"><input type="radio" name="cb-clear" value="remix" /> Remix</div>
<div class="combobox-item"><input type="radio" name="cb-clear" value="astro" /> Astro</div>
</div>
</div>Combobox groups
Wrap a combobox-label and its options in a combobox-group, and the group hides when the filter empties it.
<div class="input-group w-full max-w-sm" id="cb-groups-field">
<input class="input" placeholder="Select a timezone" />
<span class="input-group-addon input-group-addon-end">
<button class="btn btn-ghost btn-xs btn-icon" type="button" tabindex="-1" aria-label="Open list"><svg class="text-muted-foreground" 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"><path d="m6 9 6 6 6-6"/></svg></button>
</span>
</div>
<div class="combobox" data-sp-toggle="#cb-groups-field">
<div class="combobox-empty">No timezones found.</div>
<div class="combobox-list">
<div class="combobox-group">
<div class="combobox-label">Americas</div>
<div class="combobox-item"><input type="radio" name="cb-groups" value="new-york" /> (GMT-5) New York</div>
<div class="combobox-item"><input type="radio" name="cb-groups" value="los-angeles" /> (GMT-8) Los Angeles</div>
<div class="combobox-item"><input type="radio" name="cb-groups" value="chicago" /> (GMT-6) Chicago</div>
<div class="combobox-item"><input type="radio" name="cb-groups" value="toronto" /> (GMT-5) Toronto</div>
<div class="combobox-item"><input type="radio" name="cb-groups" value="vancouver" /> (GMT-8) Vancouver</div>
<div class="combobox-item"><input type="radio" name="cb-groups" value="sao-paulo" /> (GMT-3) São Paulo</div>
<div class="combobox-separator"></div>
</div>
<div class="combobox-group">
<div class="combobox-label">Europe</div>
<div class="combobox-item"><input type="radio" name="cb-groups" value="london" /> (GMT+0) London</div>
<div class="combobox-item"><input type="radio" name="cb-groups" value="paris" /> (GMT+1) Paris</div>
<div class="combobox-item"><input type="radio" name="cb-groups" value="berlin" /> (GMT+1) Berlin</div>
<div class="combobox-item"><input type="radio" name="cb-groups" value="rome" /> (GMT+1) Rome</div>
<div class="combobox-item"><input type="radio" name="cb-groups" value="madrid" /> (GMT+1) Madrid</div>
<div class="combobox-item"><input type="radio" name="cb-groups" value="amsterdam" /> (GMT+1) Amsterdam</div>
<div class="combobox-separator"></div>
</div>
<div class="combobox-group">
<div class="combobox-label">Asia/Pacific</div>
<div class="combobox-item"><input type="radio" name="cb-groups" value="tokyo" /> (GMT+9) Tokyo</div>
<div class="combobox-item"><input type="radio" name="cb-groups" value="shanghai" /> (GMT+8) Shanghai</div>
<div class="combobox-item"><input type="radio" name="cb-groups" value="singapore" /> (GMT+8) Singapore</div>
<div class="combobox-item"><input type="radio" name="cb-groups" value="dubai" /> (GMT+4) Dubai</div>
<div class="combobox-item"><input type="radio" name="cb-groups" value="sydney" /> (GMT+11) Sydney</div>
<div class="combobox-item"><input type="radio" name="cb-groups" value="seoul" /> (GMT+9) Seoul</div>
</div>
</div>
</div>Custom items
Options can hold any markup. Set data-sp-label so filtering and the field text use that label instead.
<div class="input-group w-full max-w-sm" id="cb-custom-field">
<input class="input" placeholder="Search countries..." />
<span class="input-group-addon input-group-addon-end">
<button class="btn btn-ghost btn-xs btn-icon" type="button" tabindex="-1" aria-label="Open list"><svg class="text-muted-foreground" 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"><path d="m6 9 6 6 6-6"/></svg></button>
</span>
</div>
<div class="combobox" data-sp-toggle="#cb-custom-field">
<div class="combobox-empty">No countries found.</div>
<div class="combobox-list">
<div class="combobox-item" data-sp-label="Argentina">
<input type="radio" name="cb-custom" value="argentina" />
<span class="flex flex-col items-start">
<span class="whitespace-nowrap">Argentina</span>
<span class="text-xs text-muted-foreground">South America (ar)</span>
</span>
</div>
<div class="combobox-item" data-sp-label="Australia">
<input type="radio" name="cb-custom" value="australia" />
<span class="flex flex-col items-start">
<span class="whitespace-nowrap">Australia</span>
<span class="text-xs text-muted-foreground">Oceania (au)</span>
</span>
</div>
<div class="combobox-item" data-sp-label="Brazil">
<input type="radio" name="cb-custom" value="brazil" />
<span class="flex flex-col items-start">
<span class="whitespace-nowrap">Brazil</span>
<span class="text-xs text-muted-foreground">South America (br)</span>
</span>
</div>
<div class="combobox-item" data-sp-label="Canada">
<input type="radio" name="cb-custom" value="canada" />
<span class="flex flex-col items-start">
<span class="whitespace-nowrap">Canada</span>
<span class="text-xs text-muted-foreground">North America (ca)</span>
</span>
</div>
<div class="combobox-item" data-sp-label="China">
<input type="radio" name="cb-custom" value="china" />
<span class="flex flex-col items-start">
<span class="whitespace-nowrap">China</span>
<span class="text-xs text-muted-foreground">Asia (cn)</span>
</span>
</div>
<div class="combobox-item" data-sp-label="Colombia">
<input type="radio" name="cb-custom" value="colombia" />
<span class="flex flex-col items-start">
<span class="whitespace-nowrap">Colombia</span>
<span class="text-xs text-muted-foreground">South America (co)</span>
</span>
</div>
<div class="combobox-item" data-sp-label="Egypt">
<input type="radio" name="cb-custom" value="egypt" />
<span class="flex flex-col items-start">
<span class="whitespace-nowrap">Egypt</span>
<span class="text-xs text-muted-foreground">Africa (eg)</span>
</span>
</div>
<div class="combobox-item" data-sp-label="France">
<input type="radio" name="cb-custom" value="france" />
<span class="flex flex-col items-start">
<span class="whitespace-nowrap">France</span>
<span class="text-xs text-muted-foreground">Europe (fr)</span>
</span>
</div>
<div class="combobox-item" data-sp-label="Germany">
<input type="radio" name="cb-custom" value="germany" />
<span class="flex flex-col items-start">
<span class="whitespace-nowrap">Germany</span>
<span class="text-xs text-muted-foreground">Europe (de)</span>
</span>
</div>
<div class="combobox-item" data-sp-label="Italy">
<input type="radio" name="cb-custom" value="italy" />
<span class="flex flex-col items-start">
<span class="whitespace-nowrap">Italy</span>
<span class="text-xs text-muted-foreground">Europe (it)</span>
</span>
</div>
<div class="combobox-item" data-sp-label="Japan">
<input type="radio" name="cb-custom" value="japan" />
<span class="flex flex-col items-start">
<span class="whitespace-nowrap">Japan</span>
<span class="text-xs text-muted-foreground">Asia (jp)</span>
</span>
</div>
<div class="combobox-item" data-sp-label="Kenya">
<input type="radio" name="cb-custom" value="kenya" />
<span class="flex flex-col items-start">
<span class="whitespace-nowrap">Kenya</span>
<span class="text-xs text-muted-foreground">Africa (ke)</span>
</span>
</div>
<div class="combobox-item" data-sp-label="Mexico">
<input type="radio" name="cb-custom" value="mexico" />
<span class="flex flex-col items-start">
<span class="whitespace-nowrap">Mexico</span>
<span class="text-xs text-muted-foreground">North America (mx)</span>
</span>
</div>
<div class="combobox-item" data-sp-label="New Zealand">
<input type="radio" name="cb-custom" value="new-zealand" />
<span class="flex flex-col items-start">
<span class="whitespace-nowrap">New Zealand</span>
<span class="text-xs text-muted-foreground">Oceania (nz)</span>
</span>
</div>
<div class="combobox-item" data-sp-label="Nigeria">
<input type="radio" name="cb-custom" value="nigeria" />
<span class="flex flex-col items-start">
<span class="whitespace-nowrap">Nigeria</span>
<span class="text-xs text-muted-foreground">Africa (ng)</span>
</span>
</div>
<div class="combobox-item" data-sp-label="South Africa">
<input type="radio" name="cb-custom" value="south-africa" />
<span class="flex flex-col items-start">
<span class="whitespace-nowrap">South Africa</span>
<span class="text-xs text-muted-foreground">Africa (za)</span>
</span>
</div>
<div class="combobox-item" data-sp-label="South Korea">
<input type="radio" name="cb-custom" value="south-korea" />
<span class="flex flex-col items-start">
<span class="whitespace-nowrap">South Korea</span>
<span class="text-xs text-muted-foreground">Asia (kr)</span>
</span>
</div>
<div class="combobox-item" data-sp-label="United Kingdom">
<input type="radio" name="cb-custom" value="united-kingdom" />
<span class="flex flex-col items-start">
<span class="whitespace-nowrap">United Kingdom</span>
<span class="text-xs text-muted-foreground">Europe (gb)</span>
</span>
</div>
<div class="combobox-item" data-sp-label="United States">
<input type="radio" name="cb-custom" value="united-states" />
<span class="flex flex-col items-start">
<span class="whitespace-nowrap">United States</span>
<span class="text-xs text-muted-foreground">North America (us)</span>
</span>
</div>
</div>
</div>Invalid
Set aria-invalid on the input and the field shows the error ring.
<div class="field w-full max-w-sm">
<label class="label" for="cb-invalid-input">Framework</label>
<div class="input-group" id="cb-invalid-field">
<input class="input" id="cb-invalid-input" placeholder="Select a framework" aria-invalid="true" />
<span class="input-group-addon input-group-addon-end">
<button class="btn btn-ghost btn-xs btn-icon" type="button" tabindex="-1" aria-label="Open list"><svg class="text-muted-foreground" 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"><path d="m6 9 6 6 6-6"/></svg></button>
</span>
</div>
<p class="field-description">This field contains validation errors.</p>
</div>
<div class="combobox" data-sp-toggle="#cb-invalid-field">
<div class="combobox-empty">No items found.</div>
<div class="combobox-list">
<div class="combobox-item"><input type="radio" name="cb-invalid" value="next" /> Next.js</div>
<div class="combobox-item"><input type="radio" name="cb-invalid" value="sveltekit" /> SvelteKit</div>
<div class="combobox-item"><input type="radio" name="cb-invalid" value="nuxt" /> Nuxt.js</div>
<div class="combobox-item"><input type="radio" name="cb-invalid" value="remix" /> Remix</div>
<div class="combobox-item"><input type="radio" name="cb-invalid" value="astro" /> Astro</div>
</div>
</div>Disabled
Add disabled to the input and the whole field mutes itself and stops opening.
<div class="field w-full max-w-sm">
<label class="label" for="cb-disabled-input">Framework</label>
<div class="input-group" id="cb-disabled-field">
<input class="input" id="cb-disabled-input" placeholder="Select a framework" disabled />
<span class="input-group-addon input-group-addon-end">
<button class="btn btn-ghost btn-xs btn-icon" type="button" tabindex="-1" aria-label="Open list"><svg class="text-muted-foreground" 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"><path d="m6 9 6 6 6-6"/></svg></button>
</span>
</div>
<p class="field-description">This field is currently disabled.</p>
</div>
<div class="combobox" data-sp-toggle="#cb-disabled-field">
<div class="combobox-empty">No items found.</div>
<div class="combobox-list">
<div class="combobox-item"><input type="radio" name="cb-disabled" value="next" /> Next.js</div>
<div class="combobox-item"><input type="radio" name="cb-disabled" value="sveltekit" /> SvelteKit</div>
<div class="combobox-item"><input type="radio" name="cb-disabled" value="nuxt" /> Nuxt.js</div>
<div class="combobox-item"><input type="radio" name="cb-disabled" value="remix" /> Remix</div>
<div class="combobox-item"><input type="radio" name="cb-disabled" value="astro" /> Astro</div>
</div>
</div>Auto highlight
Add data-sp-auto-highlight and the first match highlights while the user types, so Enter selects it right away.
<div class="input-group w-full max-w-sm" id="cb-auto-field">
<input class="input" placeholder="Select a framework" />
<span class="input-group-addon input-group-addon-end">
<button class="btn btn-ghost btn-xs btn-icon" type="button" tabindex="-1" aria-label="Open list"><svg class="text-muted-foreground" 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"><path d="m6 9 6 6 6-6"/></svg></button>
</span>
</div>
<div class="combobox" data-sp-toggle="#cb-auto-field" data-sp-auto-highlight="true">
<div class="combobox-empty">No items found.</div>
<div class="combobox-list">
<div class="combobox-item"><input type="radio" name="cb-auto" value="next" /> Next.js</div>
<div class="combobox-item"><input type="radio" name="cb-auto" value="sveltekit" /> SvelteKit</div>
<div class="combobox-item"><input type="radio" name="cb-auto" value="nuxt" /> Nuxt.js</div>
<div class="combobox-item"><input type="radio" name="cb-auto" value="remix" /> Remix</div>
<div class="combobox-item"><input type="radio" name="cb-auto" value="astro" /> Astro</div>
</div>
</div>Combobox in an input group
The field is a regular input group, so addons like a leading icon compose in.
<div class="input-group w-full max-w-sm" id="cb-addon-field">
<span class="input-group-addon"><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"><circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/></svg></span>
<input class="input" placeholder="Select a timezone" />
<span class="input-group-addon input-group-addon-end">
<button class="btn btn-ghost btn-xs btn-icon" type="button" tabindex="-1" aria-label="Open list"><svg class="text-muted-foreground" 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"><path d="m6 9 6 6 6-6"/></svg></button>
</span>
</div>
<div class="combobox" data-sp-toggle="#cb-addon-field">
<div class="combobox-empty">No timezones found.</div>
<div class="combobox-list">
<div class="combobox-group">
<div class="combobox-label">Americas</div>
<div class="combobox-item"><input type="radio" name="cb-addon" value="new-york" /> (GMT-5) New York</div>
<div class="combobox-item"><input type="radio" name="cb-addon" value="los-angeles" /> (GMT-8) Los Angeles</div>
<div class="combobox-item"><input type="radio" name="cb-addon" value="chicago" /> (GMT-6) Chicago</div>
<div class="combobox-item"><input type="radio" name="cb-addon" value="toronto" /> (GMT-5) Toronto</div>
<div class="combobox-item"><input type="radio" name="cb-addon" value="vancouver" /> (GMT-8) Vancouver</div>
<div class="combobox-item"><input type="radio" name="cb-addon" value="sao-paulo" /> (GMT-3) São Paulo</div>
</div>
<div class="combobox-group">
<div class="combobox-label">Europe</div>
<div class="combobox-item"><input type="radio" name="cb-addon" value="london" /> (GMT+0) London</div>
<div class="combobox-item"><input type="radio" name="cb-addon" value="paris" /> (GMT+1) Paris</div>
<div class="combobox-item"><input type="radio" name="cb-addon" value="berlin" /> (GMT+1) Berlin</div>
<div class="combobox-item"><input type="radio" name="cb-addon" value="rome" /> (GMT+1) Rome</div>
<div class="combobox-item"><input type="radio" name="cb-addon" value="madrid" /> (GMT+1) Madrid</div>
<div class="combobox-item"><input type="radio" name="cb-addon" value="amsterdam" /> (GMT+1) Amsterdam</div>
</div>
<div class="combobox-group">
<div class="combobox-label">Asia/Pacific</div>
<div class="combobox-item"><input type="radio" name="cb-addon" value="tokyo" /> (GMT+9) Tokyo</div>
<div class="combobox-item"><input type="radio" name="cb-addon" value="shanghai" /> (GMT+8) Shanghai</div>
<div class="combobox-item"><input type="radio" name="cb-addon" value="singapore" /> (GMT+8) Singapore</div>
<div class="combobox-item"><input type="radio" name="cb-addon" value="dubai" /> (GMT+4) Dubai</div>
<div class="combobox-item"><input type="radio" name="cb-addon" value="sydney" /> (GMT+11) Sydney</div>
<div class="combobox-item"><input type="radio" name="cb-addon" value="seoul" /> (GMT+9) Seoul</div>
</div>
</div>
</div>Reading the values
The hidden inputs are real form fields, so the selections submit with the form: read a single select with FormData.get and a multi select with FormData.getAll, or query input[name]:checked directly.
<form id="cb-form" class="field-group w-full max-w-sm">
<div class="field">
<label class="label" for="cb-form-framework">Framework</label>
<div class="input-group" id="cb-form-single">
<input class="input" id="cb-form-framework" placeholder="Select a framework" />
<span class="input-group-addon input-group-addon-end">
<button class="btn btn-ghost btn-xs btn-icon" type="button" tabindex="-1" aria-label="Open list"><svg class="text-muted-foreground" 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"><path d="m6 9 6 6 6-6"/></svg></button>
</span>
</div>
<div class="combobox" data-sp-toggle="#cb-form-single">
<div class="combobox-empty">No items found.</div>
<div class="combobox-list">
<div class="combobox-item"><input type="radio" name="framework" value="next" /> Next.js</div>
<div class="combobox-item"><input type="radio" name="framework" value="sveltekit" /> SvelteKit</div>
<div class="combobox-item"><input type="radio" name="framework" value="nuxt" /> Nuxt.js</div>
<div class="combobox-item"><input type="radio" name="framework" value="remix" /> Remix</div>
<div class="combobox-item"><input type="radio" name="framework" value="astro" /> Astro</div>
</div>
</div>
</div>
<div class="field">
<label class="label" for="cb-form-tools">Tools</label>
<div class="combobox-chips" id="cb-form-chips">
<input id="cb-form-tools" placeholder="Add tools" />
</div>
<div class="combobox" data-sp-toggle="#cb-form-chips">
<div class="combobox-empty">No items found.</div>
<div class="combobox-list">
<div class="combobox-item"><input type="checkbox" name="tools" value="eslint" /> ESLint</div>
<div class="combobox-item"><input type="checkbox" name="tools" value="prettier" /> Prettier</div>
<div class="combobox-item"><input type="checkbox" name="tools" value="vitest" /> Vitest</div>
<div class="combobox-item"><input type="checkbox" name="tools" value="playwright" /> Playwright</div>
</div>
</div>
</div>
<div class="field field-horizontal">
<button type="submit" class="btn">Submit</button>
</div>
<p class="field-description" id="cb-form-result">Submit to read the values.</p>
</form>
<script>
document.getElementById("cb-form").addEventListener("submit", (event) => {
event.preventDefault();
const data = new FormData(event.target);
const framework = data.get("framework") ?? "none";
const tools = data.getAll("tools").join(", ") || "none";
document.getElementById("cb-form-result").textContent = `framework: ${framework} | tools: ${tools}`;
});
</script>RTL
Add dir="rtl" to any parent element, typically <html>, to render right-to-left. See the RTL guide for details.
<div id="combobox-rtl-demo" dir="rtl" class="w-full max-w-sm">
<div class="field">
<label class="label" for="combobox-rtl-input" data-i18n="label">الفئات</label>
<div class="combobox-chips" id="combobox-rtl-chips">
<span class="combobox-chip"><span data-i18n="technology">التكنولوجيا</span> <button class="combobox-chip-remove" type="button" aria-label="Remove Technology"></button></span>
<input id="combobox-rtl-input" placeholder="أضف فئات" data-i18n-placeholder="placeholder" />
</div>
</div>
<div class="combobox" data-sp-toggle="#combobox-rtl-chips" data-sp-auto-highlight="true">
<div class="combobox-empty" data-i18n="empty">لم يتم العثور على فئات.</div>
<div class="combobox-list">
<div class="combobox-item"><input type="checkbox" name="combobox-rtl" value="technology" checked /> <span data-i18n="technology">التكنولوجيا</span></div>
<div class="combobox-item"><input type="checkbox" name="combobox-rtl" value="design" /> <span data-i18n="design">التصميم</span></div>
<div class="combobox-item"><input type="checkbox" name="combobox-rtl" value="business" /> <span data-i18n="business">الأعمال</span></div>
<div class="combobox-item"><input type="checkbox" name="combobox-rtl" value="marketing" /> <span data-i18n="marketing">التسويق</span></div>
<div class="combobox-item"><input type="checkbox" name="combobox-rtl" value="education" /> <span data-i18n="education">التعليم</span></div>
<div class="combobox-item"><input type="checkbox" name="combobox-rtl" value="health" /> <span data-i18n="health">الصحة</span></div>
</div>
</div>
</div>
<script>
const translations = {
ar: { dir: "rtl", label: "الفئات", placeholder: "أضف فئات", empty: "لم يتم العثور على فئات.", technology: "التكنولوجيا", design: "التصميم", business: "الأعمال", marketing: "التسويق", education: "التعليم", health: "الصحة" },
he: { dir: "rtl", label: "קטגוריות", placeholder: "הוסף קטגוריות", empty: "לא נמצאו קטגוריות.", technology: "טכנולוגיה", design: "עיצוב", business: "עסקים", marketing: "שיווק", education: "חינוך", health: "בריאות" },
en: { dir: "ltr", label: "Categories", placeholder: "Add categories", empty: "No categories found.", technology: "Technology", design: "Design", business: "Business", marketing: "Marketing", education: "Education", health: "Health" },
};
window.addEventListener("message", (e) => {
const t = translations[e.data?.lang];
if (e.data?.type !== "sp-language" || !t) return;
document.getElementById("combobox-rtl-demo").dir = t.dir;
document.querySelectorAll("[data-i18n]").forEach((el) => {
el.textContent = t[el.dataset.i18n];
});
document.querySelectorAll("[data-i18n-placeholder]").forEach((el) => {
el.placeholder = t[el.dataset.i18nPlaceholder];
});
});
</script>Options
Combobox
Set each option with its own data-sp-* attribute on the combobox element.
<div class="combobox" data-sp-toggle="#my-field" data-sp-auto-highlight="true">JavaScript
Events
Lifecycle events fire on the combobox element. The before* events are cancelable. Selection changes fire a native change event on the option's hidden input, which bubbles through the panel.
document.querySelector("#my-combobox").addEventListener("change", (e) => {
console.log(e.target.name, e.target.value, e.target.checked);
});Methods
Get the instance with sp.combobox(el), then call its methods:
const combobox = sp.combobox(document.querySelector("#my-combobox"));
combobox.clear();