Dropdown combobox
Displays a text input that filters a dropdown list of options, with keyboard navigation and optional async search. For form usage, prefer the ComboboxField component instead.
Component
Props
| Props | Required | Default | Type |
|---|---|---|---|
id | true | — | string |
ariaLabel | — | — | string |
options | — | [] | SelectOption[] |
placeholder | — | 'Select an option' | string |
type | — | SelectType.TEXT | SelectType |
size | — | SelectSize.MD | SelectSize |
activeStyle | — | SelectActiveStyle.CHECK | SelectActiveStyle |
modelValue | — | null | string | number | (string | number)[] | null |
dropdownPosition | — | Position.BOTTOM | Position |
autoFlip | — | true | boolean |
selectBoxClass | — | — | string |
noResultsFoundText | — | 'No results found' | string |
disabled | — | false | boolean |
readonly | — | false | boolean |
hasSeparator | — | false | boolean |
multiple | — | false | boolean |
allowDeselect | — | false | boolean |
allowCustomValue | — | false | boolean |
clearable | — | true | boolean |
filterLocally | — | true | boolean |
searchDebounce | — | 300 | number |
isLoading | — | false | boolean |
loadingText | — | 'Loading options...' | string |
clearSelectionAriaLabel | — | 'Clear selection' | string |
transparent | — | false | boolean |
shouldTeleport | — | false | boolean |
teleportTo | — | 'body' | string |
Usage
id
Sets the id of the input. It is also used to build the ids of the listbox and its options for assistive technologies.
<template>
<DropdownCombobox id="fruit" />
</template>
ariaLabel
Sets the accessible label of the input. Use it when there is no visible <label> associated with the input.
<template>
<DropdownCombobox id="fruit" ariaLabel="Fruit" />
</template>
options
Sets the options of the combobox. The array of options must be of type SelectOption. Options with sectionTitle: true render as section headers and are hidden while the user is filtering.
<template>
<DropdownCombobox id="fruit" :options="items" />
</template>
<script setup lang="ts">
const items: SelectOption[] = [
{ value: 'apple', text: 'Apple' },
{ value: 'banana', text: 'Banana' },
{ value: 'cherry', text: 'Cherry', disabled: true },
]
</script>
TypeScript Interface
interface SelectOption {
id?: string | number
value: string | number
sectionTitle?: boolean
text?: string
icon?: string
userDisplayName?: string
userProfileImg?: string
imgUrl?: string
alt?: string
helpText?: string
to?: string
isExternal?: boolean
disabled?: boolean
}
placeholder
Sets the placeholder text of the input. In multiple mode, the labels of the selected options replace the placeholder.
<template>
<DropdownCombobox id="fruit" placeholder="Search a fruit" />
</template>
type
Sets how the options are rendered in the list. It uses the SelectType enum. The input always shows the text of the selected option.
<template>
<DropdownCombobox id="fruit" :type="SelectType.ICON" :options="items" />
</template>
Options
| Value | Description |
|---|---|
TEXT | Options with text |
ICON | Options with icon and text |
USER | Options with user avatar and username |
IMAGE | Options with image and text |
size
Sets the size of the combobox. It uses the SelectSize enum.
<template>
<DropdownCombobox id="fruit" :size="SelectSize.LG" />
</template>
Options
| Value | Description |
|---|---|
MD | md |
LG | lg |
activeStyle
Sets the style of the selected option in the list. It uses the SelectActiveStyle enum.
<template>
<DropdownCombobox id="fruit" :activeStyle="SelectActiveStyle.FILL" />
</template>
Options
| Value | Description |
|---|---|
CHECK | Displays a checkmark next to the selected option |
FILL | Fills the background of the selected option |
modelValue
Sets the selected value. Use v-model to bind it. With multiple, the value is an array.
<template>
<DropdownCombobox id="fruit" v-model="fruit" :options="items" />
</template>
<script setup lang="ts">
const fruit = ref<string | number | (string | number)[] | null>(null)
</script>
dropdownPosition
Sets the position of the list relative to the input. It uses the Position enum.
<template>
<DropdownCombobox id="fruit" :dropdownPosition="Position.TOP" />
</template>
Options
| Value | Description |
|---|---|
TOP | Displays the list above the input |
BOTTOM | Displays the list below the input |
autoFlip
Moves the dropdown to the other side when it does not fit in the window. If it would be cut off at the bottom or the top edge of the screen and there is more room on the other side, it opens there instead. The position is checked when it opens, and dropdownPosition is only the starting point. Set it to false to always keep the position as given.
<template>
<DropdownCombobox id="fruit" :options="options" :autoFlip="false" />
</template>
selectBoxClass
Allows passing custom classes to the box that wraps the input.
<template>
<DropdownCombobox id="fruit" selectBoxClass="custom-box" />
</template>
noResultsFoundText
Sets the text displayed when no option matches the typed text.
<template>
<DropdownCombobox id="fruit" noResultsFoundText="No fruits found" />
</template>
disabled
Disables the input.
<template>
<DropdownCombobox id="fruit" disabled />
</template>
readonly
Sets the readonly state. The value is still displayed but the user cannot change it.
<template>
<DropdownCombobox readonly />
</template>
hasSeparator
Adds a separator between options in the list.
<template>
<DropdownCombobox id="fruit" hasSeparator />
</template>
multiple
Enables multiple selection. The input becomes a search box, the list stays open after each pick, and modelValue is an array.
<template>
<DropdownCombobox id="fruits" v-model="fruits" multiple />
</template>
<script setup lang="ts">
const fruits = ref<(string | number)[]>([])
</script>
allowDeselect
Allows deselecting the selected option by picking it again. Only applies to single selection.
<template>
<DropdownCombobox id="fruit" allowDeselect />
</template>
allowCustomValue
Lets the user commit text that is not part of options by pressing Enter or leaving the input. The typed text becomes the value, or is added to the array in multiple mode. If the text matches the label of an existing option, that option's value is used instead.
<template>
<DropdownCombobox id="tag" v-model="tag" :options="items" allowCustomValue />
</template>
clearable
Shows a button to clear the current value or typed text.
<template>
<DropdownCombobox id="fruit" :clearable="false" />
</template>
filterLocally
Filters options by their label while the user types. Set it to false when the options come from the server and are already filtered by the @search event.
<template>
<DropdownCombobox
id="user"
:options="results"
:filterLocally="false"
:isLoading="isSearching"
@search="fetchUsers"
/>
</template>
searchDebounce
Sets the delay, in milliseconds, between the last keystroke and the search event.
<template>
<DropdownCombobox id="user" :searchDebounce="500" @search="fetchUsers" />
</template>
isLoading
Shows a spinner in the input and replaces the list with the loading text. Use it while options are being fetched.
<template>
<DropdownCombobox id="user" :isLoading="true" />
</template>
loadingText
Sets the text displayed in the list while isLoading is true.
<template>
<DropdownCombobox id="user" isLoading loadingText="Loading options..." />
</template>
clearSelectionAriaLabel
Sets the accessible label of the clear button. Useful for i18n.
<template>
<DropdownCombobox id="fruit" clearSelectionAriaLabel="Limpiar selección" />
</template>
transparent
Removes the default background from the box, making it transparent.
<template>
<DropdownCombobox id="fruit" transparent />
</template>
shouldTeleport
Teleports the list to teleportTo instead of rendering it inside the combobox. Enable it when the combobox is inside a container with overflow-hidden or overflow-auto (such as Table), otherwise the list gets clipped.
<template>
<DropdownCombobox id="fruit" shouldTeleport />
</template>
teleportTo
Sets the teleport target selector used when shouldTeleport is true.
<template>
<DropdownCombobox id="fruit" shouldTeleport teleportTo="body" />
</template>
Accessibility
The input follows the ARIA combobox pattern: it has role="combobox", aria-expanded, aria-controls pointing to the listbox, and aria-activedescendant pointing to the highlighted option, so keyboard focus never leaves the input. The list uses role="listbox" and each option uses role="option" with aria-selected.
Provide an accessible name with a visible <label for="id"> or the ariaLabel prop. ComboboxField handles this for you.
| Value | Description |
|---|---|
Arrow Down | Opens the list, or moves the highlight to the next enabled option. It wraps around. |
Arrow Up | Opens the list, or moves the highlight to the previous enabled option. It wraps around. |
Enter | Selects the highlighted option. With `allowCustomValue`, it commits the typed text when no option is highlighted. |
Escape | Closes the list and restores the label of the current selection. |
Tab | Leaves the input, closes the list and restores the label of the current selection. |
Emits
| Value | Description |
|---|---|
@update:modelValue | Emitted when the selection changes. The payload is the new value, `null` when a single selection is cleared, or the new array in `multiple` mode. |
@search | Emitted, after `searchDebounce`, when the user types or clears the input. The payload is the typed text. |
Example
<template>
<DropdownCombobox
id="user"
v-model="userId"
:options="results"
:filterLocally="false"
:isLoading="isSearching"
@search="fetchUsers"
/>
</template>
<script setup lang="ts">
const userId = ref<string | number | null>(null)
const results = ref<SelectOption[]>([])
const isSearching = ref(false)
const fetchUsers = async (query: string) => {
isSearching.value = true
results.value = await searchUsers(query)
isSearching.value = false
}
</script>