Skip to main content
You are viewing Pre-Alpha documentation.
Vuetify0 Logo
Theme
Mode
Palettes
Accessibility
Vuetify One

Sign in to Vuetify One

Access premium tools across the Vuetify ecosystem — Bin, Play, Studio, and more.

Not a subscriber? See what's included

Select

A headless dropdown select component with single and multi-selection support. Uses createSelection for state management, useVirtualFocus for keyboard navigation, and usePopover for native popover positioning.


IntermediateMar 19, 2026

Usage

The Select component provides a compound pattern for building accessible dropdown selects. It supports v-model for both single values and arrays (multi-select mode).

Selected: None

<script setup lang="ts">
  import { Select } from '@vuetify/v0'
  import { shallowRef } from 'vue'

  const color = shallowRef<string>()

  const colors = [
    { id: 'red', label: 'Red' },
    { id: 'orange', label: 'Orange' },
    { id: 'green', label: 'Green' },
    { id: 'blue', label: 'Blue' },
    { id: 'purple', label: 'Purple' },
  ]
</script>

<template>
  <div class="flex flex-col gap-4 max-w-xs mx-auto">
    <Select.Root v-model="color">
      <Select.Activator class="flex items-center justify-between w-full px-3 py-2 rounded-lg border border-divider bg-surface text-on-surface text-sm cursor-pointer focus-visible:outline-2 focus-visible:outline-primary focus-visible:outline-offset-2">
        <Select.Value v-slot="{ selectedValue }">
          {{ selectedValue }}
        </Select.Value>
        <Select.Placeholder class="text-on-surface-variant">Choose a color…</Select.Placeholder>

        <Select.Cue v-slot="{ isOpen }" class="text-xs opacity-50">
          {{ isOpen ? '&#x25B4;' : '&#x25BE;' }}
        </Select.Cue>
      </Select.Activator>

      <Select.Content class="p-1 rounded-lg border border-divider bg-surface shadow-lg" :style="{ minWidth: 'anchor-size(width)' }">
        <Select.Item
          v-for="item in colors"
          :id="item.id"
          :key="item.id"
          :value="item.label"
        >
          <template #default="{ isSelected, isHighlighted }">
            <div
              class="px-3 py-2 rounded-md cursor-default select-none text-sm"
              :class="[
                isHighlighted
                  ? 'bg-primary text-on-primary'
                  : isSelected
                    ? 'text-primary font-medium'
                    : 'text-on-surface hover:bg-surface-variant',
              ]"
            >
              {{ item.label }}
            </div>
          </template>
        </Select.Item>
      </Select.Content>
    </Select.Root>

    <p class="text-sm text-on-surface-variant">
      Selected: {{ color ?? 'None' }}
    </p>
  </div>
</template>

Anatomy

vue
<script setup lang="ts">
  import { Select } from '@vuetify/v0'
</script>

<template>
  <Select.Root>
    <Select.Activator>
      <Select.Value />
      <Select.Placeholder />

      <Select.Cue />
    </Select.Activator>

    <Select.Content>
      <Select.Item />
    </Select.Content>
  </Select.Root>
</template>

Architecture

The Root creates selection, virtual focus, and popover contexts. The Activator serves as the combobox trigger with keyboard event handling. Content renders via the native popover API with CSS anchor positioning. Each Item registers with the selection context and provides data attributes for styling.

Select Architecture

Use controls to zoom and pan. Click outside or press Escape to close.

Select Architecture

Examples

Disabled States

Both individual items and the entire select can be disabled. Disabled items are skipped by virtual focus keyboard navigation. The disabled prop on Root prevents the dropdown from opening.

Selected: None

Multi-Select

Set multiple on Root to enable multi-selection. The dropdown stays open after each selection. v-model binds to an array of IDs. The Value slot receives selectedValues for rendering chips, tags, or comma-separated text.

Selected: None

Accessibility

The Select implements the WAI-ARIA Combobox↗ pattern with a listbox popup.

ARIA Attributes

AttributeValueComponent
rolecomboboxActivator
rolelistboxContent
roleoptionItem
aria-expandedtrue / falseActivator
aria-haspopuplistboxActivator
aria-controlslistbox IDActivator
aria-selectedtrue / falseItem
aria-disabledtrueItem (when disabled)
aria-multiselectabletrueContent (when multiple)

