List
Lines up rows on a phone, like recent activity or settings.
Examples
- Round-upsSpare change to Vacation fund
- Payment alerts
Styles
- Corner CoffeeToday−$4.80
- PaycheckYesterday+$2,140.00
plaindefault
- Corner CoffeeToday−$4.80
- PaycheckYesterday+$2,140.00
grouped
Trailing
- Corner CoffeeToday−$4.80
amountdefault
- StatementsMonthly, as PDF
chevron
- Round-upsSpare change to savings
switch
- SRSam RiveraOwes you $12.50Pending
badge
Tone
neutraldefault
accent
success
danger
States
rest
hover
focus-visible
pressed
- Corner CoffeeCard frozen−$4.80
disabled
Usage
When to use it
- Use
- Recent activity, accounts or friends, read one row at a time.
- Use
- A settings screen, where each row holds one switch or opens one page.
- Use
- A short choice on a phone, such as picking the account to pay from.
- Not for
- Many columns compared across rows on a wide screen. Use Table.
- Not for
- One choice from a few options inside a form. Use Radio.
- Not for
- A menu of commands behind a button. Use Dropdown menu.
Rules
9 rules
- Must
- Give a row one action: href, onClick or one trailing control, never two. Because a Switch inside the row button nests two controls, and one tap fires both.
- Must
- Show the chevron only on a row that opens another screen; href turns it on. Because the person taps a chevron row expecting a screen, and a Switch row opens nothing.
- Must
- Write a row amount as formatAmount text, signed for money in; use the Amount pill only when the row needs a tone, such as more than the balance. Because a column of plain figures stays quiet and lines up, and a pill on every row is noise.
- Should
- Keep the title to the name and put the date or category in description; both truncate.
- Should
- Use the same leading mark in every row of a list: all ListIcon or all Avatar.
- Should
- Use plain for a feed of rows; grouped only for a short settings group on the white page, never inside a Card or a Sheet.
- Must
- Give a trailing Switch an aria-label that repeats the row title. Because a bare Switch is read as "switch, off" with no setting named.
- Should
- Pull a plain list out by -mx-4 inside a padded Card or SheetBody, so row text lines up with the heading.
- Never
- Fill a row with lime to mark it; tone="accent" on its ListIcon is the most a row gets. Because the lime fill marks the one primary action, so a lime row reads as a button.
Accessibility
5 checks
- The list is a ul with role list, so the count is announced even with list styles removed.
- A row with href is one link and with onClick one button; its name is the title and the line under it.
- A trailing Switch is the row control and needs its own aria-label.
- The focus ring sits inside the row so the grouped card does not clip it.
- Rows are at least 56px tall.
Edge cases
5 edge cases
- Long title
- Title and description truncate; the trailing value never shrinks.
- Right to left
- The mark sits at the start and the chevron flips.
- No leading mark
- The hairline starts at the text edge, 16px in.
- Disabled row
- It dims to half and stops responding; say why in description.
- One row
- No hairline is drawn; the last row never has one.
API
8 props
List.variant'plain' | 'grouped'default'plain'ListItem.titleReactNodeListItem.descriptionReactNodeListItem.leading, trailingReactNodeListItem.href, onClickstring, functionListItem.chevronbooleandefaulttrue with hrefListItem.menuReactNodeListIcon{icon, tone?: 'neutral' | 'accent' | 'success' | 'danger'}default'neutral'
Tokens
14 tokens
--surface- #f6f5f2
--surface-2- #efeeea
--surface-3- #e6e4df
--radius-panel- 16px
--line- #e6e4df
--fg- #0f0f0d
--fg-3- #6b6a63
--text-base- 16px
--text-sm- 14px
--ring- var(--accent-line)
--accent-wash- #f5f9c4
--success-tint- #e5f5ea
--success-text- #17703a
--dur-instant- 80ms