Skip to content

Select

WARNING

Experimental

Introduction

The Select component A.K.A. SelectMenu provides a customizable and feature-rich dropdown selection interface, designed using the Vue composition API. It integrates the Headless UI components and provides additional customization, including multiple item selection, searching, custom icons, validation, and more.

Storybook

Props

PropTypeDefaultDescription
modelValueT[] | undefined-The current selected value(s) of the select box.
itemsT[][]An array of items that can be selected.
multipleboolean-Allow multiple selections.
itemTextstring'text'Property name of each item to display as text.
itemValuestring'value'Property name of each item to use as the value.
placeholderstring'Choose'Placeholder text for the select box.
labelstring-Label for the select box.
transitionstring'dropdown'Transition style for the dropdown.
clearableboolean-Allows clearing the selection.
clearTextstring'Clear'Text for the clear button.
errorboolean-Indicates an error in the selection.
hintstring-Hint text.
errorMessagestring-Error message display.
hideErrorbooleanfalseHide error message.
shadowboolean | Shadow | (string & {})-Shadow styling for the dropdown.
searchableboolean-Enable search function in the dropdown.
disabledboolean-Disable the select component.
emptyTextstring'No results.'No items/search results text.
searchBystring-Property name to search by.
selectionItemPropsInstanceType<typeof VBadge>['$props']-Selected item badge properties.
displayValuefunction-Function that returns display value of an item.
placementPlacement'bottom'Dropdown placement related to the input.
offsetnumber8Offset for the dropdown.
shiftboolean | number | trueDropdown shift value.
flipboolean | numbertrueFlip dropdown if it doesn't fit.
searchPlacementstring'inside'Search input placement.
searchPlaceholderstring'Search...'Search input placeholder.
chipsboolean-Display selected items as chips.
icon, iconSize, iconClass-'sm'Select box icon properties.
dropdownIcon, dropdownIconSize, dropdownIconClass-'heroicons:chevron-down', 'sm'Dropdown icon properties.
checkIcon, checkIconSize, checkIconClass-'heroicons:check', 'sm'Check icon properties.
clearIcon, clearIconSize, clearIconClass-'heroicons:x-mark', 'sm'Clear icon properties.
searchPrefixIcon, searchPrefixIconSize, searchPrefixIconClass-'sm'Search prefix icon properties.
searchSuffixIcon, searchSuffixIconSize, searchSuffixIconClass-'sm'Search suffix icon properties.
wrapperClassstring-Extra classes for the select box wrapper.
selectedIconPlacementstring'left'Icon position in selected item.
bystring-Sorting method for items.
namestring-Input name attribute.
loadingboolean-Show loading indicator.
loadingIcon, loadingText-'ri:loader-5-fill', 'Loading...'Loading display properties.
tooltipInstanceType<typeof VTooltip>['$props']-Tooltip properties.
selectedTextstring'selected'Text for selected state.
allowCustomValuesboolean-Allow custom values.

Events

Event NamePayloadDescription
update:modelValueModelValueEmitted when the model value is updated. Useful for v-model integration.
changeModelValueEmitted when a change to the value occurs.

Slots

Slot NamePropsDescription
default{modelValue, multiple, itemValue, itemText, selectionItemProps}Default slot to customize the main content.
button{open}Slot to customize the dropdown toggle button.
selection-item{item, idx, itemText, itemValue, remove, open}Customize the display of selected items.
selected{modelValue, multiple, placeholder, itemText, itemValue, open}Slot to customize the selected item display.
item{item, active, selected, itemText, itemValue, open}Customize the items in the dropdown list.
hint{hint}Slot for hint text customization.
error{error, errorMessage, hideError}Slot for error display customization.
selection{modelValue, multiple, itemValue, itemText, selectionItemProps, open}Customize the selected items list.
empty{items, emptyText, open}Display when no items or results are available.
item-text{item, itemText, itemValue, active, selected, open}Customize the text of items.
check-icon{selected, icon}Customize the check icon for selected items.
new-item-text{item}Display for new custom items (when allowCustomValues is enabled).

Methods

Method NameParametersDescription
clearNoneClear the current value of the select component.

Types

ts
type T = Record<string, any>;
type ModelValue = T | T[] | undefined;
type Shadow =
  | 'xs'
  | 'sm'
  | 'md'
  | 'lg'
  | 'xl'
  | '2xl'
  | '3xl'
  | 'inner'
  | 'none';

