Skip to content

List

The List component is a powerful and flexible UI element designed for displaying and selecting items from a list. It supports a wide range of features including single and multi-select modes, item grouping, search functionality, hierarchical navigation, and lozenge display formats.

Basic Usage

The most basic usage involves binding your selection to v-model and providing a list of items via the menu-list prop. Each item must have at minimum a text (display label) and value (unique identifier) property.

No results found
vue
<template>
  <div
    :class="[
      'spr-max-h-[300px] spr-overflow-auto spr-rounded-md spr-p-2',
      'spr-border-color-weak spr-border spr-border-solid',
    ]"
  >
    <spr-list v-model="selectedItems" :menu-list="menuList" />
  </div>
</template>

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

const selectedItems = ref([]);

const menuList = ref([
  { text: 'Apple', value: 'apple' },
  { text: 'Banana', value: 'banana' },
  { text: 'Cherry', value: 'cherry' },
  { text: 'Date', value: 'date' },
  { text: 'Elderberry', value: 'elderberry' },
  { text: 'Fig', value: 'fig' },
  { text: 'Grape', value: 'grape' },
  { text: 'Honeydew', value: 'honeydew' },
  { text: 'Kiwi', value: 'kiwi' },
  { text: 'Mango', value: 'mango' },
]);
</script>

Multi-Select

Enable multiple item selection by adding the multi-select prop. This displays checkboxes next to each item, allowing users to select multiple items simultaneously.

No results found
vue
<template>
  <div
    :class="[
      'spr-max-h-[300px] spr-overflow-auto spr-rounded-md spr-p-2',
      'spr-border-color-weak spr-border spr-border-solid',
    ]"
  >
    <spr-list v-model="selectedItems" :menu-list="menuList" multi-select />
  </div>
</template>

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

const selectedItems = ref([]);

const menuList = ref([
  { text: 'Apple', value: 'apple' },
  { text: 'Banana', value: 'banana' },
  { text: 'Cherry', value: 'cherry' },
  { text: 'Date', value: 'date' },
  { text: 'Elderberry', value: 'elderberry' },
]);
</script>

Grouping Items

Group items using the group-items-by prop with values 'default', 'A-Z', or 'Z-A':

  • default: Groups by the item's group property
  • A-Z: Sorts alphabetically in ascending order
  • Z-A: Sorts alphabetically in descending order
Grouped by default
Grouped by A-Z
vue
<template>
  <spr-list v-model="selectedItems" :menu-list="menuList" group-items-by="default" />
</template>

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

const selectedItems = ref([]);

const menuList = ref([
  { text: 'Apple', value: 'apple', group: 'Fruits' },
  { text: 'Banana', value: 'banana', group: 'Fruits' },
  { text: 'Carrot', value: 'carrot', group: 'Vegetables' },
  { text: 'Date', value: 'date', group: 'Fruits' },
  { text: 'Eggplant', value: 'eggplant', group: 'Vegetables' },
]);
</script>

Searchable List

Add search functionality with the searchable-menu prop. Users can filter items by typing in the search field.

No results found
vue
<template>
  <spr-list
    v-model="selectedItems"
    :menu-list="menuList"
    searchable-menu
    searchable-menu-placeholder="Search items..."
  />
</template>

With Icons and Subtext

Enhance list items with icons and descriptive subtext by including icon and subtext properties.

No results found
vue
<template>
  <spr-list v-model="selectedItems" :menu-list="itemsWithIcons" />
</template>

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

const selectedItems = ref([]);

const itemsWithIcons = ref([
  {
    text: 'Home',
    value: 'home',
    icon: 'ph:house',
    subtext: 'Go to home page',
  },
  {
    text: 'Settings',
    value: 'settings',
    icon: 'ph:gear',
    subtext: 'Configure preferences',
    iconColor: 'spr-text-blue-500',
  },
  {
    text: 'Users',
    value: 'users',
    icon: 'ph:users',
    subtext: 'Manage user accounts',
  },
]);
</script>

Ladderized (Hierarchical) List

Create nested hierarchical lists using the ladderized prop and including sublevel properties in items.

No results found
vue
<template>
  <spr-ladderized-list v-model="selectedItems" :menu-list="hierarchicalData" />
</template>

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

const selectedItems = ref([]);

const hierarchicalData = ref([
  {
    text: 'Fruits',
    value: 'fruits',
    sublevel: [
      { text: 'Apple', value: 'apple' },
      { text: 'Banana', value: 'banana' },
      { text: 'Cherry', value: 'cherry' },
    ],
  },
  {
    text: 'Vegetables',
    value: 'vegetables',
    sublevel: [
      { text: 'Carrot', value: 'carrot' },
      { text: 'Broccoli', value: 'broccoli' },
    ],
  },
]);
</script>

Lozenge Display

The List component supports two different lozenge display modes:

