Build · New

List

Rows of people, messages or settings: a headline with an overline and supporting text, an avatar or icon at the start, a tag at the end. The swipeable row reveals actions when swiped.

Preview

Mirrored is the same English content laid out right to left: it separates a mirroring bug from a translation one.

Installation

SoonInstalling from the registry opens at launch. Until then the command below is what it will be.
npx shadcn@latest add @ritla/list

Dependencies it brings: @phosphor-icons/react

Usage

import { List, ListItem } from "@/components/ui/list";
<List aria-label="Team">
  <ListItem leading={<Avatar name="Omar Haddad" size="sm" decorative />} supportingText="Product designer">
    Omar Haddad
  </ListItem>
</List>

Examples

Icon and overline

leadingIcon puts the icon in a 40px circle. These rows are buttons (onClick), so they get the hover fill.

Swipeable row

Swipe toward the end to archive, toward the start to snooze or delete. Start and end follow the reading direction. The ⋮ button lists the same actions for keyboards, screen readers and mice.

API reference

List

PropTypeDefaultDescription
aria-labelstringThe list's name when the page has several.
childrenReactNodeListItem or SwipeableListItem rows.

ListItem

PropTypeDefaultDescription
childrenReactNodeFigma's Headline.
overlineReactNodeFigma's Overline: a short line above the headline.
supportingTextReactNodeFigma's Supporting text, below the headline.
leadingReactNodeThe start element: an avatar, a flag or an image.
leadingIconIconComponentAn icon in a 40px circle (Type = Icon).
trailingReactNodeFigma's Show Tags: a tag or any node at the end.
hrefstringMakes the row a link.
renderReactElementA router link (<Link>) with the row's look.
onClickMouseEventHandlerMakes the row a button.

SwipeableListItem

PropTypeDefaultDescription
leadingActionsSwipeAction[]Revealed at the start by swiping toward the end (Swipe = Leading).
trailingActionsSwipeAction[]Revealed at the end by swiping toward the start (Swipe = Trailing).
SwipeAction{ label, icon, color?: "brand" | "warning" | "danger", onAction }One 88px action.
menubooleantrueA ⋮ button with the same actions, so swiping isn't the only way.
menuLabelstring"More actions"The ⋮ button's name; in the page language by default.
…ListItem propsEvery ListItem prop.

Accessibility

Keyboard

Keys are written for left-to-right. In right-to-left the arrow keys swap: the one pointing toward the reading direction moves forward.

KeyAction
TabTo the interactive rows and each swipeable row's ⋮ button.
EnterFollows the link, presses the row or opens the actions menu.

ARIA

  • The list is a ul and each row an li, so screen readers announce the count.
  • An avatar next to the name is decorative, so the name isn't read twice.
  • Swiping is never the only way: the ⋮ button lists the same actions. Without it (menu={false}) the action buttons are focusable and the row opens when one gets focus.
  • An open row closes on a tap or focus outside it.

Arabic and RTL notes

Mirrors

  • The avatar or icon sits on the right; the tag and ⋮ button on the left.
  • Swiping follows the reading direction: in Arabic a swipe to the left reveals the start actions (on the right), a swipe to the right the end actions.

Does not mirror

  • The action icons (archive, clock, trash) and avatars.
Numerals
Numbers in the text are as you pass them; format them with formatNumber.
Arabic typography
Headline body-16 Medium, supporting text body-12, overline label-12. Rows are at least 70px, so taller Arabic text grows them instead of clipping.
Mixed-direction text
Wrap names in another language inside Arabic text in <bdi>.

All components ›