defineSlots<{
  default?: (props: {
    modelValue: ModelValue;
    multiple: boolean;
    itemValue: string;
    itemText: string;
    selectionItemProps: InstanceType<typeof VBadge>['$props'];
  }) => any;
  button?: (props: {open: boolean}) => any;
  'selection-item'?: (props: {
    item: T;
    idx: any;
    itemText: string;
    itemValue: string;
    remove: () => void;
    open: boolean;
  }) => any;
  selected?: (props: {
    modelValue: ModelValue;
    multiple?: boolean;
    placeholder?: string;
    itemText?: string;
    itemValue?: string;
    open: boolean;
  }) => any;
  item?: (props: {
    item: T;
    active: boolean;
    selected: boolean;
    itemText?: string;
    itemValue?: string;
    open: boolean;
  }) => any;
  hint?: (props: {hint?: string}) => any;
  error?: (props: {
    error?: boolean;
    errorMessage?: string;
    hideError?: boolean;
  }) => any;
  selection?: (props: {
    modelValue: ModelValue;
    multiple?: boolean;
    itemValue?: string;
    itemText?: string;
    selectionItemProps?: InstanceType<typeof VBadge>['$props'];
    open: boolean;
  }) => any;
  empty?: (props: {items: T[]; emptyText?: string; open: boolean}) => any;
  'item-text'?: (props: {
    item: T;
    itemText?: string;
    itemValue?: string;
    active: boolean;
    selected: boolean;
    open: boolean;
  }) => any;
  'check-icon'?: (props: {selected: boolean; icon: string}) => any;
  'new-item-text'?: (props: {item: T}) => any;
}>();
type T = Record<string, any>;
type ModelValue = T | T[] | undefined;
type Shadow =
  | 'xs'
  | 'sm'
  | 'md'
  | 'lg'
  | 'xl'
  | '2xl'
  | '3xl'
  | 'inner'
  | 'none';

defineSlots<{
  default?: (props: {
    modelValue: ModelValue;
    multiple: boolean;
    itemValue: string;
    itemText: string;
    selectionItemProps: InstanceType<typeof VBadge>['$props'];
  }) => any;
  button?: (props: {open: boolean}) => any;
  'selection-item'?: (props: {
    item: T;
    idx: any;
    itemText: string;
    itemValue: string;
    remove: () => void;
    open: boolean;
  }) => any;
  selected?: (props: {
    modelValue: ModelValue;
    multiple?: boolean;
    placeholder?: string;
    itemText?: string;
    itemValue?: string;
    open: boolean;
  }) => any;
  item?: (props: {
    item: T;
    active: boolean;
    selected: boolean;
    itemText?: string;
    itemValue?: string;
    open: boolean;
  }) => any;
  hint?: (props: {hint?: string}) => any;
  error?: (props: {
    error?: boolean;
    errorMessage?: string;
    hideError?: boolean;
  }) => any;
  selection?: (props: {
    modelValue: ModelValue;
    multiple?: boolean;
    itemValue?: string;
    itemText?: string;
    selectionItemProps?: InstanceType<typeof VBadge>['$props'];
    open: boolean;
  }) => any;
  empty?: (props: {items: T[]; emptyText?: string; open: boolean}) => any;
  'item-text'?: (props: {
    item: T;
    itemText?: string;
    itemValue?: string;
    active: boolean;
    selected: boolean;
    open: boolean;
  }) => any;
  'check-icon'?: (props: {selected: boolean; icon: string}) => any;
  'new-item-text'?: (props: {item: T}) => any;
}>();

Usage

Here's an example how to use the component:

vue
<script setup lang="ts">
import {ref} from 'vue';
import {Select as SelectMenu} from '@morpheme/select';

const items = ref([
  {text: 'Item 1', value: 1},
  {text: 'Item 2', value: 2},
  {text: 'Item 3', value: 3},
]);

const selectedValue = ref();

const handleChange = (value) => {
  console.log('Changed value to:', value);
};
</script>

<template>
  <SelectMenu
    :items="items"
    v-model="selectedValue"
    placeholder="Select an item"
    label="Sample Label"
    @change="handleChange"
  >
    <template #item="{item, active, selected, open}">
      <!-- Custom item template -->
      <div :class="{'active-item': active, 'selected-item': selected}">
        {{ item.text }}
      </div>
    </template>

    <template #selected="{modelValue, open}">
      <!-- Custom selected display -->
      <div v-if="modelValue">You selected: {{ modelValue.text }}</div>
    </template>
  </SelectMenu>
</template>

<style scoped>
.active-item {
  background-color: lightblue;
}

.selected-item {
  font-weight: bold;
}
</style>
<script setup lang="ts">
import {ref} from 'vue';
import {Select as SelectMenu} from '@morpheme/select';

const items = ref([
  {text: 'Item 1', value: 1},
  {text: 'Item 2', value: 2},
  {text: 'Item 3', value: 3},
]);

const selectedValue = ref();

const handleChange = (value) => {
  console.log('Changed value to:', value);
};
</script>

<template>
  <SelectMenu
    :items="items"
    v-model="selectedValue"
    placeholder="Select an item"
    label="Sample Label"
    @change="handleChange"
  >
    <template #item="{item, active, selected, open}">
      <!-- Custom item template -->
      <div :class="{'active-item': active, 'selected-item': selected}">
        {{ item.text }}
      </div>
    </template>

    <template #selected="{modelValue, open}">
      <!-- Custom selected display -->
      <div v-if="modelValue">You selected: {{ modelValue.text }}</div>
    </template>
  </SelectMenu>
</template>

<style scoped>
.active-item {
  background-color: lightblue;
}

.selected-item {
  font-weight: bold;
}
</style>