Skip to main content

Overview

The Select component provides a customizable dropdown menu for selecting one or multiple items from a list, with support for icons, avatars, descriptions, and grouping.

Basic Usage

<script setup lang="ts">
import { ref } from 'vue'

const selected = ref(null)
const items = [
  'Apple',
  'Banana',
  'Cherry',
  'Date',
  'Elderberry'
]
</script>

<template>
  <USelect v-model="selected" :items="items" placeholder="Select a fruit" />
</template>

With Objects

<script setup lang="ts">
import { ref } from 'vue'

const selected = ref(null)
const items = [
  { value: 1, label: 'Wade Cooper', description: 'Software Engineer' },
  { value: 2, label: 'Arlene Mccoy', description: 'Product Manager' },
  { value: 3, label: 'Devon Webb', description: 'Designer' }
]
</script>

<template>
  <USelect
    v-model="selected"
    :items="items"
    placeholder="Select a person"
  />
</template>

With Icons and Avatars

<script setup lang="ts">
const items = [
  {
    label: 'Profile',
    icon: 'i-heroicons-user',
    value: 'profile'
  },
  {
    label: 'Settings',
    icon: 'i-heroicons-cog',
    value: 'settings'
  },
  {
    label: 'Team',
    avatar: { src: 'https://i.pravatar.cc/150?img=1' },
    value: 'team'
  }
]
</script>

<template>
  <USelect v-model="selected" :items="items" />
</template>

Multiple Selection

<script setup lang="ts">
import { ref } from 'vue'

const selected = ref([])
const items = ['React', 'Vue', 'Angular', 'Svelte', 'Solid']
</script>

<template>
  <USelect
    v-model="selected"
    :items="items"
    multiple
    placeholder="Select frameworks"
  />
</template>

Grouped Items

<script setup lang="ts">
const items = [
  [
    { type: 'label', label: 'Fruits' },
    { label: 'Apple', value: 'apple' },
    { label: 'Banana', value: 'banana' }
  ],
  [
    { type: 'label', label: 'Vegetables' },
    { label: 'Carrot', value: 'carrot' },
    { label: 'Potato', value: 'potato' }
  ]
]
</script>

<template>
  <USelect v-model="selected" :items="items" />
</template>

With Separators

<script setup lang="ts">
const items = [
  { label: 'Profile', value: 'profile' },
  { label: 'Settings', value: 'settings' },
  { type: 'separator' },
  { label: 'Logout', value: 'logout' }
]
</script>

<template>
  <USelect v-model="selected" :items="items" />
</template>

Colors

<template>
  <USelect :items="items" color="primary" placeholder="Primary" />
  <USelect :items="items" color="secondary" placeholder="Secondary" />
  <USelect :items="items" color="success" placeholder="Success" />
  <USelect :items="items" color="warning" placeholder="Warning" />
  <USelect :items="items" color="error" placeholder="Error" />
  <USelect :items="items" color="neutral" placeholder="Neutral" />
</template>

Variants

<template>
  <USelect :items="items" variant="outline" placeholder="Outline" />
  <USelect :items="items" variant="soft" placeholder="Soft" />
  <USelect :items="items" variant="ghost" placeholder="Ghost" />
  <USelect :items="items" variant="none" placeholder="None" />
</template>

Sizes

<template>
  <USelect :items="items" size="xs" placeholder="Extra Small" />
  <USelect :items="items" size="sm" placeholder="Small" />
  <USelect :items="items" size="md" placeholder="Medium" />
  <USelect :items="items" size="lg" placeholder="Large" />
  <USelect :items="items" size="xl" placeholder="Extra Large" />
</template>

States

<template>
  <!-- Disabled -->
  <USelect :items="items" disabled placeholder="Disabled" />
  
  <!-- Required -->
  <USelect :items="items" required placeholder="Required" />
  
  <!-- Highlighted -->
  <USelect :items="items" highlight placeholder="Highlighted" />
  
  <!-- Loading -->
  <USelect :items="items" loading placeholder="Loading..." />
