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.
<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.
<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
groupproperty - A-Z: Sorts alphabetically in ascending order
- Z-A: Sorts alphabetically in descending order
Grouped by default
Grouped by A-Z
<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.
<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.
<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.
<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.
<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.
<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.
<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.
Selected: None selected
<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
| Prop | Description | Type | Default |
|---|---|---|---|
modelValue (v-model) | Two-way binding for selected items containing full item objects | MenuListType[] | [] |
menuList | Array of items to display | MenuListType[] | [] (required) |
groupItemsBy | Grouping strategy: 'default' (by group property), 'A-Z' (ascending), or 'Z-A' (descending) | 'default' | 'A-Z' | 'Z-A' | undefined |
multiSelect | Enable multi-selection mode with checkboxes | boolean | false |
preSelectedItems | Pre-select items by their values | (string | number | Record<string, unknown>)[] | [] |
searchableMenu | Display search input for filtering items | boolean | false |
searchableMenuPlaceholder | Placeholder text for search input | string | 'Search...' |
searchValue | External search value (two-way binding) | string | '' |
menuLevel | Nesting level for hierarchical lists | number | 0 |
ladderized | Enable hierarchical/ladderized list display | boolean | false |
disabledLocalSearch | Disable local search filtering | boolean | false |
loading | Show loading skeleton instead of items | boolean | false |
noCheck | Hide checkmark icon in single-select mode | boolean | false |
lozenge | Display items as lozenges | boolean | false |
supportingDisplayText | Display custom text (e.g., "2 Selected") | string | '' |
displayListItemSelected | Display count of selected items when searchable | boolean | false |
stickySearchOffset | Offset for sticky search header | string | number | 0 |
itemIcon | Default icon for all items | string | '' |
disabledUnselectedItems | Disable and gray out unselected items | boolean | false |
Events
| Event | Description | Payload |
|---|---|---|
update:modelValue | Emitted when selection changes | MenuListType[] - Array of selected item objects |
update:searchValue | Emitted when search input changes | string - New search text |
@get-single-selected-item | Emitted when item selected in single-select mode | MenuListType - Selected item object |