Meet Frontfriend.Your brand. Your rules. Your agents, connected.Explore what’s new

List

Displays a list with header and items.

Interactive preview

Rendered from the shared Frontfriend stories with React Base, the same preview Studio shows. Styling comes from your Design System; the code below is native to Reka UI.

Installation

Complete project setup first. Your configuration must select vue/reka and include your Design System ID.

pnpm exec frontfriend download list -f vue --primitive reka

Review dependencies reported by the downloader and keep your source changes in version control.

Usage

<script setup lang="ts">
import { List } from "@/components/ui/list";
import { ListTitle } from "@/components/ui/list";
import { ListContent } from "@/components/ui/list";
import { ListItem } from "@/components/ui/list";
import { ListItemTitle } from "@/components/ui/list";
import { ListItemAttributes } from "@/components/ui/list";

const args = {
  "align": "justify",
  "icon": "CircleDotDashed",
  "interactive": true,
  "title": "Title",
  "first": "",
  "second": "",
  "description": "Description",
  "naked": false,
  "inverted": true,
  "variant": "main",
  "left": "",
  "titleColor": undefined,
  "descriptionColor": undefined,
  "firstColor": undefined,
  "secondColor": undefined,
} satisfies Partial<
  InstanceType<typeof ListItem> extends { $props: infer Props } ? Props : {}
> &
  Record<string, unknown> & {
    align?: "end" | "justify" | "start" | "stretch";
    variant?: "main" | "secondary";
  };
</script>

<template>
  <List class="w-[347px]" :naked="args.naked">
    <ListTitle :align="args.align" :variant="args.variant">
      Interactive list
    </ListTitle>
    <ListContent>
      <ListItem
        :icon="args.icon"
        :interactive="args.interactive"
        :inverted="args.inverted"
      >
        <template v-slot:left>
          {{ args.left }}
        </template>
        <ListItemTitle
          :title="args.title"
          :titleColor="args.titleColor"
          :description="args.description"
          :descriptionColor="args.descriptionColor"
        ></ListItemTitle>
        <ListItemAttributes
          :first="args.first"
          :second="args.second"
          :firstColor="args.firstColor"
          :secondColor="args.secondColor"
        ></ListItemAttributes>
      </ListItem>
      <ListItem
        :icon="args.icon"
        :interactive="args.interactive"
        :inverted="args.inverted"
      >
        <template v-slot:left>
          {{ args.left }}
        </template>
        <ListItemTitle
          :title="args.title"
          :titleColor="args.titleColor"
          :description="args.description"
          :descriptionColor="args.descriptionColor"
        ></ListItemTitle>
        <ListItemAttributes
          :first="args.first"
          :second="args.second"
          :firstColor="args.firstColor"
          :secondColor="args.secondColor"
        ></ListItemAttributes>
      </ListItem>
      <ListItem
        :icon="args.icon"
        :interactive="args.interactive"
        :inverted="args.inverted"
      >
        <template v-slot:left>
          {{ args.left }}
        </template>
        <ListItemTitle
          :title="args.title"
          :titleColor="args.titleColor"
          :description="args.description"
          :descriptionColor="args.descriptionColor"
        ></ListItemTitle>
        <ListItemAttributes
          :first="args.first"
          :second="args.second"
          :firstColor="args.firstColor"
          :secondColor="args.secondColor"
        ></ListItemAttributes>
      </ListItem>
      <ListItem
        :icon="args.icon"
        :interactive="args.interactive"
        :inverted="args.inverted"
      >
        <template v-slot:left>
          {{ args.left }}
        </template>
        <ListItemTitle
          :title="args.title"
          :titleColor="args.titleColor"
          :description="args.description"
          :descriptionColor="args.descriptionColor"
        ></ListItemTitle>
        <ListItemAttributes
          :first="args.first"
          :second="args.second"
          :firstColor="args.firstColor"
          :secondColor="args.secondColor"
        ></ListItemAttributes>
      </ListItem>
      <ListItem
        :icon="args.icon"
        :interactive="args.interactive"
        :inverted="args.inverted"
      >
        <template v-slot:left>
          {{ args.left }}
        </template>
        <ListItemTitle
          :title="args.title"
          :titleColor="args.titleColor"
          :description="args.description"
          :descriptionColor="args.descriptionColor"
        ></ListItemTitle>
        <ListItemAttributes
          :first="args.first"
          :second="args.second"
          :firstColor="args.firstColor"
          :secondColor="args.secondColor"
        ></ListItemAttributes>
      </ListItem>
    </ListContent>
  </List>
