Skip to content

Select ​

Native dropdown with custom chevron, matching Input.vue dimensions and focus styles. Accepts string or object option arrays.

Examples ​

Basic ​

Tailwind v4
vue
<script setup>
import { ref } from 'vue'
const product = ref('')
</script>

<template>
  <Select
    v-model="product"
    placeholder="Choose a product"
    :options="['Crusher Run', 'Screenings', 'Gabion Stone', 'Rip Rap']"
  />
</template>

Object options ​

Tailwind v4
vue
<Select
  v-model="status"
  :options="[
    { label: 'Active', value: 'active' },
    { label: 'Inactive', value: 'inactive' },
    { label: 'Archived', value: 'archived' },
  ]"
/>

With hint and error ​

Tailwind v4
vue
<Select
  v-model="shift"
  :options="['Morning', 'Afternoon', 'Night']"
  hint="Shifts start at 6 AM, 2 PM, and 10 PM"
/>
<Select
  v-model="section"
  :options="['A', 'B', 'C']"
  error="Please select a section"
/>

Disabled ​

Tailwind v4
vue
<Select :model-value="'Screenings'" :options="['Crusher Run', 'Screenings']" disabled />

Searchable (client-side filter) ​

Set searchable to render a text input inside the open dropdown. By default it filters the existing options array client-side with a case-insensitive substring match — no extra wiring required.

Tailwind v4
vue
<script setup>
import { ref } from 'vue'
const product = ref('')
</script>

<template>
  <Select
    v-model="product"
    searchable
    placeholder="Search products"
    :options="['Crusher Run', 'Screenings', 'Gabion Stone', 'Rip Rap']"
  />
</template>

Searchable + async (onSearch) ​

Pass onSearch to run your own server-side/async filtering instead of (or in addition to) the built-in client-side filter. Combine with loading so the dropdown shows a loading indicator and skips client-side filtering while you're fetching — update the options prop reactively from the parent once results arrive.

Tailwind v4
vue
<script setup>
import { ref } from 'vue'

const product = ref('')
const options = ref([
  { label: 'Crusher Run', value: 'crusher' },
  { label: 'Screenings', value: 'screenings' },
])
const loading = ref(false)

async function handleSearch(query) {
  loading.value = true
  const results = await fetchProducts(query) // your API call
  options.value = results
  loading.value = false
}
</script>

<template>
  <Select
    v-model="product"
    searchable
    :loading="loading"
    :on-search="handleSearch"
    :options="options"
    placeholder="Search products (async)"
  />
</template>

Props ​

PropTypeDefaultDescription
modelValuestring | number—Currently selected value
optionsArray<{ label: string; value: string | number } | string>—Option list; strings are used as both label and value
placeholderstring—Placeholder option shown when no value is selected
disabledbooleanfalsePrevents interaction and dims the control
errorstring—Validation error message shown below the select
hintstring—Helper text shown below the select when no error
searchablebooleanfalseRenders a search input inside the open dropdown and enables client-side filtering
onSearch(query: string) => void | Promise<any>—Debounced (~250ms) callback fired as the user types; use for async/server-side filtering
loadingbooleanfalseShows a loading indicator in the dropdown and disables client-side filtering
noResultsTextstring'No results found'Text shown when the filtered option list is empty

Emits ​

EventPayloadDescription
update:modelValuestring | numberNew value on change

Private — Jetpack Labs internal use only