- Multi Select includes Default, Hover, Focus, Focus Visible, and Locked states.
- Focus Visible is triggered by keyboard navigation using the Tab key.
- Focus is shown while the Multi Select is open with a mouse click.
- The Invalid validation state can only have Default and Hover states. When the user clicks on an Invalid Multi Select, the validation is cleared and the component transitions to the Focus state. Pressing Tab instead transitions it to the Focus Visible state.
Multiselect
Organism
The Multi Select Component is a form input component used to allow users to make one or more selections from a list of options. It supports two display modes: Lozenges, where selected options appear as individual chips with an overflow indicator, and Searchable Counter, which shows a summary count when closed and a search field when open for filtering options.
The list of options can behave in two ways:
- Static – selected options remain in their original position in the list.
- Selected on top – selected options are automatically moved to the top of the list, separated from unselected ones by a Divider. Both groups are sorted alphabetically. This behavior cannot be prototyped in Figma.
Playground
TheAppWrapper is set to max-width: 380px
Multiselect component
<
Multiselect
options
=
"[
{
"value": 1,
"text": "Option 1 is a very long option, so we can check whether truncation works with it",
"isDisabled": false,
"isSelected": false
},
{
"value": 4,
"text": "N/mm<sup>2</sup>",
"isDisabled": false,
"isSelected": false,
"hasAction": true
},
{
"value": 7,
"text": "Option 7",
"isDisabled": false,
"isSelected": false
},
{
"value": 2,
"text": "Option 2",
"isDisabled": true,
"isSelected": false
},
{
"value": 5,
"text": "Option 5",
"isDisabled": false,
"isSelected": false,
"isIndeterminate": true
},
{
"value": 3,
"text": "Option 3",
"isDisabled": false,
"isSelected": false
},
{
"value": 6,
"text": "Option 6",
"isDisabled": false,
"isSelected": false
}
]"
selectionBehavior
=
"static"
animateGrouping
label
=
"Label"
placeholder
=
"Select an option"
labelCategory
=
"large"
noOfOptionsToShow
searchOptions
=
"{
"enableSearch": false,
"caseSensitive": false,
"placeholder": "",
"summaryText": ""
}"
/>
Anatomy
- Form Label - Tells the user what they are selecting for and indicates if selection is required. Can be hidden.
- Select Field - This is where the selected options are displayed using Lozenges. Can be individual Lozenges or a summary Lozenge. It changes state when hovered, focused or locked. Placeholder text is displayed when no selections have been made yet. For Searchable type, when the menu is opened, a search Icon and Placeholder text appears and the user can type to search through options.
- Lozenges - representing the selected options.
- Icon (Chevron Down/Up) - Indicates whether the option list is closed or open. Switches to Chevron Up when clicked and the menu is opened.
- Help Text - Additional instruction to the user regarding the selection. Also can be hidden.
- Option List - containing the options which can be selected. In Figma there can be 2-10 custom options, but in practice there can of course be more. The height is set to hug with a max height of 192px so that when there are more than 6 options, it will scroll. It can open up or down to maintain readability at various locations on screen.
- Checkboxes - representing each option that can be selected. Multiple options can be selected at a time.
States
Variants
Display
- Defines how selected options are displayed inside the component.
- No Selection — No options have been selected yet. Placeholder text is shown.
- Lozenges — Each selected option is represented as an individual chip. If all selected options do not fit, the overflow is indicated by a counter chip (e.g. "+3").
- Searchable — When closed, displays a single lozenge summarizing the number of selected options. When open, the summary is replaced by a search field for filtering options in the dropdown.
Menu
- Can be open or closed.
Menu Direction
- The option list can open Down or Up to maintain readability at various locations on screen.
FormLabel
- Show or hide Form Label.
HelpText + Validation
- Show or hide Help Text.
- The Multi Select supports two validation states: None and Invalid. When validation is applied, the Help Text communicates the current validation result.
- If the Multi Select has informational Help Text and a validation state is triggered, the validation message replaces the original informational message. Validation feedback always takes priority over informational Help Text.
- Multi Select does not have a Validated state. Its values are predefined, so selecting an available option does not require positive validation feedback.
Properties
ts
export interface MultiselectGenericProps<T extends string | number> extends FormLabelOptionalProps {
modelValue: T[] | null;
selectionBehavior?: 'static' | 'selectedOnTop';
options: MultiselectOptionGeneric<T>[];
placeholder?: string;
checkboxPosition?: 'leading' | 'trailing';
disabled?: boolean;
id?: string;
icon?: IconName;
action?: MultiselectActionGeneric<T>;
// if set to 0, all options will be shown, default: 0
noOfOptionsToShow?: number;
// determine to group options by their disabled state or whether they are selected
groupOptionsBy?: 'disabled' | 'selected';
animateGrouping?: boolean;
sortOptions?: MultiSortOptions<'alphabetical' | 'numerical'>;
searchOptions?: MultiSearchOptions<T>;
}
export interface MultiSortOptions<T extends 'alphabetical' | 'numerical'> {
type: T;
order: 'asc' | 'ascending' | 'desc' | 'descending';
target: 'text' | 'value';
ignoreCase: T extends 'alphabetical' ? boolean : never;
}
export interface MultiSearchOptions<T extends string | number> {
enableSearch: boolean;
caseSensitive?: boolean;
placeholder?: string;
summaryText?: string;
searchFunction?: (options: MultiselectOptionGeneric<T>[]) => MultiselectOptionGeneric<T>[];
}ts
export interface MultiselectOptionGeneric<T extends string | number> {
text: string | number;
value: T;
isSelected: boolean;
isIndeterminate?: boolean;
isDisabled?: boolean;
hasAction?: boolean;
}ts
export interface MultiselectActionGeneric<T extends string | number> {
text: string;
icon: IconName;
function: (option: MultiselectOptionGeneric<T>) => Promise<void>;
}ModelValues
For more information on ModelValues please have a look to the Vue's Data Binding section.
ts
const searchString = defineModel('searchString', { default: '' });Developer notes
- Pressing
Tabfocuses the component.Enterwhen focused opens the dropdown. - Arrow keys move through options.
Enteron a highlighted option toggles selection and does not close the dropdown. Tabagain moves to the next control;Shift+Tabwhile browsing options returns focus to the container.- Chips: selections stay visible as Lozenges; overflow uses “+N”.
- Searchable Counter (
searchOptions.enableSearch): open state swaps the summary Lozenge for a search field that filters options. - Selection behavior (
selectionBehavior):statickeeps order;selectedOnTopgroups selected options above a Divider. - Optional per-option action (Icon Button) via the
actionprop.
vue
<script setup>
import { ref } from 'vue';
import { Multiselect } from '@pohlcon/design-system';
const modelValue = ref([]);
const searchString = ref('');
const options = ref([
{ text: 'Option 1', value: 'option1', isSelected: false },
{ text: 'Option 2', value: 'option2', isSelected: false },
{ text: 'Option 3', value: 'option3', isSelected: false },
]);
</script>
<template>
<Multiselect
v-model="modelValue"
v-model:searchString="searchString"
:options="options"
label="Multiselect"
labelPosition="labelAbove"
placeholder="Select options"
:searchOptions="{ enableSearch: true }"
/>
</template>