Skip to content

List

The List component is a flexible way to display a list of items in your Vue application. This documentation covers how to use various features of the List component, such as links, slots, icons, headers, and collapse functionality.

Usage

Basic Usage

To use the VList component, just use the component in your template like so:

INFO

The VList component is registered globally when you install with @morpheme/ui. So you don't need to import it manually.

Hover Effect

The Hover variant of the List component allows you to add custom shapes to the list items. You can use the hover prop on a ListItem to apply the default hover style, or use the hover-class prop to specify a custom hover class.

Shaped

The Shaped variant of the List component allows you to add custom shapes to the list items. You can use the shaped prop on a ListItem to apply the default shaped style, or use the shaped-class prop to specify a custom shaped class.

Rounded

The Rounded variant of the List component adds rounded corners to the list items. You can use the rounded prop on a VListItem to apply the rounded style.

Tile

The Tile variant of the List component displays the list items as tiles. You can use the tile prop on a ListItem to apply the tile style.

Hide Prepend & Hide Append

The List component allows you to hide the prepend and append elements of a VListItem. You can use the hide-prepend and hide-append props on a VListItem to hide these elements. Alternatively, you can pass the hide-prepend and hide-append props to the parent VList component and bind them to the child VListItem components via slot props.

Hide Text

The VList component allows you to hide the text of a VListItem. You can use the hide-text prop on a VListItem to hide the text. This can be useful for displaying icons only, for example.

Two Line

To display a list with two lines per list item, you can nest elements inside the VListItem component:

Three Line

To display a list with three lines per list item, you can nest additional elements inside the VListItem component:

You can use the to prop on a VListItem to make it a router link, or the href prop to make it a regular link:

Slots

The VListItem component has prepend and append slots that allow you to insert custom content at the beginning and end of each list item:

Icons

You can use the prepend-icon and append-icon props to add icons to your list items. The value for these props should be the name of the icon in the Icones icon set.

You can use the VListItemHeader component to add header to the list.

Collapse

You can use the VListCollapse component to add collapsible list.

Image

You can place image to the list using prepend slot in the VListItem component.

This example shows how to use VList inside VNavDrawer component to create sidebar navigation component.

IOS Settings

This example shows how to create IOS Settings menu using VList component.

This example shows how to use VList component in the dropdown component.

Active State

We can set active state to the list by passing active prop to the VListItem component. We can also choose different styles of active item via active-variant and active-border-position props. The active-variant prop accept "filled" | "bordered" | "filled-bordered" values and the active-border-position prop accept "top" | "right" | "bottom" | "left" values.

Event

This example demonstrates how to use events in the VList component. It shows examples of how to listen for clicks on the prepend and append icons, the prepend and append icon wrapper areas, and the append text. When one of these elements is clicked, a message is displayed using the showMessage function.

Props

VList

PropertyTypeDescription
hidePrependbooleanWhether to hide the prepend element.
hideAppendbooleanWhether to hide the append element.
shapedbooleanWhether to apply shaped styling to the list item.
roundedbooleanWhether to apply rounded styling to the list item.
tilebooleanWhether to apply tile styling to the list item.
hoverbooleanWhether to apply hover styling to the list item.
flushbooleanWhether to remove the border between list items.
densebooleanWhether to reduce the padding on the list item.
smallbooleanWhether to apply small styling to the list item.
hideTextbooleanWhether to apply hide text on the list item.
activeVariant"filled" | "bordered" | "filled-bordered"The active state variant.
activeBorderPosition"top" | "right" | "bottom" | "left"The border position.

VListItem

NameTypeDefault
tostring | RouteLocationundefined
hrefstringundefined
asanyundefined
defaultClassstring``
prependClassstring``
prependIconstring''
prependIconClassstring''
appendClassstring``
appendIconstring''
appendIconClassstring''
hidePrependbooleanfalse
hideAppendbooleanfalse
hoverbooleanfalse
hoverClassstringv-list-item--hover
shapedbooleanfalse
shapedClassstringv-list-item--shaped
roundedbooleanfalse
hideTextbooleanfalse
appendTextstring''
appendTextClassstringfalse
tilebooleanfalse

Events

VList

None.

VListItem

