Skip to content

List

Basic Usage

The list component uses the v-model directive to bind the selected items to a variable. The menu-list prop is used to pass the list of items to display in the menu. Each item in the list should contain text and value properties.

No results found
Output:
[]
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="singleSelectOutput" :menu-list="menuList" />
  </div>
</template>

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

const singleSelectOutput = 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: '5 Grape', value: 'grape' },
  { text: 'Honeydew', value: 'honeydew' },
  { text: 'Indian Fig', value: 'indian_fig' },
  { text: 'Jackfruit', value: 'jackfruit' },
  { text: 'Kiwi', value: 'kiwi' },
  { text: 'Lemon', value: 'lemon' },
  { text: 'Mango', value: 'mango' },
  { text: 'Nectarine', value: 'nectarine' },
  { text: '89 Watermelon', value: 'watermelon' },
  { text: 'Xigua', value: 'xigua' },
  { text: 'Yunnan Hackberry', value: 'yunnan_hackberry' },
  { text: '1 Zucchini', value: 'zucchini' },
  { text: 'Apricot', value: 'apricot' },
  { text: 'Blueberry', value: 'blueberry' },
  { text: 'Cantaloupe', value: 'cantaloupe' },
  { text: 'Dragonfruit', value: 'dragonfruit' },
  { text: 'Pineapple', value: 'pineapple' },
]);
</script>

NOTE

The menu-list is an array of MenuListType as defined below:

ts
type MenuListType = {
  text: string;
  value: string;
  subtext?: string;
  group?: string; // Property to group items
  sublevel?: MenuListType[]; // Property used for ladderized list
  disabled?: boolean;
  _originalObject?: Record<string, unknown>; // Store original object reference when mapping complex objects
  icon?: string; // String value for Iconify
  iconColor?: string;
  textColor?: string;
  lozengeProps?: LozengePropTypes; // Props for the lozenge component when list is displayed as lozenge
  onClickFn?: () => void;
};

Pre-Selected Items

You can pre-select items by using pre-selected-items in the component and passing an array of strings that correspond to thevalue of the item.

No results found
Output:
[]
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="singleSelectOutput" :menu-list="menuList" :pre-selected-items="preselectedItem" />
  </div>
</template>

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

const singleSelectOutput = ref([]);
const preselectedItem = ref(['apple']);

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: '5 Grape', value: 'grape' },
  { text: 'Honeydew', value: 'honeydew' },
  { text: 'Indian Fig', value: 'indian_fig' },
  { text: 'Jackfruit', value: 'jackfruit' },
  { text: 'Kiwi', value: 'kiwi' },
  { text: 'Lemon', value: 'lemon' },
  { text: 'Mango', value: 'mango' },
  { text: 'Nectarine', value: 'nectarine' },
  { text: '89 Watermelon', value: 'watermelon' },
  { text: 'Xigua', value: 'xigua' },
  { text: 'Yunnan Hackberry', value: 'yunnan_hackberry' },
  { text: '1 Zucchini', value: 'zucchini' },
  { text: 'Apricot', value: 'apricot' },
  { text: 'Blueberry', value: 'blueberry' },
  { text: 'Cantaloupe', value: 'cantaloupe' },
  { text: 'Dragonfruit', value: 'dragonfruit' },
  { text: 'Pineapple', value: 'pineapple' },
]);
</script>

Grouped Items

You can group items by passing the group-items-by prop. The value of this prop can be either default,A-Z or Z-A. default will group the list by the individual item group.

Grouped by default
Grouped by A-Z
Grouped by Z-A:
vue
<template>
  <div class="spr-grid spr-gap-4">
    <div>
      <h5 class="spr-mb-2">Grouped by default</h5>
      <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="singleSelectOutput.example3" :menu-list="groupedMenuList" group-items-by="default" />
      </div>
    </div>
    <div>
      <h5 class="spr-mb-2">Grouped by A-Z</h5>
      <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="singleSelectOutput.example4" :menu-list="groupedMenuList" group-items-by="A-Z" />
      </div>
    </div>
    <div>
      <h5 class="spr-mb-2">Grouped by Z-A:</h5>
      <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="singleSelectOutput.example5" :menu-list="groupedMenuList" group-items-by="Z-A" />
      </div>
    </div>
  </div>
</template>

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