</template>

Examples

Default

<script setup lang="ts">
import { List } from "@/components/ui/list";
import { ListTitle } from "@/components/ui/list";
import { ListContent } from "@/components/ui/list";
import { ListItem } from "@/components/ui/list";
import { ListItemTitle } from "@/components/ui/list";
import { ListItemAttributes } from "@/components/ui/list";

const args = {
  "align": "justify",
  "icon": "CircleDashed",
  "interactive": true,
  "title": "Title",
  "first": "",
  "second": "",
  "description": "Description",
  "naked": false,
  "inverted": true,
  "variant": "main",
  "left": "",
  "titleColor": undefined,
  "descriptionColor": undefined,
  "firstColor": undefined,
  "secondColor": undefined,
} satisfies Partial<
  InstanceType<typeof ListItem> extends { $props: infer Props } ? Props : {}
> &
  Record<string, unknown> & {
    align?: "end" | "justify" | "start" | "stretch";
    variant?: "main" | "secondary";
  };
</script>

<template>
  <List class="w-[347px]" :naked="args.naked">
    <ListTitle :align="args.align" :variant="args.variant">
      Interactive list
    </ListTitle>
    <ListContent>
      <ListItem
        :icon="args.icon"
        :interactive="args.interactive"
        :inverted="args.inverted"
      >
        <template v-slot:left>
          {{ args.left }}
        </template>
        <ListItemTitle
          :title="args.title"
          :titleColor="args.titleColor"
          :description="args.description"
          :descriptionColor="args.descriptionColor"
        ></ListItemTitle>
        <ListItemAttributes
          :first="args.first"
          :second="args.second"
          :firstColor="args.firstColor"
          :secondColor="args.secondColor"
        ></ListItemAttributes>
      </ListItem>
      <ListItem
        :icon="args.icon"
        :interactive="args.interactive"
        :inverted="args.inverted"
      >
        <template v-slot:left>
          {{ args.left }}
        </template>
        <ListItemTitle
          :title="args.title"
          :titleColor="args.titleColor"
          :description="args.description"
          :descriptionColor="args.descriptionColor"
        ></ListItemTitle>
        <ListItemAttributes
          :first="args.first"
          :second="args.second"
          :firstColor="args.firstColor"
          :secondColor="args.secondColor"
        ></ListItemAttributes>
      </ListItem>
      <ListItem
        :icon="args.icon"
        :interactive="args.interactive"
        :inverted="args.inverted"
      >
        <template v-slot:left>
          {{ args.left }}
        </template>
        <ListItemTitle
          :title="args.title"
          :titleColor="args.titleColor"
          :description="args.description"
          :descriptionColor="args.descriptionColor"
        ></ListItemTitle>
        <ListItemAttributes
          :first="args.first"
          :second="args.second"
          :firstColor="args.firstColor"
          :secondColor="args.secondColor"
        ></ListItemAttributes>
      </ListItem>
      <ListItem
        :icon="args.icon"
        :interactive="args.interactive"
        :inverted="args.inverted"
      >
        <template v-slot:left>
          {{ args.left }}
        </template>
        <ListItemTitle
          :title="args.title"
          :titleColor="args.titleColor"
          :description="args.description"
          :descriptionColor="args.descriptionColor"
        ></ListItemTitle>
        <ListItemAttributes
          :first="args.first"
          :second="args.second"
          :firstColor="args.firstColor"
          :secondColor="args.secondColor"
        ></ListItemAttributes>
      </ListItem>
      <ListItem
        :icon="args.icon"
        :interactive="args.interactive"
        :inverted="args.inverted"
      >
        <template v-slot:left>
          {{ args.left }}
        </template>
        <ListItemTitle
          :title="args.title"
          :titleColor="args.titleColor"
          :description="args.description"
          :descriptionColor="args.descriptionColor"
        ></ListItemTitle>
        <ListItemAttributes
          :first="args.first"
          :second="args.second"
          :firstColor="args.firstColor"
          :secondColor="args.secondColor"
        ></ListItemAttributes>
      </ListItem>
    </ListContent>
  </List>
</template>

With Attributes And Forced Slots

<script setup lang="ts">
import { List } from "@/components/ui/list";
import { ListTitle } from "@/components/ui/list";
import { ListContent } from "@/components/ui/list";
import { ListItem } from "@/components/ui/list";
import { ListItemTitle } from "@/components/ui/list";
import { Badge } from "@/components/ui/badge";
import { ListItemAttributes } from "@/components/ui/list";

