Skip to content

VPick

A custom dropdown triggered by a button, with full keyboard navigation and group labels.

This page covers the parts every VPick has. Each of the bigger capabilities has its own page:

PageWhat it covers
SearchType-ahead filtering, clearing, empty states
MultiselectMultiple values, chips, select and deselect
Tree SelectNested options, cascade selection, searching a tree
SlotsReplacing labels, icons, and the empty state
PositioningWhere the panel renders, scroll containers, inline mode
FormsLabelling, submission, validation
AccessibilityKeyboard navigation, ARIA roles, screen readers
APIEvery prop, slot, event, and method in one place

Options

Accepts the same options shape as VPickNative. Flat arrays and grouped arrays both work, and groups are detected automatically when an item has an options array.

Grouped

Separators

Use separators to render a horizontal divider between adjacent groups.

Custom data shape

Use labelKey, valueKey, disabledKey, and groupOptionsKey to pass data straight from your API without mapping. See the Data Shape guide for the full reference.

labelKey also accepts an array, used as a fallback chain where the first key with a non-empty value wins. Useful when records are inconsistent:

vue
<VPick :options="options" :label-key="['label', 'name']" value-key="id" />

States

Disabled

Loading

Error

Appearance

Rotate icon

Rotates the chevron 180 degrees when the dropdown is open.

Scrollable

Long option lists scroll inside the dropdown. Max height is controlled by --vpick-listbox-max-height (default 16rem).

Sizing

By default, the trigger hugs its content (--vpick-width: fit-content) and the dropdown matches the trigger width at minimum. Give the trigger an explicit width and the dropdown will follow.

vue
<VPick v-model="selected" :options="options" style="--vpick-width: 18rem" />

Options wider than the trigger make the dropdown grow. To pin both widths identical and truncate long labels, also cap the listbox:

vue
<VPick
  v-model="selected"
  :options="options"
  style="
    --vpick-width: 18rem;
    --vpick-listbox-max-width: var(--vpick-trigger-width);
  "
/>
VariableDefaultEffect
--vpick-widthfit-contentTrigger width.
--vpick-listbox-min-width--vpick-trigger-widthMinimum dropdown width.
--vpick-listbox-max-widthcalc(100vw - 16px)Maximum dropdown width.
--vpick-listbox-max-height16remMaximum dropdown height before scrolling.

--vpick-trigger-width is measured and set by Vue Pick on every open, so read it rather than assign it.

Object values

By default v-model holds plain values:

js
selected = ["apple", "banana"]

Set valueFormat="object" and it holds your original option objects instead:

js
selected = [
  { id: "apple", label: "Apple", price: 3 },
  { id: "banana", label: "Banana", price: 2 },
]

Useful when you need other fields off the selection and would otherwise look them up yourself. Both controls below hold the same selection:

vue
<VPick
  v-model="selected"
  :options="fruit"
  label-key="label"
  value-key="id"
  value-format="object"
/>

Objects you pass back in are matched by valueKey, not by identity, so a rebuilt object literal still resolves:

js
selected = { id: "apple" } // matches the Apple option

The hidden <select> used for form submission always posts plain values, since a form field cannot carry an object.

Core props

The props every VPick takes. The rest are listed on the page for the feature they belong to, and all of them together on the API Reference.

modelValueany default undefined

Selected value. Use v-model for two-way binding. In Vue 2 the prop is value.

optionsOptionOrGroup[] required

Array of options or option groups.

Read more

placeholderstring default undefined

Text shown when no value is selected.

disabledboolean default false

Disables the control.

loadingboolean default false

Shows a spinner and disables interaction.

errorstring default undefined

Error message. Applies error styling and aria-invalid.

idstring default undefined

HTML id, applied to the control itself so a <label for> resolves to it.

Read more

namestring default undefined

HTML name for form submission.

Read more

requiredboolean default false

HTML required attribute.

ariaLabelstring default undefined

aria-label, for when there is no visible label.

ariaDescribedbystring default undefined

aria-describedby, for wiring up hint or error text.

Data shape

labelKeystring | string[] default "label"

Key to read each option's visible label from. An array acts as a fallback chain: the first key with a non-empty value wins.

Read more

valueKeystring default "value"

Key to read each option's value from.

Read more

disabledKeystring default "disabled"

Key to read each option's disabled flag from.

Read more

groupOptionsKeystring default "options"

Key for the options array inside a group.

Read more

childrenKeystring default "children"

Key for nested children. Any option carrying that array turns tree mode on.

Read more

Appearance

separatorsboolean default false

Draws a divider between adjacent groups in the list.

rotateIconboolean default false

Rotates the trigger chevron 180 degrees while open.

animateboolean default true

Animates the multiselect chips. false adds and removes them outright.

Read more

Released under the MIT License.