# ListCell
**π Live documentation:** https://cds.coinbase.com/components/data-display/ListCell/
A versatile cell component used for displaying content in a list format, supporting various layouts and interactions.
## Import
```tsx
import { ListCell } from '@coinbase/cds-web/cells/ListCell'
```
## Examples
### Overview
A ListCell row is divided into the following 5 columns:
- Media
- Title & description
- Intermediary
- End (detail & subdetail or action)
- Accessory
#### Basic Usage
```tsx live
```
:::tip
Prefer `spacingVariant="condensed"` for the new ListCell design. Both `normal` and `compact` are deprecated and may be removed in a future major release.
:::
#### Spacing Variant
```tsx live
{/* Preferred (new design) */}
}
onClick={console.log}
title="Condensed"
variant="positive"
/>
{/* Deprecated options kept for backward compatibility */}
}
onClick={console.log}
title="Compact (deprecated)"
variant="positive"
/>
}
onClick={console.log}
title="Normal (deprecated)"
variant="positive"
/>
```
### Media
::::note
We have deprecated `CellMedia`; pass media directly as shown below.
::::
#### Leading Icon
```tsx live
}
/>
```
#### Leading Avatar
```tsx live
}
/>
```
### Title & Description
#### Title Line Limits
- In condensed spacing (`spacingVariant="condensed"`), the title shows up to two lines by default, regardless of whether a description is present.
- In normal and compact spacing, the title shows up to two lines when there is no description; if a description is present, the title is limited to one line.
- Use `disableMultilineTitle` to force the title to one line in all cases.
- When provided, the subtitle renders between the title and description and always truncates to a single line. Use `subtitleNode` if you need custom layout or multi-line behavior.
::::warning
The `title` and `description` props are rendered inside a CDS `Text` with default fonts and truncation. To render arbitrary React nodes without being wrapped by a ``, use `titleNode` and `descriptionNode`.
When using the Node props, you are responsible for styling, layout, and truncation behavior.
::::
#### Custom Title/Description via Node Props
```tsx live
}
titleNode={
Verified account
}
descriptionNode={
Composed description with any React nodes
}
/>
```
#### Subtitle
Use `subtitle` to add one line of supplementary context between the title and description. The subtitle always truncates to a single line; provide a `subtitleNode` when you need your own truncation or layout logic.
```tsx live
}
title="Bitcoin"
subtitle="Deposit available in 1-2 days"
description="Ending in β’β’42"
detail="$12,345.00"
/>
```
#### Multiline Description
```tsx live
```
### Intermediary
```tsx live
function Intermediary() {
const dimensions = { width: 62, height: 18 };
const sparklineData = prices
.map((price) => parseFloat(price))
.filter((price, index) => index % 10 === 0);
const referenceY = sparklineData[Math.floor(sparklineData.length / 3)];
const CompactChart = memo(
({ data, color = 'var(--color-fgPositive)', showArea = false, referenceY }) => (
),
);
return (
}
spacingVariant="condensed"
title="Bitcoin"
description="BTC"
intermediary={}
detail="$334,239.03"
subdetail="+4.06%"
priority="start"
variant="positive"
/>
);
}
```
### End
#### Detail and Subdetail
```tsx live
```
::::warning
Like `title` and `description`, `detail` and `subdetail` props are also rendered inside a CDS `Text` with default fonts. To render arbitrary React nodes without being wrapped by a ``, use `detailNode` and `subdetailNode`.
::::
#### Custom Detail/Subdetail via Node Props
```tsx live
}
title="Custom end content"
description="Detail and subdetail rendered with custom nodes"
detailNode={
$12,345.00
}
subdetailNode={
+5.43%
}
/>
```
#### End Action
When you pass the `end` prop, it overrides the `detail`/`subdetail`/`detailNode`/`subdetailNode`.
```tsx live
{
alert('Action clicked');
}}
>
Action
}
/>
```
### Accessory
#### Interactive Cell with Accessory
```tsx live
alert('Cell clicked!')}
/>
```
#### Preserve Layout During Selection
Use the `unselected` accessory to reserve space for the selection checkmark when toggling the `selected` state.
```tsx live
function PreserveLayoutExample() {
const [isSelected, setIsSelected] = useState(false);
return (
setIsSelected((prev) => !prev)}
/>
);
}
```
#### Custom Accessory via Node Prop
```tsx live
}
end={
}
accessoryNode={
}
/>
```
### Accessibility Label
The accessibility props are only applied when the `` has a value for the `onClick` prop. Otherwise, content passed into the `` must use accessibility props and attributes as needed.
```tsx live
}
media={}
onClick={() => window.alert('ListCell clicked!')}
title="BTC"
spacingVariant="condensed"
/>
}
media={}
title="BTC"
spacingVariant="condensed"
/>
```
### Helper text
```tsx live
This is a default helper message.
}
media={}
end={}
/>
This is a warning message.
}
media={}
end={}
/>
This is an error message.
}
media={}
end={}
/>
```
### ContentCell
```tsx live
Long description with multiple lines. This section can be arbitrarily long and occupy many
many lines.
}
end={
Meta
}
media={}
onClick={() => console.log('clicked')}
priority="end"
spacingVariant="condensed"
styles={{
media: {
marginTop: 'var(--space-0_5)',
alignSelf: 'flex-start',
},
end: {
marginTop: 'var(--space-0_5)',
alignSelf: 'flex-start',
},
}}
subdetail="Subdetail"
subtitle="Subtitle"
title="Content-style layout"
/>
```
### Loading States
The ListCellFallback component provides loading state representations of ListCell. It uses placeholder rectangles to indicate where content will appear, creating a smooth loading experience. The web version uses percentage-based widths and custom layouts to match the ListCell's four-column structure.
```tsx live
{/* Basic loading state */}
{/* Loading state with media */}
{/* Loading state with details */}
{/* Full loading state with custom widths */}
```
### Priority
The priority prop controls which parts of the cell are protected from shrinking and truncation when horizontal space is limited. It accepts start, middle, and end as a string or an array of strings.
```tsx live
function PriorityContent() {
const dimensions = { width: 62, height: 18 };
const sparklineData = prices
.map((price) => parseFloat(price))
.filter((price, index) => index % 10 === 0);
const referenceY = sparklineData[Math.floor(sparklineData.length / 3)];
const CompactChart = memo(
({ data, color = 'var(--color-fgPositive)', showArea = false, referenceY }) => (
),
);
return (
}
detail="$334,239.03"
subdetail="+4.06%"
priority="start"
variant="positive"
/>
}
detail="$334,239.03"
subdetail="+4.06%"
priority="middle"
variant="positive"
/>
}
detail="$334,239.03"
subdetail="+4.06%"
priority="end"
variant="positive"
/>
}
detail="$334,239.03"
subdetail="+4.06%"
priority={['start', 'middle', 'end']}
variant="warning"
/>
);
}
```
### Anatomy
Without helper text (top-only layout):
```text
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β root (Box) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββ pressable ββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββ contentContainer & mainContent (HStack) βββ
βββ βββββββ ββββββββββββββββββββββββββββββββ ββββββββββββββ ββββββββββββββ βββββββββββ βββ
βββ βmediaβ β titleStackContainer (Box) β βintermediaryβ β end β βaccessoryβ βββ
βββ β β β ββββββββββββββββββββββββββββ β β β β (detail β β β βββ
βββ β β β β titleStack (VStack) β β β β β or β β β βββ
βββ β β β β ββββββββββββ β β β β β action) β β β βββ
βββ β β β β β title β β β β β β β β β βββ
βββ β β β β ββββββββββββ β β β β β β β β βββ
βββ β β β β ββββββββββββ β β β β β β β β βββ
βββ β β β β β subtitle β β β β β β β β β βββ
βββ β β β β ββββββββββββ β β β β β β β β βββ
βββ β β β β ββββββββββββββ β β β β β β β β βββ
βββ β β β β β descriptionβ β β β β β β β β βββ
βββ β β β β ββββββββββββββ β β β β β β β β βββ
βββ β β β ββββββββββββββββββββββββββββ β β β β β β β βββ
βββ βββββββ ββββββββββββββββββββββββββββββββ ββββββββββββββ ββββββββββββββ βββββββββββ βββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
```
With helper text (top + bottom layout):
```text
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β root (Box) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββ pressable ββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββ contentContainer (VStack) βββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββ mainContent (HStack) ββββ
ββββ βββββββ ββββββββββββββββββββββββββββββββ ββββββββββββββ ββββββββββββββ βββββββββββ ββββ
ββββ βmediaβ β titleStackContainer (Box) β βintermediaryβ β end β βaccessoryβ ββββ
ββββ β β β ββββββββββββββββββββββββββββ β β β β (detail β β β ββββ
ββββ β β β β titleStack (VStack) β β β β β or β β β ββββ
ββββ β β β β ββββββββββββ β β β β β action) β β β ββββ
ββββ β β β β β title β β β β β β β β β ββββ
ββββ β β β β ββββββββββββ β β β β β β β β ββββ
ββββ β β β β ββββββββββββ β β β β β β β β ββββ
ββββ β β β β β subtitle β β β β β β β β β ββββ
ββββ β β β β ββββββββββββ β β β β β β β β ββββ
ββββ β β β β ββββββββββββββ β β β β β β β β ββββ
ββββ β β β β β descriptionβ β β β β β β β β ββββ
ββββ β β β β ββββββββββββββ β β β β β β β β ββββ
ββββ β β β ββββββββββββββββββββββββββββ β β β β β β β ββββ
ββββ βββββββ ββββββββββββββββββββββββββββββββ ββββββββββββββ ββββββββββββββ βββββββββββ ββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββ helperText ββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
```
Mapping to `styles` / `classNames` keys:
- root: outer `Box` wrapping the entire cell
- pressable: interactive overlay when `href` / `onClick` keyboard handlers are present
- contentContainer: container around top and optional bottom content
- mainContent: inner horizontal layout that holds the main pieces
- titleStackContainer: wrapper around the title stack (controls flex behavior)
- titleStack: stacked text column (title/subtitle/description)
- title/subtitle/description: individual text nodes within `titleStack`
- media: leading media container
- intermediary: middle container between main and end
- end: container for `detail` / `subdetail` or `end` prop you pass in
- accessory: trailing accessory container
- helperText: container below main content to display helper text
## Props
| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `about` | `string \| undefined` | No | `-` | - |
| `accessKey` | `string \| undefined` | No | `-` | - |
| `accessory` | `CellAccessoryType` | No | `-` | Accessory to display at the end of the cell. |
| `accessoryNode` | `ReactNode` | No | `-` | Custom accessory node rendered at the end of the cell. Takes precedence over accessory. |
| `action` | `ReactNode` | No | `-` | - |
| `alignContent` | `ResponsiveProp