Combobox
A dropdown with a search box for picking one or more values from a list.
<template> <Combobox :items="[{ value: 'a', label: 'Apple' }]" model-value="a" placeholder="Fruits" /></template>Props
| Name | Type | Default |
|---|---|---|
| items | ({ type: 'label'; label: string } | { value: string; label: string; description?: string; icon?: string; sublabel?: string; disabled?: boolean })[] | - |
| placeholder | string | - |
| searchPlaceholder | string | - |
| icon | string | - |
| multiple | boolean | false |
| size | 'md' | 'sm' | 'xs' | 'md' |
| error | boolean | false |
| virtualize | boolean | false |
| modelValue | string | string[] | - |
Slots
| Name | Description |
|---|---|
| item-leading | Scoped `{ item }`. Replaces an option row's leading icon (e.g. a status dot). Not rendered for section-header entries. |
| item-label | Scoped `{ item }`. Replaces an option row's label (e.g. a status badge that carries its own text). Not rendered for section-header entries. |
Guidelines
Do
- Use this when the user needs to search or filter a list that's too long to scan by eye - a repository, an organization, a branch.
- Use
multiplewhen more than one option can be selected - the trigger keeps showingplaceholderas a fixed label, with a small count badge appended once anything's selected. - When that placeholder is an instruction ("Select repositories"), pass
selected-labelwith the field's name ("Repositories"): once anything is selected the trigger reads the name beside the count instead of the instruction.
- Give an option a
descriptionwhen its label alone doesn't identify it (a display name plus a slug) - search matches the label and the description, so typing either finds it. - Use the
#item-leading="{ item }"slot to replace an option's leading icon with custom content, such as a status dot. Without the slot, each item's owniconrenders as usual.#item-label="{ item }"replaces the label the same way, for a badge that carries its own text. - In single mode (no
multiple), picking the already-selected option again clears the value back toundefined, so a single-select Combobox can always be unset. - Set
virtualizefor a list of hundreds of options, so the panel renders only the rows in view. - Group related options with a
{ type: 'label', label: '...' }section header entry - but only once there are 2+ groups to tell apart. - Inside a
UFormField, a validation error puts the field on the error surface by itself. Passerrorfor a state the form doesn't know; the trigger takes Input's red wash and border either way. - Use
#item-trailing="{ item }"for right-hand content such as a project key; it replaces the item'ssublabel. - Use
#empty="{ searchTerm }"for a remote search's loading or error line, so the panel never shows a misleading "No results". - To page a remote list in on scroll, put a template ref on the Combobox and pass its
viewportReftouseInfiniteScroll. - Write the placeholder by where the picker sits: in a filter or toolbar with no visible label, the bare field name ("Repository"); in a form under a label, "Select a/an x" ("Select a channel"). Once something is picked it shows the value, or with
multiplethe field name and the count (selected-label). - Always pass a
placeholderwhen the picker can start empty: there's no built-in default. - Don't use this when the list is already short enough to scan without searching - use
Selectinstead, which has no search box to fight. - Don't use this for a short, fully-visible list of mutually-exclusive options - use
RadioGroupinstead. - Don't use this for independent on/off choices - use
Checkbox. - Don't add a section header to a single, ungrouped list - a lone
{ type: 'label' }entry has nothing to distinguish it from, so it just adds noise above the options. - Don't pass
:ui- it would replace the whole design-system look (trigger, panel and option rows), so the type-check rejects it. Select and Combobox triggers share one resting surface with the secondary Button, and every picker shares one option-row style. - Don't use an example name ("e.g. acme/web"), an ellipsis, or a generic "Select something" as the placeholder: an example reads as already picked, and a generic one doesn't say what to pick.
Examples
Multiple select
Selecting more than one item, with search to narrow a long list.
<template> <Combobox v-model="selected" :items="[ { value: 'apple', label: 'Apple' }, { value: 'banana', label: 'Banana' }, { value: 'blueberry', label: 'Blueberry' }, { value: 'grapes', label: 'Grapes' }, { value: 'pineapple', label: 'Pineapple' }, ]" multiple placeholder="Fruits" /></template>Sizes
The three trigger height steps - xs, sm, and md.
<template> <Combobox v-model="selected" :items="items" size="xs" placeholder="Fruits" /> <Combobox v-model="selected" :items="items" size="sm" placeholder="Fruits" /> <Combobox v-model="selected" :items="items" size="md" placeholder="Fruits" /></template>Multiple select sizes
The count badge checked at every trigger size, not just the default.
<template> <Combobox v-model="selected" :items="items" multiple size="xs" placeholder="Fruits" /> <Combobox v-model="selected" :items="items" multiple size="sm" placeholder="Fruits" /> <Combobox v-model="selected" :items="items" multiple size="md" placeholder="Fruits" /></template>