EventDescription
(e: 'click:prepend'): voidEmitted when the element wrapped around the prepend slot is clicked.
(e: 'click:prependIcon'): voidEmitted when the prependIcon element is clicked.
(e: 'click:append'): voidEmitted when the element wrapped around the append slot is clicked.
(e: 'click:appendIcon'): voidEmitted when the appendIcon element is clicked.
(e: 'click:appendText'): voidEmitted when the element wrapped around the appendText slot is clicked.

Here is example of listening event in VListItem component:

vue
<script setup lang="ts">
function handleClickPrepend() {
  // handle click event on prepend slot
}
</script>

<template>
  <VList>
    <VListItem @click:prepend="handleClickPrepend">
      <template #prepend>
        <div class="text-cyan-500">prepend</div>
      </template>
    </VListItem>
  </VList>
</template>
<script setup lang="ts">
function handleClickPrepend() {
  // handle click event on prepend slot
}
</script>

<template>
  <VList>
    <VListItem @click:prepend="handleClickPrepend">
      <template #prepend>
        <div class="text-cyan-500">prepend</div>
      </template>
    </VListItem>
  </VList>
</template>

Slots

EventDescription
prependSlot for custom content to be displayed before the main content.
prepend.iconSlot for a custom icon to be displayed before the main content.
defaultThe default slot for the main content.
appendSlot for custom content to be displayed after the main content.
append.iconSlot for a custom icon to be displayed after the main content.
append.textSlot for custom text to be displayed after the main content.

Here is example of using slot in VListItem component:

vue
<template>
  <VList>
    <VListItem>
      <template #prepend>
        <div class="text-cyan-500">prepend</div>
      </template>
    </VListItem>
  </VList>
</template>
<template>
  <VList>
    <VListItem>
      <template #prepend>
        <div class="text-cyan-500">prepend</div>
      </template>
    </VListItem>
  </VList>
</template>

CSS Variables

