Skip to content

Multiselect

The FTMultiselect component is a searchable checkbox multiselect for choosing a subset of named items — as a dropdown (default) or an always-open inline panel. Items can carry an optional color swatch and an optional count. Two ordering modes: alphabetical (az) and drag-to-reorder (manual).

Basic usage

vue
<script setup lang="ts">
import { ref } from 'vue';
import { FTMultiselect, type IFTMultiselectItem } from '@fasttrack-solutions/vue-components-lib';

const items: IFTMultiselectItem[] = [
  { name: 'Casino', count: 128, color: '#e53e3e' },
  { name: 'Sports', count: 42, color: '#3182ce' },
  { name: 'Archived' }, // no swatch, no count
];

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

<template>
  <FTMultiselect v-model="selected" :items="items" label="Segments" placeholder="Segments" />
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { FTMultiselect, type IFTMultiselectItem } from '@fasttrack-solutions/vue-components-lib';

const items: IFTMultiselectItem[] = [
  { name: 'Casino', count: 128, color: '#e53e3e' },
  { name: 'Sports', count: 42, color: '#3182ce' },
  { name: 'Archived' }, // no swatch, no count
];

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

<template>
  <FTMultiselect v-model="selected" :items="items" label="Segments" placeholder="Segments" />
</template>

Playground

Properties

Selected: (none)
Mode: az
<script setup lang="ts">
import { ref } from 'vue';

const selected = ref([]);
const mode = ref("az");
const manualOrder = ref([]);
const items = ref([
  {
    "name": "Casino",
    "count": 128,
    "color": "#e53e3e"
  },
  {
    "name": "Sports",
    "count": 42,
    "color": "#3182ce"
  },
  {
    "name": "Poker",
    "count": 7,
    "color": "#38a169"
  },
  {
    "name": "Archived"
  },
  {
    "name": "Bingo",
    "count": 0
  }
]);
</script>

<template>
  <FTMultiselect
    v-model="selected"
    v-model:mode="mode"
    v-model:manualOrder="manualOrder"
    :items="items"
    label="Segments"
    placeholder="Segments"
  />
</template>

Items

IFTMultiselectItemname is both the display text and the identity key (v-model and manualOrder are arrays of names). count renders after the name only when present (0 is valid and renders).

The leading swatch column appears as soon as any item carries a color; items in that list without one render a muted placeholder so every row stays aligned. A list where no item has a color renders no swatch column at all.

Icons

iconPrefix sets the FontAwesome prefix for the caret, search glyph and drag grip (angle-down, magnifying-glass, grip-dots-vertical). It defaults to 'fas'; apps that register only sharp-solid icons must pass iconPrefix="fass" or the three icons render as nothing — which also disables manual reordering, since the drag handle is the grip icon.

Ordering modes

v-model:mode switches between 'az' (locale-aware alphabetical, default) and 'manual' (drag rows by the grip handle). Switching to manual seeds v-model:manualOrder with the current visible order if it is empty. Items missing from manualOrder are appended after the ordered ones, and an empty manualOrder renders alphabetically — so mounting straight into 'manual' gives the same order as switching into it, without the component writing to your state on mount.

Set showSort to false to hide the A-Z / Manual toggle for consumers that don't offer reordering. This hides the control only — v-model:mode still works, so you can pin the panel to either order, and the manual grips still appear if the mode is 'manual'. With the toggle hidden the bulk actions stay right-aligned, and if there are also no items the head bar is dropped rather than rendered empty.

Search and bulk actions

Searching filters rows by case-insensitive substring (searchable, on by default). Select All / Select None operate on the visible rows only — selections on filtered-out items are preserved. The search query clears when the dropdown closes.

Inline

Set inline to drop the trigger button and render the panel open, in-flow — for sidebars and filter rails.

Peer dependencies

FTMultiselect requires the consumer to install @vueuse/core, vue-draggable-next, and sortablejs (peer dependencies of this library — vue-draggable-next itself depends on sortablejs).

Props

PropTypeDefaultDescription
itemsIFTMultiselectItem[]— (required)Items to choose from
labelstring'Items'Label above the trigger (dropdown mode only)
placeholderstring'Items'Text inside the trigger button
inlinebooleanfalseRender the panel open and in-flow, no trigger
searchablebooleantrueShow the search input
searchPlaceholderstring'Search…'Search input placeholder
showBadgebooleantrueShow the selected/total badge in the trigger
showSortbooleantrueShow the A-Z / Manual sort toggle
isRequiredbooleanfalseMark the field required (dropdown mode only)
iconPrefixstring'fas'FontAwesome prefix for caret/search/grip icons

Naming: show* props hide a control without disabling what it controls — showSort: false hides the sort toggle, but v-model:mode still applies. Adjective props (searchable, inline) switch the capability or mode itself.

Required

isRequired renders the same * marker FTInput uses — same class name, colour token (--ft-input-required-color, falling back to --color-brand-pink-400), size and offset — so the two line up in a shared form. It also sets aria-required on the trigger. The marker lives inside the <label>, which only renders in dropdown mode, so it has no effect when inline is set.

Models

ModelTypeDefaultDescription
v-modelstring[][]Selected item names
v-model:mode'az' | 'manual''az'Ordering mode
v-model:manualOrderstring[][]Item names in manual order