Combobox New Alpha Light DOM & Tailwind
Lets users choose one or several options from a list by typing to filter, then picking with the keyboard or pointer.
Usage
Combobox lets people choose one option (or several) from a list by typing to filter, then picking with the keyboard or pointer. Reach for it when a Select would be unwieldy because there are many options to scan.
Combobox renders its built-in label, hint and error on its own. Wrapped in a Field, the Field takes over with a Field Label, Field Description and Field Error, and the built-in versions step aside automatically.
Import the combobox; add the option parts when you author options declaratively (importing the combobox also registers them):
import "@nordhealth/components/lib/Combobox"
import "@nordhealth/components/lib/ComboboxOption"
import "@nordhealth/components/lib/ComboboxGroup"
Options can be authored declaratively as child elements or set as a data array — see Composition.
For a free-text input with suggestions (where the typed text is the value), see Autocomplete.
Standalone or inside a Field
Use the control on its own with its built-in label, hint and error, or wrap it in a Field — the Field then provides the labelling. Both render the same control:
Composition
There are two ways to supply options. Author them declaratively as children of <nord-combobox>, like a native <select> — no JavaScript required — or set the .options property for dynamic data.
Combobox
├── ComboboxOption
├── ComboboxOption
└── ComboboxGroup (optional)
├── ComboboxOption
└── ComboboxOption
<nord-combobox>
<nord-combobox-option value="next">Next.js</nord-combobox-option>
<nord-combobox-group label="Meta-frameworks">
<nord-combobox-option value="astro">Astro</nord-combobox-option>
</nord-combobox-group>
</nord-combobox>
Combobox Option
<nord-combobox-option> declares a single option:
value— the value submitted with the form and tracked in the combobox'svalue.disabled— marks the option unselectable; it stays visible but is skipped during keyboard navigation.label— text used for filtering and the accessible name. Defaults to the element's text content.
The option's child markup becomes the rendered row, so you can author custom items — an avatar, secondary text, an icon — without an html string or a render function. Set label when the content isn't plain text, so filtering and the accessible name have something to match on.
Combobox Group
<nord-combobox-group label="…"> clusters the <nord-combobox-option> children inside it under a heading; each contained option inherits the group's label.
Combobox
└── ComboboxGroup (label)
├── ComboboxOption
└── ComboboxOption
Data-driven options
For dynamic, async or very large (virtualized) lists, set the .options property — an array of { value, label } objects — instead of declaring children. It's bound like any framework prop: :options in Vue, options={} in React, .options=${} in Lit. When .options is set it takes precedence over any declarative children.
Examples
Multiple
Add multiple to select several options. Selected options appear as removable chips. Pair it with clearable when users need to clear all selected chips at once. Set the initial selection with the .value property as an array.
Creatable
Add creatable to offer the typed query as a new option. When the query doesn't match an existing option, a highlighted "Create" row (hinted with a ⏎ Kbd) appears; selecting it adds the value as an option and selects it automatically — no JavaScript required. A create event still fires for notification; call event.preventDefault() in the handler to opt out and add the option yourself (for example, to map the typed text to a different value).
Async search
Add external-filtering to take over filtering yourself — listen for input, fetch matches, and assign them to .options. Set loading to show a spinner while the request is in flight. A preselected value keeps its label even before its option has loaded.
Async search (multiple)
The same async pattern works with multiple: selections become chips while typing fetches fresh matches. Use clearable to offer one-step clearing for the selected chips.
Virtualized
Add virtualized for very large lists. The combobox renders only the options in view (windowing), so a list of thousands stays fast. Rows are assumed to be a uniform height; virtualization is skipped for grouped lists.
Clearable
A clear (✕) button is shown by default whenever there is a value. Set the clearable property to false (e.g. .clearable = false, or :clearable="false" / clearable={false} in a framework) to hide it. The button only controls that affordance — a single-select value can always be cleared by deleting the input text.
Grouped options
Cluster related options under a heading: wrap declarative options in a <nord-combobox-group label="…">, or give each .options entry a group.
Auto highlight
Add auto-highlight to highlight the first matching option as the user types, so it can be committed by pressing Enter.
Invalid
Mark the surrounding Field as invalid to show the error state.
Custom items
For declarative options, author custom content as markup inside <nord-combobox-option> (see Composition). For data-driven .options, provide a .renderOption function (or a per-option html string) to render richer rows.
Disabled items
Mark individual options with disabled to keep them visible but unselectable. They are skipped during keyboard navigation.
Readonly
Set readonly to show the current value while preventing edits. The control stays focusable so its value can still be read, but the list cannot be opened.
Open on focus
By default the list opens when the combobox receives focus. Set open-on-focus to false to require a keystroke or click before the list appears.
Input group
Combobox composes inside an Input Group so you can pair it with buttons or other controls as a single unit.
Preselected value
Set the .value property to preselect an option. The combobox shows its label on load, even before the user opens the list.
Inside a dialog
Combobox positions its list correctly when used inside a Modal or other dialog, so the options are never clipped by the dialog bounds.
RTL
Combobox follows the document or container direction. Toggle the direction to see the layout mirror.
Accessibility
- Give Combobox an accessible name with its built-in
label, or — inside a Field — a Field Label; use Field Error for validation messages. - The list, active option and selection state are wired up with ARIA, and the highlighted option is tracked with
aria-activedescendantso screen reader users hear the current choice while filtering. - The full keyboard pattern is supported: type to filter, move through options with the arrow keys, commit with Enter, and dismiss the list with Escape.
- When
clearableis set, the clear button has an accessible label so its purpose is announced.
API reference
Combobox
Combobox lets users choose one option (or several) from a list by typing to
filter, then picking with the keyboard or pointer. Use it when a Select
would be unwieldy because there are many options to scan.
Combobox is a control only — it has no built-in label, hint or error. Compose
it inside a Field to give it a label, hint and error
message, the same way you would a native input.
The committed value is an option's value (or an array of them with
multiple); the input is a filter/search field whose text is discarded on
commit. For a free-text input with suggestions where the typed text is the
value, use Autocomplete instead.
<nord-combobox></nord-combobox>Props
| Property | Attribute | Description | Type | Default |
|---|---|---|---|---|
value | value | The value of the combobox. A single string when multiple is false,
or an array of strings when multiple is true. | string | '' |
multiple | multiple | Allows selecting more than one option. Selected options are shown as removable chips and the listbox stays open after each selection. | boolean | false |
clearable | clearable | Shows a clear (✕) button while there is a value. Pressing it resets the
value to '' (or [] when multiple), then fires clear and change.
Defaults to true.
This prop only toggles the button. A single-select value can always be
cleared by deleting the input text, regardless of this prop (Base UI
parity). | boolean | true |
creatable | creatable | Offers a "Create" affordance when the query does not exactly match an
existing option. Choosing it (click or Enter) adds the typed value as an
option and selects it (in multiple mode it is appended as a chip), and
fires a cancelable create event. Call event.preventDefault() to opt out
and handle creation yourself (e.g. to map the value to a different value). | boolean | false |
size | size | The size of the component. | 's' | 'm' | 'l' | 'm' |
autocomplete | autocomplete | Specifies the data type of the field, so that the browser may attempt to fill out the field automatically on behalf of the user. | AutocompleteAttribute | 'off' |
required | required | Determines whether the control is required or not.
A required control is announced as such to assistive technology and, inside
a <nord-field>, drives the required indicator on the <nord-field-label>.
When using this property you need to also set “novalidate” attribute on a form element to prevent browser from displaying its own validation errors. | boolean | false |
disabled | disabled | Makes the component disabled. This prevents users from being able to interact with the component, and conveys its inactive state to assistive technologies. | boolean | false |
name | name | The name of the form component. | string | undefined | — |
form | form | Gets the form, if any, associated with the form element. The setter accepts a string, which is the id of the form. | HTMLFormElement | null | — |
open | open | Controls whether the component is open or not. | boolean | false |
align | align | Set the alignment in relation to the toggle (or anchor) depending on the position.
start will align it to the left of the toggle (or anchor).
end will align it to the right of the toggle (or anchor).
Setting the position to inline-start or inline-end will switch
start and end to the top and bottom respectively. | 'start' | 'end' | 'start' |
position | position | Set the position in relation to the toggle (or anchor).
Options follow logical properties.
block-start and block-end referring to top and bottom respectively,
inline-start and inline-end referring to left and right respectively.
You can also set it to auto for automatic positioning depending on
which side has the most space available. | 'block-end' | 'block-start' | 'inline-start' | 'inline-end' | 'auto' | 'block-end' |
sideOffset | side-offset | Distance in pixels from the toggle (or anchor) along the main axis — the
gap between the floating element and the side it opens against. Fed into
Floating UI's offset middleware as mainAxis. Defaults to 8. | number | 8 |
alignOffset | align-offset | Offset in pixels along the alignment axis — slides the floating element
toward the start or end of the toggle (or anchor). Fed into Floating
UI's offset middleware as alignmentAxis. Defaults to 0. | number | 0 |
placeholder | placeholder | Placeholder text to display within the input. | string | undefined | — |
externalFiltering | external-filtering | Use external filtering mode. When set to true, the component will not
perform internal text-based filtering and expects the consumer to update
the options in response to the input event. | boolean | false |
loading | loading | Shows a spinner in the control and listbox while asynchronous results are
loading. Pair with external-filtering for async search. | boolean | false |
autoHighlight | auto-highlight | Highlights the first option after filtering so pressing Enter selects it. | boolean | false |
invalid | invalid | Marks the control as invalid, applying error styling and setting
aria-invalid on the input. | boolean | false |
readonly | readonly | Marks the control read-only: the value stays visible, focusable and
submitted with the form, but the listbox can't be opened and the value can't
be changed (no typing, navigation, selection or clearing). Unlike disabled,
a read-only control still participates in form submission. | boolean | false |
openOnFocus | open-on-focus | Whether focusing or clicking into the input opens the listbox. Defaults to
true. Set to false to only open on typing or a trigger (chevron) click. | boolean | true |
noResultsText | no-results-text | Message shown when no options match the query. Defaults to "No items found.". | string | undefined | — |
virtualized | virtualized | Virtualizes (windows) the option list so only the rows in view are rendered, keeping very large lists (thousands of options) fast. Rows are assumed to be a uniform height, which is measured from the first option. Virtualization is skipped for grouped lists, whose labels and separators break that assumption — grouped lists are expected to be short and curated. | boolean | false |
Field properties
| Property | Attribute | Description | Type | Default |
|---|---|---|---|---|
label | label | Label for the control. Ignored when the control is wrapped in a
<nord-field>, which provides the label via <nord-field-label>. | string | '' |
hint | hint | Optional hint text shown with the control. Ignored inside a <nord-field>,
which provides it via <nord-field-description>. | string | undefined | — |
hintBelow | hint-below | Renders the hint below the control and any error instead of below the label. | boolean | false |
hideLabel | hide-label | Visually hide the label, but still expose it to assistive technologies. | boolean | false |
error | error | Optional error shown with the control. Ignored inside a <nord-field>,
which provides it via <nord-field-error>. | string | undefined | — |
hideRequired | hide-required | Visually hide the required indicator, but still expose the required state to assistive technologies. | boolean | false |
Slots
| Slot name | Description |
|---|---|
start | Optional slot used to place an icon or prefix at the start of the control. |
end | Optional slot used to place an icon or suffix at the end of the control. |
Methods
| Method name | Parameters | Description |
|---|---|---|
show() => void | N/A | Show the listbox programmatically. |
hide() => void | N/A | Hide the listbox programmatically. |
focus(options?: FocusOptions) => void | options: FocusOptions | Focus the control's input. |
| Event | Detail Type | Description |
|---|---|---|
change | NordEvent | Dispatched when the committed value changes via user interaction. |
input | NordEvent | Dispatched as the user types into the search input. |
open | NordEvent | Dispatched when the listbox is opened. |
close | NordEvent | Dispatched when the listbox is closed. |
clear | ComboboxClearEvent | Dispatched when the value is cleared via the clear button or clear(). |
create | ComboboxCreateEvent | Dispatched when the user chooses the "Create" affordance in a creatable combobox. |
CSS Properties
CSS Custom Properties provide more fine grain control over component presentation. We advise utilizing existing properties on the component before using these.
| Property | Description | Default |
|---|---|---|
--n-combobox-list-inline-size | Controls the inline size, or width, of the dropdown list. Defaults to the width of the combobox control. | — |
--n-combobox-block-size | Controls the block size, or height, of the control. The medium default is var(--n-space-xl); the s and l sizes scale from it. | — |
State attributes
These data-* attributes are set by the component to reflect its current state. Use them as styling hooks — they are read-only and should not be set manually.
| Attribute | Description |
|---|---|
data-invalid | Present while the control is invalid (mirrors the invalid property). Style hook for the whole control. |
data-focused | Present while the control has focus. Style hook for focus-within treatments. |
Parts
This component is made up of the following parts.
Combobox Group
Groups declarative <nord-combobox-option> children under a heading inside a
Combobox:
``html
<nord-combobox>
<nord-combobox-group label="Frameworks">
<nord-combobox-option value="next">Next.js</nord-combobox-option>
</nord-combobox-group>
</nord-combobox>
`
Contained options inherit this label as their group. The element renders
nothing itself and is hidden with display: none`.
<nord-combobox-group></nord-combobox-group>Props
| Property | Attribute | Description | Type | Default |
|---|---|---|---|---|
label | label | The group heading shown above its options. | string | '' |
Slots
| Slot name | Description |
|---|---|
Default slot | The group's <nord-combobox-option> children. |
Combobox Option
A declarative option for a Combobox. Place these as
children of <nord-combobox> instead of (or as an alternative to) setting the
.options property:
``html
<nord-combobox>
<nord-combobox-option value="bug">Bug</nord-combobox-option>
<nord-combobox-option value="feature">Feature</nord-combobox-option>
</nord-combobox>
`
The option's child markup becomes the rendered row, so you can author custom
items (e.g. an avatar + text) without an html string or a render function.
Set the label attribute when the visible markup isn't plain text, so
filtering and the accessible name have something to match on.
The element renders nothing itself — it is a data source the combobox reads via
context and is hidden with display: none`.
<nord-combobox-option></nord-combobox-option>Props
| Property | Attribute | Description | Type | Default |
|---|---|---|---|---|
value | value | The value submitted with the form and tracked in the combobox's value. | string | '' |
disabled | disabled | Whether the option is selectable. | boolean | false |
label | label | Text used for filtering and the accessible name. Defaults to the text content. | string | undefined | — |
Slots
| Slot name | Description |
|---|---|
Default slot | The option's label / custom content. |
Dependencies
This component is internally dependent on the following components:
- <nord-icon>
Icon
Icons are used to provide additional meaning or in places where text label doesn’t fit. Icon component allows you to display an icon from the Nordicons library.
- <nord-kbd>
Kbd
Kbd is used to display a keyboard key, such as a shortcut or a key the user should press. Group related keys together with Kbd Group.
- <nord-tag>
Tag
Tags represent a set of keywords that help label, categorize, and organize objects. Commonly used to signify the attributes of an object.
Design guidelinesFor designers
Usage
Combobox is a control only — it has no built-in label, hint or error. Pair it with a Field to give it a label, helper text and an error message, exactly like a native input. Connect the Field Label to the combobox with the for attribute so it gets an accessible name and click-to-focus.
Import the combobox and the Field parts you need — each import registers its custom element:
import '@nordhealth/components/lib/Combobox'
import '@nordhealth/components/lib/Field'
import '@nordhealth/components/lib/FieldLabel'
import '@nordhealth/components/lib/FieldDescription'
import '@nordhealth/components/lib/FieldError'
Then compose the Field around the combobox:
<nord-field>
<nord-field-label for="framework">Framework</nord-field-label>
<nord-combobox id="framework" placeholder="Select a framework"></nord-combobox>
<nord-field-description>Choose the framework for your project.</nord-field-description>
<!-- show a Field Error and mark the Field invalid instead, when validation fails -->
</nord-field>
Provide the choices with the options property — pairing it with a Field only handles labelling and layout, it doesn't change how you populate the list:
document.querySelector('nord-combobox').options = [
{ value: 'next', label: 'Next.js' },
{ value: 'astro', label: 'Astro' },
]
Combobox renders in the light DOM, so you can style it directly with your own CSS or Tailwind utilities, and set its width on the combobox (or on its Field).
Use the size property (s, m or l, defaulting to m) to scale the control's height, padding and font size to match surrounding form controls.
Select vs free-text suggestions
The committed value is an option's value. The input is a search/filter field whose text is discarded on commit; closing the listbox reverts the input to the selected option's label. Nothing is committed unless the user picks an option, so the value is always one of the options you provide (or an array of them with multiple).
If you instead need the typed text itself to be the committed value — free-text input with the options as completion aids — use Autocomplete. Autocomplete also offers inline ghost-text completion, where arrow-key navigation previews the highlighted option's remaining label.
Picking an option vs creating one
Both multiple and creatable keep the value made of option values — they never produce arbitrary free text (use Autocomplete for that):
multiplelets users pick several options, each shown as a removable chip; the listbox stays open after every selection.creatableoffers a Create row (hinted with a ⏎ Kbd) when the query matches no option. Choosing it fires acreateevent so you add the option — the combobox never mutatesoptions. Withmultiple, append the created option tovalueyourself.
The inner input always hard-codes autocomplete="off" so browser autofill never fights the suggestion list.
Do
- Use when users need to pick from a long list of options and benefit from typing to filter, such as countries, timezones or frameworks.
- Pair it with a Field and a Field Label connected with
for, so it has an accessible name, helper text and an error message. - Use
multiplewhen users may legitimately pick more than one option, showing each choice as a removable chip. - Use
external-filteringand updateoptionsfrom theinputevent when the list comes from a server or is too large to filter on the client. - Group related options with the
groupproperty to help users scan long lists.
Don’t
- Don’t use when there are only a handful of options and filtering adds no value, see Select instead.
- Don’t add a Field Label without a
forpointing at the combobox’sid, or the control will have no accessible name. - Don’t use for free-form text entry, see Input instead.
- Don’t use to trigger actions or commands, see Command Menu instead.