const groupedMenuList = 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' },
  { text: 'Fig', value: 'fig', group: 'Fruits' },
  { text: 'Grape', value: 'grape', group: 'Fruits' },
  { text: 'Honeydew', value: 'honeydew', group: 'Fruits' },
  { text: 'Indian Fig', value: 'indian_fig', group: 'Fruits' },
  { text: 'Jackfruit', value: 'jackfruit', group: 'Fruits' },
  { text: 'Kale', value: 'kale', group: 'Vegetables' },
  { text: 'Lemon', value: 'lemon', group: 'Fruits' },
  { text: 'Mango', value: 'mango', group: 'Fruits' },
  { text: 'Nectarine', value: 'nectarine', group: 'Fruits' },
  { text: 'Okra', value: 'okra', group: 'Vegetables' },
  { text: 'Peach', value: 'peach', group: 'Fruits' },
  { text: 'Quince', value: 'quince', group: 'Fruits' },
  { text: 'Radish', value: 'radish', group: 'Vegetables' },
  { text: 'Spinach', value: 'spinach', group: 'Vegetables' },
  { text: 'Tomato', value: 'tomato', group: 'Vegetables' },
  { text: 'Ugli Fruit', value: 'ugli_fruit', group: 'Fruits' },
  { text: 'Watermelon', value: 'watermelon', group: 'Fruits' },
  { text: 'Xigua', value: 'xigua', group: 'Fruits' },
  { text: 'Yam', value: 'yam', group: 'Vegetables' },
  { text: 'Zucchini', value: 'zucchini', group: 'Vegetables' },
]);

const singleSelectOutput = ref({
  example3: [],
  example4: [],
  example5: [],
});
</script>

Multi Select

You can enable multiple selection of items by passing the multi-select prop, which can be either true or false.

No results found
vue
<template>
  <div class="spr-grid spr-gap-4">
    <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="singleSelectOutput.example6" :menu-list="menuList" multi-select />
    </div>

    <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="singleSelectOutput.example7" :menu-list="menuList" group-items-by="A-Z" multi-select />
    </div>
  </div>
</template>

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

const singleSelectOutput = ref({
  example6: [],
  example7: [],
});

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: '5 Grape', value: 'grape' },
  { text: 'Honeydew', value: 'honeydew' },
  { text: 'Indian Fig', value: 'indian_fig' },
  { text: 'Jackfruit', value: 'jackfruit' },
  { text: 'Kiwi', value: 'kiwi' },
  { text: 'Lemon', value: 'lemon' },
  { text: 'Mango', value: 'mango' },
  { text: 'Nectarine', value: 'nectarine' },
  { text: '89 Watermelon', value: 'watermelon' },
  { text: 'Xigua', value: 'xigua' },
  { text: 'Yunnan Hackberry', value: 'yunnan_hackberry' },
  { text: '1 Zucchini', value: 'zucchini' },
  { text: 'Apricot', value: 'apricot' },
  { text: 'Blueberry', value: 'blueberry' },
  { text: 'Cantaloupe', value: 'cantaloupe' },
  { text: 'Dragonfruit', value: 'dragonfruit' },
  { text: 'Pineapple', value: 'pineapple' },
]);
</script>

Get Selected Item

You can retrieve the data of the selected item using the @update:model-value emit.

No results found
Output:
No selected item
Output:
No selected items
vue
<template>
  <div class="spr-grid spr-gap-4">
    <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="singleSelectOutput.example8" :menu-list="menuList" @update:model-value="handleSingleSelect" />
    </div>
    <div class="spr-my-3 spr-bg-blue-100 spr-p-4">
      <h5>Output:</h5>
      <span>{{ singleSelectText }}</span>
    </div>

    <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="singleSelectOutput.example9"
        :menu-list="menuList"
        group-items-by="A-Z"
        multi-select
        @update:model-value="handleMultiSelect"
      />
    </div>
    <div class="spr-my-3 spr-bg-blue-100 spr-p-4">
      <h5>Output:</h5>
      <span>{{ multipleSelectText }}</span>
    </div>
  </div>
