Skip to content

List item

Show one row with a title and description and an action or value beside it. Built on it: List field.

  • Anna Petrova

    anna@work

  • Ivan Sidorov

    ivan@work

  • Verified

    The account passed the check.

    Done
<script setup lang="ts">import { BadgeCheck } from '@lucide/vue'import { UiCard, UiList, UiListItem, UiAvatar, UiButton, UiBadge } from 'grani'</script> <template>  <UiCard :padded="false" class="w-full max-w-md">    <UiList>      <UiListItem title="Anna Petrova" description="anna@work">        <template #media><UiAvatar name="Anna Petrova" /></template>        <template #actions><UiButton variant="ghost">Edit</UiButton></template>      </UiListItem>      <UiListItem title="Ivan Sidorov" description="ivan@work">        <template #media><UiAvatar name="Ivan Sidorov" /></template>        <template #actions><UiButton variant="ghost">Edit</UiButton></template>      </UiListItem>      <UiListItem title="Verified" description="The account passed the check.">        <template #media><BadgeCheck aria-hidden="true" /></template>        <template #actions><UiBadge tone="success" label="Done" /></template>      </UiListItem>    </UiList>  </UiCard></template>

Also called list row, setting row, cell.

Usage

<UiListItem>…</UiListItem>

With GraniResolver in the Vite config, a template needs no import: set it up once.

API

Name · typeDefaultDescription
State
loadingbooleanA command or link row is running: a spinner in place of the glyph, clicks refused, focus kept.
errorstringWith as="label": an error in place of the description, read with the control and marking it invalid.
Behavior
titlestringThe primary line of text.
descriptionstringSupporting text below the title.
highlightstringLetters of the title to mark, in any case: the query of a search over the rows. The first match is marked.
litbooleanA moment of brand color: the row just came, or a refused repeat points at it. Set it, clear it after a second.
aslabel | button | divThe root element: label for a field, button for a command; a plain row is a div.
tostringA route or URL. Makes the whole row a link; actions then hold no controls. A disabled one is a disabled button, not a link; javascript: and data: are refused, as on UiLink.
target_blank | _selfWith to: _blank or _self decides the tab; unset, a new tab for an absolute address only.
relstringWith to: replaces the default noreferrer (nofollow, sponsored); noopener stays on a new tab.
stepbooleanWith as="button": the row goes one level in, a step of a drawer; a chevron at the end.
Look
variantsoft | outline | plain | mutedplain for a row among rows, outline for a standalone row, muted for a filled surface. On a notice in a UiList, soft fills the row with its tone's pale plate as well; plain keeps the surface. Alone the notice is its card either way.
sizesm | mdmd for pages, sm for drawers and dense lists. Unset: the host's (a sidebar says sm), else md. Rows keep their own scale, 44 at sm and 56 at md; the app's size (createGrani({ size })) does not move them.
tonebrand | success | warning | danger | infoMeaning. On a plain row a notice: alone a white card whose start edge is in the tone, in a UiList a row with the tone's edge, read as a status. On a command or link row the ink alone: danger for an irreversible action, brand for the one that makes something new (“Add …”).
Form and access
disabledbooleanA command or link row that cannot be taken now: no rights, nothing to do.
requiredbooleanWith as="label": an asterisk after the title and aria-required on the control.

Anything else lands on the root element: native attributes, aria-*, data-testid.

When to use another component

When you needTake
A field with its label above its controlField
An action on its ownButton
A list of names that grows from its last rowList field
A message about a requestA toast through Toaster
Why a list is emptyNo data