Keyboard Navigation

KeyAction
Enter / SpaceOpen dropdown, or select highlighted item
ArrowDownOpen dropdown, or move highlight down
ArrowUpOpen dropdown, or move highlight up
HomeMove highlight to first item
EndMove highlight to last item
EscapeClose dropdown
TabClose dropdown and move focus

API Reference

The following API details are for all variations of the Select component.

Selection.Root

Props

namespace

string

Namespace for dependency injection (must match SelectionItem namespace)

Default: "v0:selection"

disabled

boolean

Disables the entire selection instance

Default: false

enroll

boolean

Auto-select non-disabled items on registration

Default: false

mandatory

boolean | "force"

Controls mandatory selection behavior: - false (default): No mandatory selection enforcement - true: Prevents deselecting the last selected item - `force`: Automatically selects the first non-disabled item on registration

Default: false

multiple

boolean

Enable multi-selection mode (array v-model)

Default: false

modelValue

T | T[]

Events

update:model-value

[value: T | T[]]

Slots

default

SelectionRootSlotProps

Select.Root

Props

name

string

Form field name — auto-renders hidden input when provided

namespace

string

Namespace for dependency injection

Default: "v0:select"

id

string

Unique identifier (auto-generated if not provided)

form

string

Associate with a form by ID

disabled

boolean

Disables the entire select

Default: false

multiple

boolean

Enable multi-selection mode

Default: false

mandatory

boolean | "force"

Controls mandatory selection behavior: - false (default): No mandatory selection enforcement - true: Prevents deselecting the last selected item - `force`: Automatically selects the first non-disabled item

Default: false

Events

update:model-value

[value: any]

Slots

default

SelectRootSlotProps

Select.Activator

Props

namespace

string

Namespace for dependency injection

Default: "v0:select"

Slots

default

SelectActivatorSlotProps

Select.Content

Props

namespace

string

Namespace for dependency injection

Default: "v0:select"

Slots

default

SelectContentSlotProps

Select.Cue

Props

namespace

string

Default: "v0:select"

Slots

default

SelectCueSlotProps

Select.HiddenInput

Props

namespace

string

Default: "v0:select"

Select.Item

Props

namespace

string

Namespace for dependency injection

Default: "v0:select"

id

string

Unique identifier (auto-generated if not provided)

value

V

Value associated with this option

disabled

MaybeRefOrGetter<boolean>

Disables this specific option

Slots

default

SelectItemSlotProps<V>

Select.Placeholder

Props

namespace

string

Default: "v0:select"

Slots

default

SelectPlaceholderSlotProps

Select.Value

Props

namespace

string

Namespace for dependency injection

Default: "v0:select"

Slots

default

SelectValueSlotProps

Selection.Item

Props

id

string

Unique identifier (auto-generated if not provided)

label

string

Optional display label (passed through to slot, not used in registration)

value

V

Value associated with this item

disabled

MaybeRefOrGetter<boolean>

Disables this specific item

namespace

string

Namespace for dependency injection

Default: "v0:selection"

Slots

default

SelectionItemSlotProps<V>

Recipes

Form Submission

Set name on Root to auto-render hidden inputs for form submission — one per selected value in multi-select mode:

vue
<template>
  <Select.Root v-model="value" name="color">
    <!-- ... -->
  </Select.Root>
</template>

Mandatory Selection

Use mandatory to prevent deselecting the last item, or mandatory="force" to auto-select the first item on mount:

vue
<template>
  <Select.Root v-model="value" mandatory="force">
    <!-- First non-disabled item is selected automatically -->
  </Select.Root>
</template>

Custom Positioning

Control dropdown placement with CSS anchor positioning props on Content:

vue
<template>
  <Select.Content position-area="top" position-try="flip-block">
    <!-- Dropdown appears above the activator -->
  </Select.Content>
</template>

Data Attributes

Style interactive states without slot props:

AttributeValuesComponent
data-selectedtrueItem
data-highlighted""Item
data-disabledtrueItem
data-select-open""Activator
data-state"open" / "closed"Cue
Was this page helpful?

© 2016-1970 Vuetify, LLC
Ctrl+/