</template>

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

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: '5 Grape', value: 'grape' },
  { text: 'Honeydew', value: 'honeydew' },
  { text: 'Indian Fig', value: 'indian_fig' },
  { text: 'Jackfruit', value: 'jackfruit' },
  { text: 'Kiwi', value: 'kiwi' },
  { text: 'Lemon', value: 'lemon' },
  { text: 'Mango', value: 'mango' },
  { text: 'Nectarine', value: 'nectarine' },
  { text: '89 Watermelon', value: 'watermelon' },
  { text: 'Xigua', value: 'xigua' },
  { text: 'Yunnan Hackberry', value: 'yunnan_hackberry' },
  { text: '1 Zucchini', value: 'zucchini' },
  { text: 'Apricot', value: 'apricot' },
  { text: 'Blueberry', value: 'blueberry' },
  { text: 'Cantaloupe', value: 'cantaloupe' },
  { text: 'Dragonfruit', value: 'dragonfruit' },
  { text: 'Pineapple', value: 'pineapple' },
]);

const singleSelectOutput = ref({
  example8: [],
  example9: [],
});

const singleSelectText = ref('No selected item');
const handleSingleSelect = (data) => {
  singleSelectText.value = data[0].text;
};

const multipleSelectText = ref('No selected items');
const handleMultiSelect = (data) => {
  multipleSelectText.value = data.map((item) => item.text).join(', ');
};
</script>

List with Subtext

You can add subtext to the list items by including the subtext property in the object from the menu-list array.

No results found
vue
<template>
  <div class="spr-grid spr-gap-4">
    <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="singleSelectOutput" :menu-list="mockDropdownData" />
    </div>
  </div>
</template>

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

const singleSelectOutput = ref([]);
const mockDropdownData = [
  {
    text: 'Lion',
    value: 'lion',
    subtext: 'King of the jungle',
  },
  {
    text: 'Elephant',
    value: 'elephant',
    subtext: 'Largest land animal',
  },
  {
    text: 'Giraffe',
    value: 'giraffe',
    subtext: 'Tallest living terrestrial animal',
  },
  {
    text: 'Zebra',
    value: 'zebra',
    subtext: 'Known for distinctive black and white stripes',
  },
];
</script>

Ladderized List

Ladderized list is a variation of the list component that allows you to display items in a hierarchical structure. You can pass the sublevel property in the object from the menu-list array to create a ladderized list.

No results found
vue
<template>
  <div class="spr-grid spr-gap-4">
    <div class="spr-border-color-weak spr-max-h-[300px] spr-overflow-hidden spr-rounded-md spr-border spr-border-solid">
      <spr-ladderized-list v-model="singleSelectOutput" :menu-list="mockDropdownData" />
    </div>
  </div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';

const singleSelectOutput = ref([]);
const mockDropdownData = [
  {
    text: 'Lion',
    value: 'lion',
    subtext: 'King of the jungle',
    sublevel: [
      {
        text: 'Cub',
        value: 'cub',
        subtext: 'Young lion',
        sublevel: [
          {
            text: 'Cub 1',
            value: 'cub1',
          },
          {
            text: 'Cub 2',
            value: 'cub2',
          },
        ],
      },
      {
        text: 'Pride Member',
        value: 'pride-member',
        subtext: 'Member of a lion pride',
      },
    ],
  },
  {
    text: 'Elephant',
    value: 'elephant',
    subtext: 'Largest land animal',
    sublevel: [
      {
        text: 'Calf',
        value: 'calf',
        subtext: 'Young elephant',
      },
    ],
  },
  {
    text: 'Giraffe',
    value: 'giraffe',
    subtext: 'Tallest living terrestrial animal',
    sublevel: [
      {
        text: 'Calf',
        value: 'giraffe-calf',
        subtext: 'Young giraffe',
      },
      {
        text: 'Adult',
        value: 'giraffe-adult',
        subtext: 'Mature giraffe',
      },
    ],
  },
  {
    text: 'Zebra',
    value: 'zebra',
    subtext: 'Known for distinctive black and white stripes',
    sublevel: [
      {
        text: 'Foal',
        value: 'zebra-foal',
        subtext: 'Young zebra',
      },
      {
        text: 'Mare',
        value: 'zebra-mare',
        subtext: 'Adult female zebra',
      },
    ],
  },
];
</script>

No Check

No results found
Output:
[]
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="singleSelectOutput" :menu-list="menuList" noCheck />
  </div>
</template>

Lozenge