const args = {
  "align": "justify",
  "icon": "CircleDashed",
  "interactive": true,
  "title": "Title",
  "first": "1st",
  "description": "",
  "second": "",
  "naked": false,
  "inverted": false,
  "variant": "main",
  "titleColor": undefined,
  "descriptionColor": undefined,
  "firstColor": undefined,
  "secondColor": undefined,
} satisfies Partial<
  InstanceType<typeof ListItem> extends { $props: infer Props } ? Props : {}
> &
  Record<string, unknown> & {
    align?: "end" | "justify" | "start" | "stretch";
    variant?: "main" | "secondary";
  };
</script>

<template>
  <List class="w-[347px]" :naked="args.naked">
    <ListTitle :align="args.align" :variant="args.variant">
      With Attributes and forced slots
    </ListTitle>
    <ListContent>
      <ListItem
        :icon="args.icon"
        :interactive="args.interactive"
        :inverted="args.inverted"
      >
        <ListItemTitle
          :title="args.title"
          :titleColor="args.titleColor"
          :description="args.description"
          :descriptionColor="args.descriptionColor"
        >
          <Badge variant="secondary">pending</Badge>
        </ListItemTitle>
        <ListItemAttributes
          :first="args.first"
          :second="args.second"
          :firstColor="args.firstColor"
          :secondColor="args.secondColor"
        >
          <Badge variant="tertiary">12:04</Badge>
        </ListItemAttributes>
      </ListItem>
      <ListItem icon="CircleDashed" :interactive="true">
        <ListItemTitle title="Title" description="Description" />
        <ListItemAttributes first="1st" second="2nd" />
      </ListItem>
      <ListItem icon="CircleDashed" :interactive="true">
        <ListItemTitle title="Title" description="Description" />
        <ListItemAttributes first="1st" second="2nd" />
      </ListItem>
    </ListContent>
  </List>
</template>

Naked

<script setup lang="ts">
import { List } from "@/components/ui/list";
import { ListTitle } from "@/components/ui/list";
import { ListContent } from "@/components/ui/list";
import { ListItem } from "@/components/ui/list";
import { Avatar } from "@/components/ui/avatar";
import { AvatarImage } from "@/components/ui/avatar";
import { AvatarFallback } from "@/components/ui/avatar";
import { ListItemTitle } from "@/components/ui/list";
import { ListItemAttributes } from "@/components/ui/list";
import { Badge } from "@/components/ui/badge";

const args = {
  "align": "justify",
  "icon": "CircleDashed",
  "interactive": false,
  "title": "Mario Rossi",
  "firstColor": "text-positive-mid",
  "first": "read",
  "description": "",
  "second": "",
  "naked": true,
  "inverted": false,
  "variant": undefined,
  "titleColor": undefined,
  "descriptionColor": undefined,
  "secondColor": undefined,
} satisfies Partial<
  InstanceType<typeof ListItem> extends { $props: infer Props } ? Props : {}
> &
  Record<string, unknown> & {
    align?: "end" | "justify" | "start" | "stretch";
    firstColor?:
      | "text-neutral-mid"
      | "text-neutral-strong"
      | "text-neutral-subtle"
      | "text-neutral-low"
      | "text-positive-mid"
      | "text-positive-strong"
      | "text-positive-subtle"
      | "text-positive-low"
      | "text-negative-mid"
      | "text-negative-strong"
      | "text-negative-subtle"
      | "text-negative-low"
      | "text-warning-mid"
      | "text-warning-strong"
      | "text-warning-subtle"
      | "text-warning-low"
      | "text-info-mid"
      | "text-info-strong"
      | "text-info-subtle"
      | "text-info-low"
      | "text-highlight-mid"
      | "text-highlight-strong"
      | "text-highlight-subtle"
      | "text-highlight-low"
      | "text-interactive-mid"
      | "text-interactive-strong"
      | "text-interactive-subtle"
      | "text-interactive-low"
      | "text-brand-mid"
      | "text-brand-strong"
      | "text-brand-subtle"
      | "text-brand-low"
      | "text-inverse-mid"
      | "text-inverse-strong"
      | "text-inverse-subtle"
      | "text-inverse-low"
      | "text-onpositive-mid"
      | "text-onpositive-strong"
      | "text-onpositive-subtle"
      | "text-onpositive-low"
      | "text-onnegative-mid"
      | "text-onnegative-strong"
      | "text-onnegative-subtle"
      | "text-onnegative-low"
      | "text-onwarning-mid"
      | "text-onwarning-strong"
      | "text-onwarning-subtle"
      | "text-onwarning-low"
      | "text-oninfo-mid"
      | "text-oninfo-strong"
      | "text-oninfo-subtle"
      | "text-oninfo-low"
      | "text-onhighlight-mid"
      | "text-onhighlight-strong"
      | "text-onhighlight-subtle"
      | "text-onhighlight-low"
      | "text-oninteractive-mid"
      | "text-oninteractive-strong"
      | "text-oninteractive-subtle"
      | "text-oninteractive-low"
      | "text-onbrand-mid"
      | "text-onbrand-strong"
      | "text-onbrand-subtle"
      | "text-onbrand-low";
  };