scss
:root {
  --v-list-padding-y: var(--size-spacing-1);
  --v-list-padding-x: var(--size-spacing-1);
  --v-list-gap: 0;
  --v-list-bg-color: var(--color-transparent);

  /* item */
  --v-list-item-bg-color: var(--color-transparent);
  --v-list-item-color: var(--color-gray-700);
  --v-list-item-padding-y: var(--size-spacing-2);
  --v-list-item-padding-x: var(--size-spacing-3);
  --v-list-item-border-radius: var(--border-radius-md);
  --v-list-item-border-width: 0;
  --v-list-item-border-color: var(--color-transparent);
  --v-list-item-border-style: solid;
  --v-list-item-gap: var(--size-spacing-3);
  --v-list-item-font-size: var(--size-font-sm);
  --v-list-item-font-weight: var(--font-weight-regular);
  --v-list-item-line-height: 20px;
  --v-list-item-text-align: left;
  --v-list-item-icon-width: var(--size-spacing-4);
  --v-list-item-icon-height: var(--size-spacing-4);

  /* item hover */
  --v-list-item-hover-bg-color: var(--color-gray-100);
  --v-list-item-hover-color: var(--color-gray-700);

  /* item active */
  --v-list-item-active-bg-color: var(--color-primary-600);
  --v-list-item-active-border-color: var(--color-primary-600);
  --v-list-item-active-color: var(--color-white);

  /* filled bordered */
  --v-list-item-active-filled-bordered-bg-color: var(--color-primary-50);
  --v-list-item-active-filled-bordered-border-color: var(--color-primary-500);
  --v-list-item-active-filled-bordered-color: var(--color-primary-600);

  /* append & prepend */
  --v-list-item-append-prepend-min-width: var(--size-spacing-5);

  /* item header */
  --v-list-item-header-bg-color: var(--v-list-item-bg-color);
  --v-list-item-header-color: var(--color-gray-500);
  --v-list-item-header-padding-y: var(--size-spacing-1);
  --v-list-item-header-padding-x: var(--v-list-item-padding-x);
  --v-list-item-header-border-radius: var(--v-list-item-border-radius);
  --v-list-item-header-border-width: var(--v-list-item-border-width);
  --v-list-item-header-border-color: var(--v-list-item-border-color);
  --v-list-item-header-border-style: var(--v-list-item-border-style);
  --v-list-item-header-gap: var(--v-list-item-gap);
  --v-list-item-header-font-size: var(--size-font-xs);
  --v-list-item-header-font-weight: var(--font-weight-medium);
  --v-list-item-header-line-height: var(--v-list-item-line-height);
  --v-list-item-header-text-transform: uppercase;
  --v-list-item-header-text-align: var(--v-list-item-text-align);

  /* divider */
  --v-list-item-divider-width: 1px;
  --v-list-item-divider-color: var(--color-gray-200);
  --v-list-item-divider-style: solid;

  // icon
  --v-list-item-icon-color: currentColor;

  // append text
  --v-list-item-append-text-color: var(--v-list-item-color);
  --v-list-item-append-font-size: var(--v-list-item-font-size);
  --v-list-item-append-font-weight: var(--v-list-item-font-weight);
}
:root {
  --v-list-padding-y: var(--size-spacing-1);
  --v-list-padding-x: var(--size-spacing-1);
  --v-list-gap: 0;
  --v-list-bg-color: var(--color-transparent);

  /* item */
  --v-list-item-bg-color: var(--color-transparent);
  --v-list-item-color: var(--color-gray-700);
  --v-list-item-padding-y: var(--size-spacing-2);
  --v-list-item-padding-x: var(--size-spacing-3);
  --v-list-item-border-radius: var(--border-radius-md);
  --v-list-item-border-width: 0;
  --v-list-item-border-color: var(--color-transparent);
  --v-list-item-border-style: solid;
  --v-list-item-gap: var(--size-spacing-3);
  --v-list-item-font-size: var(--size-font-sm);
  --v-list-item-font-weight: var(--font-weight-regular);
  --v-list-item-line-height: 20px;
  --v-list-item-text-align: left;
  --v-list-item-icon-width: var(--size-spacing-4);
  --v-list-item-icon-height: var(--size-spacing-4);

  /* item hover */
  --v-list-item-hover-bg-color: var(--color-gray-100);
  --v-list-item-hover-color: var(--color-gray-700);

  /* item active */
  --v-list-item-active-bg-color: var(--color-primary-600);
  --v-list-item-active-border-color: var(--color-primary-600);
  --v-list-item-active-color: var(--color-white);

  /* filled bordered */
  --v-list-item-active-filled-bordered-bg-color: var(--color-primary-50);
  --v-list-item-active-filled-bordered-border-color: var(--color-primary-500);
  --v-list-item-active-filled-bordered-color: var(--color-primary-600);

  /* append & prepend */
  --v-list-item-append-prepend-min-width: var(--size-spacing-5);

  /* item header */
  --v-list-item-header-bg-color: var(--v-list-item-bg-color);
  --v-list-item-header-color: var(--color-gray-500);
  --v-list-item-header-padding-y: var(--size-spacing-1);
  --v-list-item-header-padding-x: var(--v-list-item-padding-x);
  --v-list-item-header-border-radius: var(--v-list-item-border-radius);
  --v-list-item-header-border-width: var(--v-list-item-border-width);
  --v-list-item-header-border-color: var(--v-list-item-border-color);
  --v-list-item-header-border-style: var(--v-list-item-border-style);
  --v-list-item-header-gap: var(--v-list-item-gap);
  --v-list-item-header-font-size: var(--size-font-xs);
  --v-list-item-header-font-weight: var(--font-weight-medium);
  --v-list-item-header-line-height: var(--v-list-item-line-height);
  --v-list-item-header-text-transform: uppercase;
  --v-list-item-header-text-align: var(--v-list-item-text-align);

  /* divider */
  --v-list-item-divider-width: 1px;
  --v-list-item-divider-color: var(--color-gray-200);
  --v-list-item-divider-style: solid;

  // icon
  --v-list-item-icon-color: currentColor;

  // append text
  --v-list-item-append-text-color: var(--v-list-item-color);
  --v-list-item-append-font-size: var(--v-list-item-font-size);
  --v-list-item-append-font-weight: var(--v-list-item-font-weight);
}

View full styles here.

Standalone Installation

You can also install the VList component individually via @morpheme/list package:

bash
npm i @morpheme/list
npm i @morpheme/list

Then, use it in the template like so:

vue
<script setup lang="ts">
import { VList, VListItem } from "@morpheme/list";
</script>

<template>
  <VList>
    <VListItem prepend-icon="ic:round-home"> Text </VListItem>
  </VList>
</template>
<script setup lang="ts">
import { VList, VListItem } from "@morpheme/list";
</script>

<template>
  <VList>
    <VListItem prepend-icon="ic:round-home"> Text </VListItem>
  </VList>
</template>

Storybook

View Storybook documentation here.