Skip to content

Select Menu

Display a select menu with advanced features.

Usage

The SelectMenu component renders by default a Select component and is based on the ui.select preset. You can use most of the Select props to configure the display if you don't want to override the default slot such as color, variant, size, placeholder, icon, disabled, etc. Like the Select component, you can use the options prop to pass an array of strings or objects.

vue
<script setup>
import {ref} from 'vue'
const people = ['Wade Cooper', 'Arlene Mccoy', 'Devon Webb', 'Tom Cook', 'Tanya Fox', 'Hellen Schmidt', 'Caroline Schultz', 'Mason Heaney', 'Claudie Smitham', 'Emil Schaefer']

const selected = ref(people[0])
</script>

<template>
  <s-select-menu v-model="selected" :options="people" />
</template>

Multiple

You can use the multiple prop to select multiple values.

vue
<script setup>
import {ref} from 'vue'
const people = ['Wade Cooper', 'Arlene Mccoy', 'Devon Webb', 'Tom Cook', 'Tanya Fox', 'Hellen Schmidt', 'Caroline Schultz', 'Mason Heaney', 'Claudie Smitham', 'Emil Schaefer']

const selected = ref([])
</script>

<template>
  <s-select-menu v-model="selected" :options="people" multiple placeholder="Select people" />
</template>

Objects

You can pass an array of objects to options and either compare on the whole object or use the by prop to compare on a specific key. You can configure which field will be used to display the label through the option-attribute prop that defaults to label.

vue
<script setup>
import {ref} from 'vue';

const people = [{
  id: 'ManukMinasyan',
  label: 'ManukMinasyan',
  href: 'https://github.com/ManukMinasyan',
  target: '_blank',
  avatar: { src: 'https://avatars.githubusercontent.com/u/2556185?v=4' }
},
  {
    id: 'Ilyapashayan20',
    label: 'Ilyapashayan',
    href: 'https://github.com/Ilyapashayan20',
    target: '_blank',
    avatar: { src: 'https://avatars.githubusercontent.com/u/77129709?v=4' }
  },
  {
    id: 'smarroufin',
    label: 'smarroufin',
    href: 'https://github.com/smarroufin',
    target: '_blank',
    avatar: { src: 'https://avatars.githubusercontent.com/u/7547335?v=4' }
  },
  {
    id: 'nobody',
    label: 'Nobody',
    icon: 'icon-[heroicons--user-circle]'
  }]

const selected = ref(people[0])
</script>

<template>
  <s-select-menu v-model="selected" :options="people">
    <template #label>
      <s-icon v-if="selected.icon" :name="selected.icon" class="w-4 h-4" />
      <s-avatar v-else-if="selected.avatar" v-bind="selected.avatar" size="3xs" />

      {{ selected.label }}
    </template>
  </s-select-menu>
</template>

If you only want to select a single object property rather than the whole object as value, you can set the value-attribute property. This prop defaults to null.

vue
<script setup>
import {computed, ref} from "vue";

const people = [
  {
    id: 1,
    name: 'Wade Cooper'
  },
  {
    id: 2,
    name: 'Arlene Mccoy'
  },
  {
    id: 3,
    name: 'Devon Webb'
  },
  {
    id: 4,
    name: 'Tom Cook'
  }
]

const selected = ref(people[0].id)

const current = computed(() => people.find(person => person.id === selected.value))
</script>

<template>
  <s-select-menu
      v-model="selected"
      :options="people"
      placeholder="Select people"
      value-attribute="id"
      option-attribute="name"
  >
    <template #label>
      {{ current.name }}
    </template>
  </s-select-menu>
</template>

Icon

Use the selected-icon prop to set a different icon or change it globally in ui.selectMenu.default.selectedIcon. Defaults to icon-[heroicons--check-20-solid].

vue
<script setup>
import {ref} from "vue";

const person = ref('Arlene Mccoy')
</script>

<template>
  <s-select-menu
      v-model="person"
      selected-icon="icon-[heroicons--hand-thumb-up-solid]"
      class="w-full lg:w-40"
      placeholder="Select a person"
      :options="['Wade Cooper', 'Arlene Mccoy', 'Devon Webb', 'Tom Cook', 'Tanya Fox', 'Hellen Schmidt', 'Caroline Schultz', 'Mason Heaney', 'Claudie Smitham', 'Emil Schaefer']"
  />
</template>

Searchable

Use the searchable prop to enable search.

Use the searchable-placeholder prop to set a different placeholder.

This will use Headless UI Combobox component instead of Listbox.

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

const person = ref(null)
</script>
<template>
  <s-select-menu
      searchable
      searchable-placeholder="Search a person..."
      class="w-full lg:w-40"
      placeholder="Select a person"
      v-model="person"
      :options="['Wade Cooper', 'Arlene Mccoy', 'Devon Webb', 'Tom Cook', 'Tanya Fox', 'Hellen Schmidt', 'Caroline Schultz', 'Mason Heaney', 'Claudie Smitham', 'Emil Schaefer']"
  />
</template>

Attributes

Use the search-attributes prop with an array of property names to search on each option object. Nested attributes can be accessed using dot.notation. When the property value is an array or object, these are cast to string so these can be searched within.

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

const options = [
  { id: 1, name: 'Wade Cooper', colors: ['red', 'yellow'] },
  { id: 2, name: 'Arlene Mccoy', colors: ['blue', 'yellow'] },
  { id: 3, name: 'Devon Webb', colors: ['green', 'blue'] },
  { id: 4, name: 'Tom Cook', colors: ['blue', 'red'] },
  { id: 5, name: 'Tanya Fox', colors: ['green', 'red'] },
  { id: 5, name: 'Hellen Schmidt', colors: ['green', 'yellow'] }
]

const selected = ref(options[1])
</script>

<template>
  <SSelectMenu
      v-model="selected"
      :options="options"
      placeholder="Select a person"
      searchable
      searchable-placeholder="Search by name or color"
      option-attribute="name"
      by="id"
      :search-attributes="['name', 'colors']"
  >
    <template #option="{ option: person }">
      <span v-for="color in person.colors" :key="color.id" class="h-2 w-2 rounded-full" :class="`bg-${color}-500 dark:bg-${color}-400`" />
      <span class="truncate">{{ person.name }}</span>
    </template>
  </SSelectMenu>
</template>

Clear on close

By default, the search query will be kept after the menu is closed. To clear it on close, set the clear-search-on-close prop.

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

const person = ref(null)
</script>
<template>
  <SSelectMenu
      v-model="person"
      clear-search-on-close
      class="w-full lg:w-48"
      placeholder="Select a person"
      searchable
      searchable-placeholder="Search a person..."
      :options="['Wade Cooper', 'Arlene Mccoy', 'Devon Webb', 'Tom Cook', 'Tanya Fox', 'Hellen Schmidt', 'Caroline Schultz', 'Mason Heaney', 'Claudie Smitham', 'Emil Schaefer']"
  />
</template>

Released under the MIT License.