</template>

With Icons

<template>
  <!-- Leading icon -->
  <USelect
    :items="items"
    leading-icon="i-heroicons-user"
    placeholder="Select user"
  />
  
  <!-- Custom trailing icon -->
  <USelect
    :items="items"
    trailing-icon="i-heroicons-chevron-up-down"
    placeholder="Select option"
  />
</template>

With Form

<script setup lang="ts">
import { z } from 'zod'
import { ref } from 'vue'

const schema = z.object({
  country: z.string().min(1, 'Please select a country'),
  role: z.string().min(1, 'Please select a role')
})

const state = ref({
  country: '',
  role: ''
})

const countries = [
  { value: 'us', label: 'United States' },
  { value: 'ca', label: 'Canada' },
  { value: 'mx', label: 'Mexico' }
]

const roles = [
  { value: 'admin', label: 'Admin' },
  { value: 'user', label: 'User' },
  { value: 'guest', label: 'Guest' }
]
</script>

<template>
  <UForm :schema="schema" :state="state">
    <UFormField label="Country" name="country">
      <USelect v-model="state.country" :items="countries" />
    </UFormField>
    
    <UFormField label="Role" name="role">
      <USelect v-model="state.role" :items="roles" />
    </UFormField>
  </UForm>
</template>

Custom Slots

<template>
  <USelect v-model="selected" :items="items">
    <template #item="{ item }">
      <div class="flex items-center gap-2">
        <UBadge :color="item.color">{{ item.status }}</UBadge>
        <span>{{ item.label }}</span>
      </div>
    </template>
  </USelect>
</template>

Props

modelValue
any
The controlled value. Can be bound with v-model.
defaultValue
any
The default value when initially rendered.
items
array
Array of items or nested arrays for grouped items.
valueKey
string
default:"value"
Field to use as the value when items are objects.
labelKey
string
default:"label"
Field to use as the label when items are objects.
descriptionKey
string
default:"description"
Field to use as the description when items are objects.
placeholder
string
Placeholder text when no item is selected.
multiple
boolean
Allow multiple items to be selected.
color
string
default:"primary"
Color variant.
variant
string
default:"outline"
Visual variant.
size
string
default:"md"
Size variant.
leadingIcon
string
Icon displayed at the start.
trailingIcon
string
Icon displayed at the end (chevron by default).
selectedIcon
string
Icon shown for selected items.
disabled
boolean
Disable the select.
required
boolean
Mark as required.
highlight
boolean
Highlight the ring color.
autofocus
boolean
Automatically focus on mount.
autofocusDelay
number
default:"0"
Delay before autofocus.
portal
boolean | string | HTMLElement
default:"true"
Render the menu in a portal.
content
object
Content props (side, sideOffset, etc.).
arrow
boolean | object
Display an arrow alongside the menu.

Events

@update:modelValue
(value: any) => void
Emitted when the selected value changes.
@change
(event: Event) => void
Emitted when the value is committed.
@blur
(event: FocusEvent) => void
Emitted when focus is lost.
@focus
(event: FocusEvent) => void
Emitted when focused.

Slots

leading
{ modelValue: any, open: boolean, ui: object }
Custom leading content.
default
{ modelValue: any, open: boolean, ui: object }
Custom trigger content.
trailing
{ modelValue: any, open: boolean, ui: object }
Custom trailing content.
item
{ item: any, index: number, ui: object }
Custom item rendering.
item-leading
{ item: any, index: number, ui: object }
Custom item leading content.
item-trailing
{ item: any, index: number, ui: object }
Custom item trailing content.

Exposed

triggerRef
Ref<HTMLButtonElement>
Reference to the trigger button.
viewportRef
Ref<HTMLElement>
Reference to the viewport element.

Build docs developers (and LLMs) love