</script>

<template>
  <List class="w-[347px]" :naked="args.naked">
    <ListTitle :align="args.align" :variant="args.variant">
      Naked with slot left and right
    </ListTitle>
    <ListContent>
      <ListItem :interactive="args.interactive" :inverted="args.inverted">
        <template v-slot:left>
          <Avatar>
            <AvatarImage
              src="https://uploads.donux.com/api/image/67920ddf5778c60b519f2002"
              alt="avatar"
            />
            <AvatarFallback name="Mario Rossi" />
          </Avatar>
        </template>
        <ListItemTitle
          :title="args.title"
          :titleColor="args.titleColor"
          :description="args.description"
          :descriptionColor="args.descriptionColor"
        />
        <ListItemAttributes
          :first="args.first"
          :second="args.second"
          :firstColor="args.firstColor"
          :secondColor="args.secondColor"
        />
      </ListItem>

      <ListItem>
        <template v-slot:left>
          <Avatar>
            <AvatarImage src="https://imgur.com/Y2V03fl.pn" alt="avatar" />
            <AvatarFallback name="Mario Rossi" />
          </Avatar>
        </template>
        <ListItemTitle title="Valeria Piras" />
        <ListItemAttributes first="1st" class="flex-row items-center">
          <Badge variant="secondary">pending</Badge>
        </ListItemAttributes>
      </ListItem>

      <ListItem>
        <template v-slot:left>
          <Avatar>
            <AvatarImage
              src="https://uploads.donux.com/api/image/67920ddf5778c60b519f2002"
              alt="avatar"
            />
            <AvatarFallback name="Mario Rossi" />
          </Avatar>
        </template>
        <ListItemTitle title="John Smith" />
        <ListItemAttributes first="1st" />
      </ListItem>

      <ListItem>
        <template v-slot:left>
          <Avatar>
            <AvatarImage
              src="https://uploads.donux.com/api/image/67920ddf5778c60b519f2002"
              alt="avatar"
            />
            <AvatarFallback name="Mario Rossi" />
          </Avatar>
        </template>
        <ListItemTitle title="Olen Del" />
        <ListItemAttributes first="1st" />
      </ListItem>

      <ListItem>
        <template v-slot:left>
          <Avatar>
            <AvatarImage
              src="https://uploads.donux.com/api/image/67920ddf5778c60b519f2002"
              alt="avatar"
            />
            <AvatarFallback name="Mario Rossi" />
          </Avatar>
        </template>
        <ListItemTitle title="Micheal Korguneiam very long name" />
        <ListItemAttributes first="not sent" />
      </ListItem>
    </ListContent>
  </List>
</template>

API reference

Frontfriend-owned props. Native HTML and inherited primitive props remain documented by Reka UI.

List

Prop Type Default Description
class HTMLAttributes["class"] —
naked boolean —

ListContent

Prop Type Default Description
class HTMLAttributes["class"] —
naked boolean —

ListItem

Prop Type Default Description
class HTMLAttributes["class"] —
icon IconName —
interactive boolean —
inverted boolean —

ListItemAttributes

Prop Type Default Description
class HTMLAttributes["class"] —
first string —
firstColor string —
second string —
secondColor string —

ListItemTitle

Prop Type Default Description
description string —
descriptionColor string —
title string —
titleColor string —

ListTitle

Prop Type Default Description
align "end" | "justify" | "start" | "stretch" —
class HTMLAttributes["class"] —
variant "main" | "secondary" | "tertiary" —

Configuration determines the actual classes and available styling hooks. See Theming & component configuration before introducing a repeated local override.