1. Full Lozenge Mode (Item as Lozenge)

Display entire list items as lozenges by enabling the lozenge prop and providing lozengeProps for each item. The item becomes the lozenge itself.

No results found
vue
<template>
  <spr-list v-model="selectedItems" :menu-list="lozengeItems" lozenge />
</template>

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

const selectedItems = ref([]);

const lozengeItems = ref([
  {
    text: 'Active',
    value: 'active',
    lozengeProps: {
      label: 'Active',
      tone: 'success',
      fill: true,
      icon: 'ph:check-circle',
    },
  },
  {
    text: 'Pending',
    value: 'pending',
    lozengeProps: {
      label: 'Pending',
      tone: 'neutral',
      fill: false,
      icon: 'ph:clock',
    },
  },
  {
    text: 'Disabled',
    value: 'disabled',
    lozengeProps: {
      label: 'Disabled',
      tone: 'negative',
      fill: true,
      icon: 'ph:x-circle',
    },
  },
]);
</script>

2. Lozenge Badge (Item with Right-Side Lozenge)

Display a regular list item with a lozenge badge on the right side by using the lozenge property on individual items. This allows you to show metadata or status alongside the item text.

No results found
vue
<template>
  <spr-list v-model="selectedItems" :menu-list="menuItems" />
</template>

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

const selectedItems = ref([]);

const menuItems = ref([
  {
    text: 'Task 1',
    value: 'task1',
    subtext: 'Due tomorrow',
    lozenge: {
      label: 'Pending',
      tone: 'neutral',
      fill: false,
    },
  },
  {
    text: 'Task 2',
    value: 'task2',
    subtext: 'Completed',
    lozenge: {
      label: 'Done',
      tone: 'success',
      fill: true,
    },
  },
  {
    text: 'Task 3',
    value: 'task3',
    subtext: 'In progress',
    lozenge: {
      label: 'Active',
      tone: 'success',
      fill: true,
    },
  },
]);
</script>

Pre-Selected Items

Use pre-selected-items to set initial selections based on item values.

vue
<template>
  <spr-list v-model="selectedItems" :menu-list="menuList" :pre-selected-items="['apple', 'banana']" />
</template>

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

const selectedItems = ref([]);

const menuList = ref([
  { text: 'Apple', value: 'apple' },
  { text: 'Banana', value: 'banana' },
  { text: 'Cherry', value: 'cherry' },
]);
</script>

Event Handling

Use @update:model-value to react to selection changes and retrieve the complete selected item objects.

No results found

Selected: None selected

vue
<template>
  <spr-list v-model="selectedItems" :menu-list="menuList" @update:model-value="handleSelection" />
  <div v-if="selectedItem" class="spr-mt-4 spr-bg-blue-50 spr-p-4">
    <p>Selected Item: {{ selectedItem.text }}</p>
  </div>
</template>

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

const selectedItems = ref([]);
const selectedItem = ref(null);

const menuList = ref([
  { text: 'Apple', value: 'apple' },
  { text: 'Banana', value: 'banana' },
  { text: 'Cherry', value: 'cherry' },
]);

const handleSelection = (items) => {
  selectedItem.value = items[0] || null;
};
</script>

API Reference

Props

PropDescriptionTypeDefault
modelValue (v-model)Two-way binding for selected items containing full item objectsMenuListType[][]
menuListArray of items to displayMenuListType[][] (required)
groupItemsByGrouping strategy: 'default' (by group property), 'A-Z' (ascending), or 'Z-A' (descending)'default' | 'A-Z' | 'Z-A'undefined
multiSelectEnable multi-selection mode with checkboxesbooleanfalse
preSelectedItemsPre-select items by their values(string | number | Record<string, unknown>)[][]
searchableMenuDisplay search input for filtering itemsbooleanfalse
searchableMenuPlaceholderPlaceholder text for search inputstring'Search...'
searchValueExternal search value (two-way binding)string''
menuLevelNesting level for hierarchical listsnumber0
ladderizedEnable hierarchical/ladderized list displaybooleanfalse
disabledLocalSearchDisable local search filteringbooleanfalse
loadingShow loading skeleton instead of itemsbooleanfalse
noCheckHide checkmark icon in single-select modebooleanfalse
lozengeDisplay items as lozengesbooleanfalse
supportingDisplayTextDisplay custom text (e.g., "2 Selected")string''
displayListItemSelectedDisplay count of selected items when searchablebooleanfalse
stickySearchOffsetOffset for sticky search headerstring | number0
itemIconDefault icon for all itemsstring''
disabledUnselectedItemsDisable and gray out unselected itemsbooleanfalse

Events

EventDescriptionPayload
update:modelValueEmitted when selection changesMenuListType[] - Array of selected item objects
update:searchValueEmitted when search input changesstring - New search text
@get-single-selected-itemEmitted when item selected in single-select modeMenuListType - Selected item object