The list component can also be displayed as a lozenge by passing the lozenge prop. The items in the list should contain lozengeProps to define the properties of the lozenge.

No results found
Output:
[]
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="lozengeListValue" :menu-list="lozengeMenuList" lozenge />
  </div>
</template>
<script setup lang="ts">
import { LOZENGE_TONE } from '@/components/lozenge/lozenge';
import { MenuListType } from '@/components/list/list';

const lozengeListValue = ref([]);
const lozengeMenuList = ref(
  LOZENGE_TONE.map((tone: string) => ({
    text: `${tone.charAt(0).toUpperCase() + tone.slice(1)}`,
    value: tone,
    lozengeProps: {
      label: `${tone.charAt(0).toUpperCase() + tone.slice(1)}`,
      tone: tone,
      fill: true,
      url: "https://tinyurl.com/2vzn782p",
      icon: "ph:address-book-tabs",
      postfixIcon: "ph:caret-right-fill",
    }
  })) as MenuListType[];
);
</script>

API Reference

Props

NameDescriptionTypeDefault
modelValueTwo-way binding for the selected items. Contains the complete item objects of all selected items, not just their values. Used with v-model for reactivity.MenuListType[][]
menuListThe list of items to display in the component. Each item should contain at minimum text and value properties, with optional properties like subtext, group, icon, etc.MenuListType[][] (required)
groupItemsByControls how items are grouped in the list:
  • default: Groups items by their group property
  • A-Z: Sorts items alphabetically by text in ascending order
  • Z-A: Sorts items alphabetically by text in descending order
'default' | 'A-Z' | 'Z-A'undefined
multiSelectEnables multi-selection mode, allowing users to select multiple items simultaneously. When enabled, checkboxes appear next to each item.booleanfalse
preSelectedItemsPre-selects items in the list based on their values. Pass an array of strings or numbers that correspond to the value properties of items to be pre-selected.(string | number | Record<string, unknown>)[][]
searchableMenuEnables a search input field at the top of the list for filtering items. When enabled, users can type to filter the list items by their text values.booleanfalse
searchableMenuPlaceholderPlaceholder text for the search input field when searchableMenu is enabled.string'Search...'
searchValueExternal search value to filter the list. Can be used to control the search from outside the component.string''
menuLevelIndicates the nesting level of the list. Used internally for ladderized lists to track hierarchy.number0
ladderizedEnables ladderized (hierarchical) list mode. When enabled, items with sublevel properties will display nested lists.booleanfalse
disabledLocalSearchDisables the local search/filtering functionality even when searchableMenu is true. Useful when implementing custom search logic externally.booleanfalse
loadingDisplays a loading indicator instead of list items. Use this when fetching data asynchronously.booleanfalse
noCheckHides the checkmark icon that appears next to selected items in single-select mode. Has no effect in multi-select mode.booleanfalse
dropdownInternal prop used to indicate the list is being used within a dropdown component. Affects certain visual behaviors.booleanfalse
lozengeEnables lozenge mode for the list items. When enabled, items are displayed as lozenges.booleanfalse

Events

NameDescriptionParameters
update:modelValueEmitted when the selection changes. Provides the complete selected items with all their properties, not just values. Used for v-model binding.(value: MenuListType[]): Array of the complete selected item objects
update:searchValueEmitted when the search input value changes. Used for controlling the search externally.(value: string): The new search text value

The List component accepts items conforming to the MenuListType interface:

typescript
type MenuListType = {
  text: string;                                    // Display text for the item (required)
  value: string | number;                          // Unique identifier for the item (required)
  subtext?: string;                                // Optional secondary text displayed below main text
  group?: string;                                  // Optional group identifier for grouping items
  sublevel?: MenuListType[];                       // Optional nested items for ladderized lists
  disabled?: boolean;                              // Optional flag to disable the item
  _originalObject?: Record<string, unknown>;       // Optional reference to original object
  icon?: string;                                   // Optional Iconify icon name
  iconColor?: string;                              // Optional CSS class for icon color
  textColor?: string;                              // Optional CSS class for text color
  lozengeProps?: LozengePropTypes;                 // Props for the lozenge component when list is displayed as lozenge
  onClickFn?: () => void;                          // Optional click handler function
};

Product Uses

Sprout HR
Sprout Payroll