An editable combobox with autocomplete behavior and selection support.
Installation <script type="module">
import '@nvidia-elements/core/combobox/define.js';
</script>
<nve-combobox>
<label>label</label>
<input type="search" />
<datalist>
<option value="status"></option>
<option value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
</datalist>
<nve-control-message>message</nve-control-message>
</nve-combobox>
<script type="module">
import '@nvidia-elements/core/combobox/define.js';
</script>
<nve-combobox>
<label>label</label>
<input type="search" />
<datalist>
<option value="status"></option>
<option value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
</datalist>
<nve-control-message>message</nve-control-message>
</nve-combobox>
nve api.get nve-combobox nve api.get nve-combobox
Single Select Multi Select Selected First \n"}
Multi-select that reorders selected options before unselected options after the combobox closes. Use when long filter lists need selected values to stay easy to review.
<nve-combobox id="combobox-selected-first" style="width: 500px; --scroll-height: 220px">
<label>label</label>
<input type="search" />
<select multiple>
<option value="status"></option>
<option value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
<option value="includes"></option>
<option value="user"></option>
<option value="progress"></option>
</select>
<nve-control-message>message</nve-control-message>
</nve-combobox>
<script type="module">
const combobox = document.querySelector("#combobox-selected-first");
const select = combobox.querySelector("select");
const optionOrder = new Map([...select.options].map((option, index) => [option, index]));
combobox.addEventListener("open", () => {
const selectedOrder = new Map([...select.selectedOptions].map((option, index) => [option, index]));
Array.from(select.options)
.sort((a, b) =>
Number(b.selected) - Number(a.selected) || (a.selected && b.selected)
? selectedOrder.get(a) - selectedOrder.get(b)
: optionOrder.get(a) - optionOrder.get(b),
)
.forEach((option) => select.append(option));
});
</script> <nve-combobox id="combobox-selected-first" style="width: 500px; --scroll-height: 220px">
<label>label</label>
<input type="search" />
<select multiple>
<option value="status"></option>
<option value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
<option value="includes"></option>
<option value="user"></option>
<option value="progress"></option>
</select>
<nve-control-message>message</nve-control-message>
</nve-combobox>
<script type="module">
const combobox = document.querySelector("#combobox-selected-first");
const select = combobox.querySelector("select");
const optionOrder = new Map([...select.options].map((option, index) => [option, index]));
combobox.addEventListener("open", () => {
const selectedOrder = new Map([...select.selectedOptions].map((option, index) => [option, index]));
Array.from(select.options)
.sort((a, b) =>
Number(b.selected) - Number(a.selected) || (a.selected && b.selected)
? selectedOrder.get(a) - selectedOrder.get(b)
: optionOrder.get(a) - optionOrder.get(b),
)
.forEach((option) => select.append(option));
});
</script>
label message
Empty Default Option Label Overflow Overflow Wrap \n"}
Infinite scroll combobox loading, using the scroll event to append options as the user nears the end of the list. Use for server-backed datasets where loading all options up front is impractical.
<nve-combobox id="infinite-scroll-combo" style="--scroll-height: 200px">
<label>GPU Models</label>
<input type="search" placeholder="Scroll to load more…" />
<datalist id="infinite-scroll-list"></datalist>
</nve-combobox>
<script type="module">
const combo = document.getElementById("infinite-scroll-combo");
const datalist = document.getElementById("infinite-scroll-list");
let loading = false;
async function loadBatch() {
if (loading) return;
loading = true;
const items = await new Promise((resolve) =>
setTimeout(
() => resolve(Array.from({ length: 100 }, (_, i) => "GPU Model " + (datalist.options.length + i + 1))),
300,
),
);
datalist.append(...items.map((v) => new Option(v)));
loading = false;
}
loadBatch();
combo.addEventListener("scroll", (e) => {
if (e.detail.scrollHeight - e.detail.scrollTop - e.detail.clientHeight <= 128) {
loadBatch();
}
});
</script> <nve-combobox id="infinite-scroll-combo" style="--scroll-height: 200px">
<label>GPU Models</label>
<input type="search" placeholder="Scroll to load more…" />
<datalist id="infinite-scroll-list"></datalist>
</nve-combobox>
<script type="module">
const combo = document.getElementById("infinite-scroll-combo");
const datalist = document.getElementById("infinite-scroll-list");
let loading = false;
async function loadBatch() {
if (loading) return;
loading = true;
const items = await new Promise((resolve) =>
setTimeout(
() => resolve(Array.from({ length: 100 }, (_, i) => "GPU Model " + (datalist.options.length + i + 1))),
300,
),
);
datalist.append(...items.map((v) => new Option(v)));
loading = false;
}
loadBatch();
combo.addEventListener("scroll", (e) => {
if (e.detail.scrollHeight - e.detail.scrollTop - e.detail.clientHeight <= 128) {
loadBatch();
}
});
</script>
GPU Models
Create Options \n"}
Combobox with create option behavior that allows users to add new options and tags on the fly. Use when the option list is not exhaustive and users need to enter values that don't yet exist.
<nve-combobox id="creatable-combo" behavior-create style="--scroll-height: 220px">
<label>Tags</label>
<input type="search" placeholder="Select or create a tag…" />
<select multiple>
<option value="Go">Go</option>
<option value="Rust">Rust</option>
<option value="Python">Python</option>
<option value="JavaScript">JavaScript</option>
<option value="TypeScript">TypeScript</option>
<option value="Java">Java</option>
<option value="C#">C#</option>
<option value="C++">C++</option>
<option value="C">C</option>
<option value="PHP">PHP</option>
</select>
<nve-control-message>Press Enter to create a tag that doesn't exist yet</nve-control-message>
</nve-combobox>
<script type="module">
const combobox = document.getElementById("creatable-combo");
const select = combobox.querySelector("select");
combobox.addEventListener("create", (e) => {
const option = document.createElement("option");
option.value = e.detail.value;
option.textContent = e.detail.value;
option.selected = true;
select.appendChild(option);
});
</script> <nve-combobox id="creatable-combo" behavior-create style="--scroll-height: 220px">
<label>Tags</label>
<input type="search" placeholder="Select or create a tag…" />
<select multiple>
<option value="Go">Go</option>
<option value="Rust">Rust</option>
<option value="Python">Python</option>
<option value="JavaScript">JavaScript</option>
<option value="TypeScript">TypeScript</option>
<option value="Java">Java</option>
<option value="C#">C#</option>
<option value="C++">C++</option>
<option value="C">C</option>
<option value="PHP">PHP</option>
</select>
<nve-control-message>Press Enter to create a tag that doesn't exist yet</nve-control-message>
</nve-combobox>
<script type="module">
const combobox = document.getElementById("creatable-combo");
const select = combobox.querySelector("select");
combobox.addEventListener("create", (e) => {
const option = document.createElement("option");
option.value = e.detail.value;
option.textContent = e.detail.value;
option.selected = true;
select.appendChild(option);
});
</script>
Tags Go Rust Python JavaScript TypeScript Java C# C++ C PHP Press Enter to create a tag that doesn't exist yet
Layout Controls the directional arrangement and spacing behavior of the element's content.
Layout Description vertical Arranges content in a vertical stack with block-level spacing. vertical-inline Arranges content vertically with compact inline spacing for dense layouts. horizontal Arranges content in a horizontal row with block-level spacing. horizontal-inline Arranges content horizontally with compact inline spacing. Vertical Vertical layout showing different combobox states (normal, disabled, success, error) stacked for comparison.
<div nve-layout="column gap:lg full">
<nve-combobox>
<label>label</label>
<input type="search" />
<datalist>
<option value="status"></option>
<option value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
</datalist>
<nve-control-message>message</nve-control-message>
</nve-combobox>
<nve-combobox>
<label>disabled</label>
<input type="search" disabled />
<datalist>
<option value="status"></option>
<option value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
</datalist>
<nve-control-message>message</nve-control-message>
</nve-combobox>
<nve-combobox>
<label>success</label>
<input type="search" />
<datalist>
<option value="status"></option>
<option value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
</datalist>
<nve-control-message status="success">message</nve-control-message>
</nve-combobox>
<nve-combobox>
<label>error</label>
<input type="search" />
<datalist>
<option value="status"></option>
<option value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
</datalist>
<nve-control-message status="error">message</nve-control-message>
</nve-combobox>
</div> <div nve-layout="column gap:lg full">
<nve-combobox>
<label>label</label>
<input type="search" />
<datalist>
<option value="status"></option>
<option value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
</datalist>
<nve-control-message>message</nve-control-message>
</nve-combobox>
<nve-combobox>
<label>disabled</label>
<input type="search" disabled />
<datalist>
<option value="status"></option>
<option value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
</datalist>
<nve-control-message>message</nve-control-message>
</nve-combobox>
<nve-combobox>
<label>success</label>
<input type="search" />
<datalist>
<option value="status"></option>
<option value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
</datalist>
<nve-control-message status="success">message</nve-control-message>
</nve-combobox>
<nve-combobox>
<label>error</label>
<input type="search" />
<datalist>
<option value="status"></option>
<option value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
</datalist>
<nve-control-message status="error">message</nve-control-message>
</nve-combobox>
</div>
Horizontal Horizontal layout showing different combobox states (normal, disabled, success, error) for inline form layouts.
<div nve-layout="column gap:lg full">
<nve-combobox layout="horizontal">
<label>label</label>
<input type="search" />
<datalist>
<option value="status"></option>
<option value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
</datalist>
<nve-control-message>message</nve-control-message>
</nve-combobox>
<nve-combobox layout="horizontal">
<label>disabled</label>
<input type="search" disabled />
<datalist>
<option value="status"></option>
<option value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
</datalist>
<nve-control-message>message</nve-control-message>
</nve-combobox>
<nve-combobox layout="horizontal">
<label>success</label>
<input type="search" />
<datalist>
<option value="status"></option>
<option value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
</datalist>
<nve-control-message status="success">message</nve-control-message>
</nve-combobox>
<nve-combobox layout="horizontal">
<label>error</label>
<input type="search" />
<datalist>
<option value="status"></option>
<option value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
</datalist>
<nve-control-message status="error">message</nve-control-message>
</nve-combobox>
</div> <div nve-layout="column gap:lg full">
<nve-combobox layout="horizontal">
<label>label</label>
<input type="search" />
<datalist>
<option value="status"></option>
<option value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
</datalist>
<nve-control-message>message</nve-control-message>
</nve-combobox>
<nve-combobox layout="horizontal">
<label>disabled</label>
<input type="search" disabled />
<datalist>
<option value="status"></option>
<option value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
</datalist>
<nve-control-message>message</nve-control-message>
</nve-combobox>
<nve-combobox layout="horizontal">
<label>success</label>
<input type="search" />
<datalist>
<option value="status"></option>
<option value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
</datalist>
<nve-control-message status="success">message</nve-control-message>
</nve-combobox>
<nve-combobox layout="horizontal">
<label>error</label>
<input type="search" />
<datalist>
<option value="status"></option>
<option value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
</datalist>
<nve-control-message status="error">message</nve-control-message>
</nve-combobox>
</div>
Container Reduces the visual container for a minimal borderless appearance while preserving whitespace bounds.Use when embedding within another container such as a toolbar.
Container Description flat Flat slot for dropdown footer content
Multi-select with footer action button for extra operations on selected items.
<nve-combobox style="width: 500px; --scroll-height: 200px">
<label>label</label>
<input type="search" />
<select multiple>
<option value="status"></option>
<option value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
<option value="includes"></option>
<option value="user"></option>
<option value="progress"></option>
</select>
<nve-button slot="footer" container="flat">action</nve-button>
<nve-control-message>message</nve-control-message>
</nve-combobox> \n"}
Complete form integration showing combobox with form submission, reset, and programmatic value setting.
<form nve-layout="column gap:lg align:stretch">
<nve-combobox style="--scroll-height: 220px">
<label>label</label>
<input type="search" name="input" />
<select multiple name="select" value="priority">
<option value="status"></option>
<option selected value="priority"></option>
<option selected value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
</select>
<nve-control-message>message</nve-control-message>
</nve-combobox>
<div nve-layout="row gap:xs">
<nve-button type="button">set</nve-button>
<nve-button type="reset">reset</nve-button>
<nve-button type="submit">submit</nve-button>
</div>
</form>
<script type="module">
const form = document.querySelector("form");
const select = document.querySelector("select");
const input = document.querySelector("input");
const btn = document.querySelector("[type=button]");
form.addEventListener("submit", (e) => {
e.preventDefault();
const formData = new FormData(form);
console.log("input: ", formData.get("input"));
console.log("select: ", formData.get("select"));
console.log(
"selectedOptions: ",
Array.from(select.selectedOptions).map((o) => o.value),
);
});
btn.addEventListener("click", () => {
select.value = "status";
select.options[0].selected = true;
input.value = "test";
});
</script> <form nve-layout="column gap:lg align:stretch">
<nve-combobox style="--scroll-height: 220px">
<label>label</label>
<input type="search" name="input" />
<select multiple name="select" value="priority">
<option value="status"></option>
<option selected value="priority"></option>
<option selected value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
</select>
<nve-control-message>message</nve-control-message>
</nve-combobox>
<div nve-layout="row gap:xs">
<nve-button type="button">set</nve-button>
<nve-button type="reset">reset</nve-button>
<nve-button type="submit">submit</nve-button>
</div>
</form>
<script type="module">
const form = document.querySelector("form");
const select = document.querySelector("select");
const input = document.querySelector("input");
const btn = document.querySelector("[type=button]");
form.addEventListener("submit", (e) => {
e.preventDefault();
const formData = new FormData(form);
console.log("input: ", formData.get("input"));
console.log("select: ", formData.get("select"));
console.log(
"selectedOptions: ",
Array.from(select.selectedOptions).map((o) => o.value),
);
});
btn.addEventListener("click", () => {
select.value = "status";
select.options[0].selected = true;
input.value = "test";
});
</script>
Reset Resets control value to initial attribute value and clears any active validation rules.
\n"}
Multi-select with reset functionality via icon button and footer button to clear all selections.
<nve-combobox id="combobox-reset" style="width: 500px; --scroll-height: 220px">
<label>label</label>
<input type="search" />
<select multiple>
<option value="status"></option>
<option value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
</select>
<nve-icon-button aria-label="clear selection" icon-name="cancel" container="inline"></nve-icon-button>
<nve-button slot="footer" aria-label="clear selection" container="flat">reset</nve-button>
<nve-control-message>message</nve-control-message>
</nve-combobox>
<script type="module">
document
.querySelector("#combobox-reset nve-icon-button")
.addEventListener("click", (e) => e.target.parentElement.reset());
document.querySelector("#combobox-reset nve-button").addEventListener("click", (e) => e.target.parentElement.reset());
</script> <nve-combobox id="combobox-reset" style="width: 500px; --scroll-height: 220px">
<label>label</label>
<input type="search" />
<select multiple>
<option value="status"></option>
<option value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
</select>
<nve-icon-button aria-label="clear selection" icon-name="cancel" container="inline"></nve-icon-button>
<nve-button slot="footer" aria-label="clear selection" container="flat">reset</nve-button>
<nve-control-message>message</nve-control-message>
</nve-combobox>
<script type="module">
document
.querySelector("#combobox-reset nve-icon-button")
.addEventListener("click", (e) => e.target.parentElement.reset());
document.querySelector("#combobox-reset nve-button").addEventListener("click", (e) => e.target.parentElement.reset());
</script>
label reset message
Disabled Options Manage inline tag rendering for many-item select
TagLayout Description hidden wrap \n"}
Multi-select without built-in tags, using external tag management for custom selection display.
<form id="hidden-tags" nve-layout="column gap:lg align:stretch">
<nve-combobox tag-layout="hidden">
<label>label</label>
<input type="search" />
<select multiple>
<option selected value="status"></option>
<option selected value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
</select>
</nve-combobox>
<div id="tags" nve-layout="row gap:xs"></div>
</form>
<script type="module">
const form = document.querySelector("#hidden-tags");
const select = form.querySelector("select");
const tags = form.querySelector("#tags");
updateTags();
select.addEventListener("change", (e) => updateTags());
tags.addEventListener("close", (e) => {
Array.from(select.options).find((o) => o.value === e.target.value).selected = false;
updateTags();
});
function updateTags() {
tags.innerHTML = "";
Array.from(select.selectedOptions).forEach(
(o) => (tags.innerHTML += '<nve-tag closable value="' + o.value + '">' + o.value + "</nve-tag>"),
);
}
</script> <form id="hidden-tags" nve-layout="column gap:lg align:stretch">
<nve-combobox tag-layout="hidden">
<label>label</label>
<input type="search" />
<select multiple>
<option selected value="status"></option>
<option selected value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
</select>
</nve-combobox>
<div id="tags" nve-layout="row gap:xs"></div>
</form>
<script type="module">
const form = document.querySelector("#hidden-tags");
const select = form.querySelector("select");
const tags = form.querySelector("#tags");
updateTags();
select.addEventListener("change", (e) => updateTags());
tags.addEventListener("close", (e) => {
Array.from(select.options).find((o) => o.value === e.target.value).selected = false;
updateTags();
});
function updateTags() {
tags.innerHTML = "";
Array.from(select.selectedOptions).forEach(
(o) => (tags.innerHTML += '<nve-tag closable value="' + o.value + '">' + o.value + "</nve-tag>"),
);
}
</script>
Select All Select all options provided
\n"}
Multi-select with bulk selection controls (Select All/Deselect All) in footer for efficient mass operations.
<nve-combobox id="combobox-select-all" style="width: 500px; --scroll-height: 200px">
<label>label</label>
<input type="search" />
<select multiple>
<option value="status"></option>
<option value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
<option value="includes"></option>
<option value="user"></option>
<option value="progress"></option>
</select>
<div slot="footer" nve-layout="row align:stretch full">
<nve-button container="flat">Select All</nve-button>
<nve-button container="flat">Deselect All</nve-button>
</div>
<nve-control-message>message</nve-control-message>
</nve-combobox>
<script type="module">
const combobox = document.querySelector("#combobox-select-all");
const [selectAll, deselectAll] = Array.from(combobox.querySelectorAll("nve-button"));
selectAll.addEventListener("click", () => combobox.selectAll());
deselectAll.addEventListener("click", () => combobox.reset());
combobox.addEventListener("change", (e) => console.log(e.target.selectedOptions));
</script> <nve-combobox id="combobox-select-all" style="width: 500px; --scroll-height: 200px">
<label>label</label>
<input type="search" />
<select multiple>
<option value="status"></option>
<option value="priority"></option>
<option value="date"></option>
<option value="session"></option>
<option value="configuration"></option>
<option value="contains"></option>
<option value="includes"></option>
<option value="user"></option>
<option value="progress"></option>
</select>
<div slot="footer" nve-layout="row align:stretch full">
<nve-button container="flat">Select All</nve-button>
<nve-button container="flat">Deselect All</nve-button>
</div>
<nve-control-message>message</nve-control-message>
</nve-combobox>
<script type="module">
const combobox = document.querySelector("#combobox-select-all");
const [selectAll, deselectAll] = Array.from(combobox.querySelectorAll("nve-button"));
selectAll.addEventListener("click", () => combobox.selectAll());
deselectAll.addEventListener("click", () => combobox.reset());
combobox.addEventListener("change", (e) => console.log(e.target.selectedOptions));
</script>
Release Status All elements and features go through 3 phases of stability, pre-release, beta and stable.
pre-release Docs Preview API Documentation Fully Themeable
beta Robust unit test coverages Passed API Review Passed Designer VQA Review Included in library package stable No known outstanding AA WCAG issues No known outstanding performance issues Adapts to different screen/container sizes No breaking API changes for at least 90 days