diff --git a/apps/docs/docs/components/data-display/ListCell/_mobileExamples.mdx b/apps/docs/docs/components/data-display/ListCell/_mobileExamples.mdx
index 273ddfadb..472f0090e 100644
--- a/apps/docs/docs/components/data-display/ListCell/_mobileExamples.mdx
+++ b/apps/docs/docs/components/data-display/ListCell/_mobileExamples.mdx
@@ -2,7 +2,7 @@
A ListCell row is divided into the following 5 columns:
-- Media
+- Start
- Title & description
- Intermediary
- End (detail & subdetail or action)
@@ -32,7 +32,7 @@ Prefer `spacingVariant="condensed"` for the new ListCell design. The `compact` m
description="New design (condensed)"
detail="$12,345.00"
spacingVariant="condensed"
- media={ }
+ start={ }
onPress={console.log}
title="Condensed"
variant="positive"
@@ -43,7 +43,7 @@ Prefer `spacingVariant="condensed"` for the new ListCell design. The `compact` m
accessory="arrow"
detail="$12,345.00"
spacingVariant="compact"
- media={ }
+ start={ }
onPress={console.log}
title="Compact (deprecated)"
variant="positive"
@@ -52,7 +52,7 @@ Prefer `spacingVariant="condensed"` for the new ListCell design. The `compact` m
accessory="arrow"
detail="$12,345.00"
spacingVariant="normal"
- media={ }
+ start={ }
onPress={console.log}
title="Normal"
variant="positive"
@@ -60,10 +60,10 @@ Prefer `spacingVariant="condensed"` for the new ListCell design. The `compact` m
```
-## Media
+## Start
::::note
-We have deprecated `CellMedia`; pass media directly as shown below.
+We have deprecated `CellMedia`; pass start content directly with the `start` prop as shown below.
::::
### Leading Icon
@@ -73,7 +73,7 @@ We have deprecated `CellMedia`; pass media directly as shown below.
spacingVariant="condensed"
title="List Cell with Icon"
description="Shows usage with a leading icon"
- media={ }
+ start={ }
/>
```
@@ -84,7 +84,7 @@ We have deprecated `CellMedia`; pass media directly as shown below.
spacingVariant="condensed"
title="List Cell with Icon"
description="Shows usage with a leading icon"
- media={ }
+ start={ }
/>
```
@@ -106,7 +106,7 @@ When using the Node props, you are responsible for styling, layout, and truncati
```tsx
}
+ start={ }
titleNode={
@@ -168,7 +168,7 @@ function Intermediary() {
return (
}
+ start={ }
spacingVariant="condensed"
title="Bitcoin"
description="BTC"
@@ -205,7 +205,7 @@ Like `title` and `description`, `detail` and `subdetail` props are also rendered
```tsx
}
+ start={ }
title="Custom end content"
description="Detail and subdetail rendered with custom nodes"
detailNode={
@@ -273,7 +273,7 @@ When you pass the `end` prop, it overrides the `detail`/`subdetail`/`detailNode`
spacingVariant="condensed"
title="Accessory Node"
description="Custom accessory with its own onPress"
- media={ }
+ start={ }
end={
` has a value for t
}
- media={ }
+ start={ }
onPress={() => window.alert('ListCell clicked!')}
title="BTC"
spacingVariant="condensed"
@@ -309,7 +309,7 @@ The accessibility props are only applied when the `` has a value for t
}
- media={ }
+ start={ }
title="BTC"
spacingVariant="condensed"
/>
@@ -329,7 +329,7 @@ The accessibility props are only applied when the `` has a value for t
This is a default helper message.
}
- media={ }
+ start={ }
end={Action }
/>
` has a value for t
This is a warning message.
}
- media={ }
+ start={ }
end={Action }
/>
` has a value for t
This is an error message.
}
- media={ }
+ start={ }
end={Action }
/>
@@ -368,8 +368,8 @@ The ListCellFallback component provides loading state representations of ListCel
{/* Basic loading state */}
- {/* Loading state with media */}
-
+ {/* Loading state with start content */}
+
{/* Loading state with details */}
@@ -382,7 +382,7 @@ The ListCellFallback component provides loading state representations of ListCel
detail
subdetail
helperText
- media="icon"
+ start="icon"
rectWidthVariant={2} // Creates a deterministic variant of the loading state
disableRandomRectWidth
styles={{ helperText: { paddingLeft: 48 } }}
@@ -472,6 +472,10 @@ function PriorityContent() {
}
```
+:::::note
+`start` priority applies to the title and description column, not the start slot content. The start slot always have `flexShrink={0}`.
+:::::
+
## Anatomy
Without helper text (top-only layout):
@@ -484,7 +488,7 @@ Without helper text (top-only layout):
││┌───────────────────────────────────────────────────────────────────────┐││
│││ contentContainer & mainContent (HStack) │││
│││ ┌─────┐ ┌────────────────┐ ┌────────────┐ ┌────────────┐ ┌─────────┐ │││
-│││ │media│ │ VStack │ │intermediary│ │ end │ │accessory│ │││
+│││ │start│ │ VStack │ │intermediary│ │ end │ │accessory│ │││
│││ │ │ │ ┌──────────┐ │ │ │ │ (detail │ │ │ │││
│││ │ │ │ │ title │ │ │ │ │ or │ │ │ │││
│││ │ │ │ └──────────┘ │ │ │ │ action) │ │ │ │││
@@ -509,7 +513,7 @@ With helper text (top + bottom layout):
│││┌───────────────────────────────────────────────────────────────────────┐│││
││││ mainContent (HStack) ││││
││││ ┌─────┐ ┌────────────────┐ ┌────────────┐ ┌────────────┐ ┌─────────┐ ││││
-││││ │media│ │ VStack │ │intermediary│ │ end │ │accessory│ ││││
+││││ │start│ │ VStack │ │intermediary│ │ end │ │accessory│ ││││
││││ │ │ │ ┌──────────┐ │ │ │ │ (detail │ │ │ ││││
││││ │ │ │ │ title │ │ │ │ │ or │ │ │ ││││
││││ │ │ │ └──────────┘ │ │ │ │ action) │ │ │ ││││
@@ -533,7 +537,7 @@ Mapping to `styles` / `classNames` keys:
- contentContainer: container around top and optional bottom content
- mainContent: inner horizontal layout that holds the main pieces
- title/description: stacked text column within `topContent`
-- media: leading media container
+- start: leading content container
- intermediary: middle container between main and end
- end: container for `detail` / `subdetail` or `end` prop you pass in
- accessory: trailing accessory container
diff --git a/apps/docs/docs/components/data-display/ListCell/_webExamples.mdx b/apps/docs/docs/components/data-display/ListCell/_webExamples.mdx
index f71c2bb8c..5f32e7ca9 100644
--- a/apps/docs/docs/components/data-display/ListCell/_webExamples.mdx
+++ b/apps/docs/docs/components/data-display/ListCell/_webExamples.mdx
@@ -2,7 +2,7 @@
A ListCell row is divided into the following 5 columns:
-- Media
+- Start
- Title & description
- Intermediary
- End (detail & subdetail or action)
@@ -32,7 +32,7 @@ Prefer `spacingVariant="condensed"` for the new ListCell design. The `compact` m
description="New design (condensed)"
detail="$12,345.00"
spacingVariant="condensed"
- media={ }
+ start={ }
onClick={console.log}
title="Condensed"
variant="positive"
@@ -43,7 +43,7 @@ Prefer `spacingVariant="condensed"` for the new ListCell design. The `compact` m
accessory="arrow"
detail="$12,345.00"
spacingVariant="compact"
- media={ }
+ start={ }
onClick={console.log}
title="Compact (deprecated)"
variant="positive"
@@ -52,7 +52,7 @@ Prefer `spacingVariant="condensed"` for the new ListCell design. The `compact` m
accessory="arrow"
detail="$12,345.00"
spacingVariant="normal"
- media={ }
+ start={ }
onClick={console.log}
title="Normal"
variant="positive"
@@ -60,10 +60,10 @@ Prefer `spacingVariant="condensed"` for the new ListCell design. The `compact` m
```
-## Media
+## Start
::::note
-We have deprecated `CellMedia`; pass media directly as shown below.
+We have deprecated `CellMedia`; pass start content directly with the `start` prop as shown below.
::::
### Leading Icon
@@ -73,7 +73,7 @@ We have deprecated `CellMedia`; pass media directly as shown below.
spacingVariant="condensed"
title="List Cell with Icon"
description="Shows usage with a leading icon"
- media={ }
+ start={ }
/>
```
@@ -84,7 +84,7 @@ We have deprecated `CellMedia`; pass media directly as shown below.
spacingVariant="condensed"
title="List Cell with Icon"
description="Shows usage with a leading icon"
- media={ }
+ start={ }
/>
```
@@ -106,7 +106,7 @@ When using the Node props, you are responsible for styling, layout, and truncati
```tsx live
}
+ start={ }
titleNode={
@@ -168,7 +168,7 @@ function Intermediary() {
return (
}
+ start={ }
spacingVariant="condensed"
title="Bitcoin"
description="BTC"
@@ -205,7 +205,7 @@ Like `title` and `description`, `detail` and `subdetail` props are also rendered
```tsx live
}
+ start={ }
title="Custom end content"
description="Detail and subdetail rendered with custom nodes"
detailNode={
@@ -273,7 +273,7 @@ When you pass the `end` prop, it overrides the `detail`/`subdetail`/`detailNode`
spacingVariant="condensed"
title="Accessory Node"
description="Custom accessory with its own onClick"
- media={ }
+ start={ }
end={
` has a value for t
}
- media={ }
+ start={ }
onClick={() => window.alert('ListCell clicked!')}
title="BTC"
spacingVariant="condensed"
@@ -309,7 +309,7 @@ The accessibility props are only applied when the `` has a value for t
}
- media={ }
+ start={ }
title="BTC"
spacingVariant="condensed"
/>
@@ -329,7 +329,7 @@ The accessibility props are only applied when the `` has a value for t
This is a default helper message.
}
- media={ }
+ start={ }
end={Action }
/>
` has a value for t
This is a warning message.
}
- media={ }
+ start={ }
end={Action }
/>
` has a value for t
This is an error message.
}
- media={ }
+ start={ }
end={Action }
/>
@@ -368,8 +368,8 @@ The ListCellFallback component provides loading state representations of ListCel
{/* Basic loading state */}
- {/* Loading state with media */}
-
+ {/* Loading state with start content */}
+
{/* Loading state with details */}
@@ -382,7 +382,7 @@ The ListCellFallback component provides loading state representations of ListCel
detail
subdetail
helperText
- media="icon"
+ start="icon"
rectWidthVariant={2} // Creates a deterministic variant of the loading state
disableRandomRectWidth
styles={{ helperText: { paddingLeft: 48 } }}
@@ -472,6 +472,10 @@ function PriorityContent() {
}
```
+:::::note
+`start` priority applies to the title and description column, not the start slot content. The start slot always have `flexShrink={0}`.
+:::::
+
## Anatomy
Without helper text (top-only layout):
@@ -484,7 +488,7 @@ Without helper text (top-only layout):
││┌───────────────────────────────────────────────────────────────────────┐││
│││ contentContainer & mainContent (HStack) │││
│││ ┌─────┐ ┌────────────────┐ ┌────────────┐ ┌────────────┐ ┌─────────┐ │││
-│││ │media│ │ VStack │ │intermediary│ │ end │ │accessory│ │││
+│││ │start│ │ VStack │ │intermediary│ │ end │ │accessory│ │││
│││ │ │ │ ┌──────────┐ │ │ │ │ (detail │ │ │ │││
│││ │ │ │ │ title │ │ │ │ │ or │ │ │ │││
│││ │ │ │ └──────────┘ │ │ │ │ action) │ │ │ │││
@@ -509,7 +513,7 @@ With helper text (top + bottom layout):
│││┌───────────────────────────────────────────────────────────────────────┐│││
││││ mainContent (HStack) ││││
││││ ┌─────┐ ┌────────────────┐ ┌────────────┐ ┌────────────┐ ┌─────────┐ ││││
-││││ │media│ │ VStack │ │intermediary│ │ end │ │accessory│ ││││
+││││ │start│ │ VStack │ │intermediary│ │ end │ │accessory│ ││││
││││ │ │ │ ┌──────────┐ │ │ │ │ (detail │ │ │ ││││
││││ │ │ │ │ title │ │ │ │ │ or │ │ │ ││││
││││ │ │ │ └──────────┘ │ │ │ │ action) │ │ │ ││││
@@ -533,7 +537,7 @@ Mapping to `styles` / `classNames` keys:
- contentContainer: container around top and optional bottom content
- mainContent: inner horizontal layout that holds the main pieces
- title/description: stacked text column within `topContent`
-- media: leading media container
+- start: leading content container
- intermediary: middle container between main and end
- end: container for `detail` / `subdetail` or `end` prop you pass in
- accessory: trailing accessory container
diff --git a/packages/common/CHANGELOG.md b/packages/common/CHANGELOG.md
index eda7f61e8..83e90f821 100644
--- a/packages/common/CHANGELOG.md
+++ b/packages/common/CHANGELOG.md
@@ -8,6 +8,10 @@ All notable changes to this project will be documented in this file.
+## 8.20.2 ((11/7/2025, 03:45 PM PST))
+
+This is an artificial version bump with no new change.
+
## 8.20.1 ((11/7/2025, 01:20 PM PST))
This is an artificial version bump with no new change.
diff --git a/packages/common/package.json b/packages/common/package.json
index b999b7c9c..8ea68b5dc 100644
--- a/packages/common/package.json
+++ b/packages/common/package.json
@@ -1,6 +1,6 @@
{
"name": "@coinbase/cds-common",
- "version": "8.20.1",
+ "version": "8.20.2",
"description": "Coinbase Design System - Common",
"repository": {
"type": "git",
diff --git a/packages/mcp-server/CHANGELOG.md b/packages/mcp-server/CHANGELOG.md
index 137294495..c9eaefe90 100644
--- a/packages/mcp-server/CHANGELOG.md
+++ b/packages/mcp-server/CHANGELOG.md
@@ -8,6 +8,10 @@ All notable changes to this project will be documented in this file.
+## 8.20.2 ((11/7/2025, 03:45 PM PST))
+
+This is an artificial version bump with no new change.
+
## 8.20.1 ((11/7/2025, 01:20 PM PST))
This is an artificial version bump with no new change.
diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json
index 69f7b545e..847f36588 100644
--- a/packages/mcp-server/package.json
+++ b/packages/mcp-server/package.json
@@ -1,6 +1,6 @@
{
"name": "@coinbase/cds-mcp-server",
- "version": "8.20.1",
+ "version": "8.20.2",
"description": "Coinbase Design System - MCP Server",
"repository": {
"type": "git",
diff --git a/packages/mobile/CHANGELOG.md b/packages/mobile/CHANGELOG.md
index 46b632d42..6fd01b655 100644
--- a/packages/mobile/CHANGELOG.md
+++ b/packages/mobile/CHANGELOG.md
@@ -8,6 +8,12 @@ All notable changes to this project will be documented in this file.
+## 8.20.2 (11/7/2025 PST)
+
+#### 🐞 Fixes
+
+- Deprecated `media` in favor of `start` prop in ListCell. [[#136](https://github.com/coinbase/cds/pull/136)]
+
## 8.20.1 (11/7/2025 PST)
#### 🐞 Fixes
diff --git a/packages/mobile/package.json b/packages/mobile/package.json
index 511f1b870..ef782af91 100644
--- a/packages/mobile/package.json
+++ b/packages/mobile/package.json
@@ -1,6 +1,6 @@
{
"name": "@coinbase/cds-mobile",
- "version": "8.20.1",
+ "version": "8.20.2",
"description": "Coinbase Design System - Mobile",
"repository": {
"type": "git",
diff --git a/packages/mobile/src/cells/Cell.tsx b/packages/mobile/src/cells/Cell.tsx
index b1af4491a..9380e5a10 100644
--- a/packages/mobile/src/cells/Cell.tsx
+++ b/packages/mobile/src/cells/Cell.tsx
@@ -51,7 +51,11 @@ export type CellBaseProps = SharedProps &
detail?: React.ReactNode;
/** Middle content between main content and detail. */
intermediary?: React.ReactNode;
- /** Media rendered at the start of the cell (icon, avatar, image, etc). */
+ /** Content rendered at the start of the cell (icon, avatar, image, etc). */
+ start?: React.ReactElement;
+ /**
+ * @deprecated Use `start` instead. `media` will be removed in a future major release.
+ */
media?: React.ReactElement;
borderRadius?: ThemeVars.BorderRadius;
/**
@@ -79,6 +83,10 @@ export type CellBaseProps = SharedProps &
topContent?: StyleProp;
bottomContent?: StyleProp;
pressable?: StyleProp;
+ start?: StyleProp;
+ /**
+ * @deprecated Use `styles.start` instead. `styles.media` will be removed in a future major release.
+ */
media?: StyleProp;
intermediary?: StyleProp;
/** Applied to the container of detail or action */
@@ -101,6 +109,7 @@ export const Cell = memo(function Cell({
detailWidth,
disabled,
intermediary,
+ start,
media,
minHeight,
maxHeight,
@@ -154,11 +163,13 @@ export const Cell = memo(function Cell({
const endContent = end ?? detail;
+ const startNode = start ?? media;
+
const topContent = (
<>
- {!!media && (
-
- {media}
+ {!!startNode && (
+
+ {startNode}
)}
@@ -232,8 +243,10 @@ export const Cell = memo(function Cell({
alignItems,
columnGap,
gap,
+ start,
media,
styles?.media,
+ styles?.start,
priority,
children,
intermediary,
diff --git a/packages/mobile/src/cells/ListCell.tsx b/packages/mobile/src/cells/ListCell.tsx
index fe72eb6c7..5710214f9 100644
--- a/packages/mobile/src/cells/ListCell.tsx
+++ b/packages/mobile/src/cells/ListCell.tsx
@@ -86,7 +86,11 @@ export type ListCellBaseProps = CellDetailProps &
helperText?: React.ReactNode;
/** For internal use only. */
intermediary?: React.ReactNode;
- /* Media (icon, asset, image, etc) to display at the start of the cell. */
+ /** Content to display at the start of the cell (icon, asset, image, etc). */
+ start?: React.ReactElement;
+ /**
+ * @deprecated Use `start` instead. `media` will be removed in a future major release.
+ */
media?: React.ReactElement;
/** Allow the description to span multiple lines. This *will* break fixed height requirements, so should not be used in a `FlatList`. */
multiline?: boolean;
@@ -97,6 +101,10 @@ export type ListCellBaseProps = CellDetailProps &
/** Styles for the components */
styles?: {
root?: StyleProp;
+ start?: StyleProp;
+ /**
+ * @deprecated Use `styles.start` instead. `styles.media` will be removed in a future major release.
+ */
media?: StyleProp;
intermediary?: StyleProp;
end?: StyleProp;
@@ -133,6 +141,7 @@ export const ListCell = memo(function ListCell({
disabled,
disableSelectionAccessory,
helperText,
+ start,
media,
multiline,
selected,
@@ -196,7 +205,6 @@ export const ListCell = memo(function ListCell({
innerSpacing ?? (spacingVariant === 'condensed' ? condensedInnerSpacing : undefined)
}
intermediary={intermediary}
- media={media}
minHeight={minHeight}
onPress={onPress}
outerSpacing={
@@ -204,8 +212,10 @@ export const ListCell = memo(function ListCell({
}
priority={priority}
selected={selected}
+ start={start ?? media}
style={[style, styles?.root]}
styles={{
+ start: styles?.start,
accessory: styles?.accessory,
bottomContent: styles?.helperText,
contentContainer: styles?.contentContainer,
diff --git a/packages/mobile/src/cells/ListCellFallback.tsx b/packages/mobile/src/cells/ListCellFallback.tsx
index 98e27aafa..1dba04c54 100644
--- a/packages/mobile/src/cells/ListCellFallback.tsx
+++ b/packages/mobile/src/cells/ListCellFallback.tsx
@@ -21,7 +21,11 @@ export type ListCellFallbackBaseProps = SharedProps &
detail?: boolean;
/** Display helper text shimmer. */
helperText?: boolean;
- /** Display media shimmer with a shape according to type. */
+ /** Display start shimmer with a shape according to type. */
+ start?: CellMediaType;
+ /**
+ * @deprecated Use `start` instead. `media` will be removed in a future major release.
+ */
media?: CellMediaType;
/** Display subdetail shimmer. */
subdetail?: boolean;
@@ -50,6 +54,7 @@ export const ListCellFallback = memo(function ListCellFallback({
description,
detail,
subdetail,
+ start,
media,
disableRandomRectWidth,
rectWidthVariant,
@@ -149,12 +154,14 @@ export const ListCellFallback = memo(function ListCellFallback({
]);
const mediaFallback = useMemo(() => {
- if (!media) {
+ const startType = start ?? media;
+
+ if (!startType) {
return;
}
- return ;
- }, [media]);
+ return ;
+ }, [media, start]);
const titleFallback = useMemo(() => {
if (!title) {
@@ -180,10 +187,10 @@ export const ListCellFallback = memo(function ListCellFallback({
innerSpacing={
innerSpacing ?? (spacingVariant === 'condensed' ? condensedInnerSpacing : undefined)
}
- media={mediaFallback}
outerSpacing={
outerSpacing ?? (spacingVariant === 'condensed' ? condensedOuterSpacing : undefined)
}
+ start={mediaFallback}
{...props}
>
diff --git a/packages/mobile/src/cells/__stories__/ListCell.stories.tsx b/packages/mobile/src/cells/__stories__/ListCell.stories.tsx
index f72356012..85b267274 100644
--- a/packages/mobile/src/cells/__stories__/ListCell.stories.tsx
+++ b/packages/mobile/src/cells/__stories__/ListCell.stories.tsx
@@ -87,8 +87,8 @@ const CustomNodes = () => (
}
- media={ }
spacingVariant="condensed"
+ start={ }
titleNode={
@@ -113,9 +113,9 @@ const CustomNodes = () => (
$12
}
- media={ }
priority="end"
spacingVariant="condensed"
+ start={ }
subdetailNode={
@@ -550,44 +550,44 @@ const WithAccessory = () => (
const WithMedia = () => (
<>
- } spacingVariant="condensed" title="Icon" />
+ } title="Icon" />
}
onPress={onPressConsole}
spacingVariant="condensed"
+ start={ }
title="Icon (pressable)"
/>
}
spacingVariant="condensed"
+ start={ }
title="Icon"
/>
}
spacingVariant="condensed"
+ start={ }
title="Avatar"
/>
}
spacingVariant="condensed"
+ start={ }
subdetail="Neutral"
title="Asset"
/>
}
spacingVariant="condensed"
+ start={ }
title="Image"
/>
}
spacingVariant="condensed"
+ start={ }
title="Pictogram"
/>
>
@@ -711,9 +711,9 @@ const WithHelperText = () => (
Helper text with media}
- media={ }
onPress={onPressConsole}
spacingVariant="condensed"
+ start={ }
title="Title"
/>
(
Helper text with media, action, and accessory and very long text
}
- media={ }
priority="end"
spacingVariant="condensed"
+ start={ }
title="Title"
/>
>
@@ -774,9 +774,9 @@ const CondensedListCell = () => {
accessory="more"
description="Description"
detail="Detail"
- media={ }
onPress={onPressConsole}
spacingVariant="condensed"
+ start={ }
subdetail="Subdetail"
title="Title"
/>
@@ -789,9 +789,9 @@ const CondensedListCell = () => {
This is helpful information to guide the user
}
- media={ }
onPress={onPressConsole}
spacingVariant="condensed"
+ start={ }
subdetail="Subdetail"
title="Title"
/>
@@ -800,9 +800,9 @@ const CondensedListCell = () => {
accessory="more"
description="Long description with multiple lines. This section can be arbitrarily long and occupy many many lines."
detail="Detail"
- media={ }
onPress={onPressConsole}
spacingVariant="condensed"
+ start={ }
subdetail="Subdetail"
title="Title"
/>
@@ -811,9 +811,9 @@ const CondensedListCell = () => {
accessory="more"
description="Long description with multiple lines. This section can be arbitrarily long and occupy many many lines."
detail="Detail"
- media={ }
onPress={onPressConsole}
spacingVariant="condensed"
+ start={ }
styles={{
media: {
marginTop: theme.space[1],
@@ -836,9 +836,9 @@ const CondensedListCell = () => {
accessory="more"
description="Description"
detail="Detail"
- media={ }
onPress={onPressConsole}
spacingVariant="condensed"
+ start={ }
subdetail="Subdetail"
title="Title"
/>
@@ -846,9 +846,9 @@ const CondensedListCell = () => {
accessory="more"
description="Description"
detail="Detail"
- media={ }
onPress={onPressConsole}
spacingVariant="condensed"
+ start={ }
subdetail="Subdetail"
title="Title"
/>
@@ -857,9 +857,9 @@ const CondensedListCell = () => {
description="Description"
detail="Detail"
end={Action }
- media={ }
onPress={onPressConsole}
spacingVariant="condensed"
+ start={ }
subdetail="Subdetail"
title="Title"
/>
@@ -868,9 +868,9 @@ const CondensedListCell = () => {
description="Description"
detail="Detail"
intermediary={ }
- media={ }
onPress={onPressConsole}
spacingVariant="condensed"
+ start={ }
subdetail={
@@ -893,9 +893,9 @@ const SpacingVariant = () => (
description="New design"
detail="$12,345.00"
intermediary={ }
- media={ }
onPress={onPressConsole}
spacingVariant="condensed"
+ start={ }
subdetail="+1.23%"
title="Condensed"
variant="positive"
@@ -907,9 +907,9 @@ const SpacingVariant = () => (
description="Deprecated (use condensed)"
detail="$12,345.00"
intermediary={ }
- media={ }
onPress={onPressConsole}
spacingVariant="compact"
+ start={ }
subdetail="+1.23%"
title="Compact"
variant="positive"
@@ -918,9 +918,9 @@ const SpacingVariant = () => (
accessory="arrow"
detail="$12,345.00"
intermediary={ }
- media={ }
onPress={onPressConsole}
spacingVariant="normal"
+ start={ }
subdetail="+1.23%"
title="Normal"
variant="positive"
@@ -982,10 +982,10 @@ const UseCaseShowcase = () => {
}
intermediary={ }
- media={ }
onPress={onPressConsole}
priority="middle"
spacingVariant="condensed"
+ start={ }
styles={{
end: {
width: 100,
@@ -1005,9 +1005,9 @@ const UseCaseShowcase = () => {
}
intermediary={ }
- media={ }
onPress={onPressConsole}
spacingVariant="condensed"
+ start={ }
styles={{
end: {
width: 100,
@@ -1027,9 +1027,9 @@ const UseCaseShowcase = () => {
}
intermediary={ }
- media={ }
onPress={onPressConsole}
spacingVariant="condensed"
+ start={ }
styles={{
end: {
width: 100,
@@ -1046,9 +1046,9 @@ const UseCaseShowcase = () => {
}
intermediary={ }
- media={ }
onPress={onPressConsole}
spacingVariant="condensed"
+ start={ }
styles={{
end: {
width: 100,
@@ -1066,9 +1066,9 @@ const UseCaseShowcase = () => {
}
intermediary={ }
- media={ }
onPress={onPressConsole}
spacingVariant="condensed"
+ start={ }
styles={{
end: {
width: 100,
diff --git a/packages/mobile/src/cells/__stories__/ListCellFallback.stories.tsx b/packages/mobile/src/cells/__stories__/ListCellFallback.stories.tsx
index dec895fb1..ce2cdd238 100644
--- a/packages/mobile/src/cells/__stories__/ListCellFallback.stories.tsx
+++ b/packages/mobile/src/cells/__stories__/ListCellFallback.stories.tsx
@@ -35,35 +35,35 @@ const Fallbacks = () => {
title
spacingVariant="condensed"
/>
-
+
{
disableRandomRectWidth
subdetail
title
- media="asset"
spacingVariant="condensed"
+ start="asset"
/>
@@ -114,35 +114,35 @@ const Fallbacks = () => {
title
spacingVariant="compact"
/>
-
+
{
disableRandomRectWidth
subdetail
title
- media="asset"
spacingVariant="compact"
+ start="asset"
/>
{
helperText
subdetail
title
- media="image"
spacingVariant="compact"
+ start="image"
styles={{ helperText: { paddingLeft: 64 } }}
/>
>
diff --git a/packages/web/CHANGELOG.md b/packages/web/CHANGELOG.md
index a4e9318f3..082480f9a 100644
--- a/packages/web/CHANGELOG.md
+++ b/packages/web/CHANGELOG.md
@@ -8,6 +8,12 @@ All notable changes to this project will be documented in this file.
+## 8.20.2 (11/7/2025 PST)
+
+#### 🐞 Fixes
+
+- Deprecated `media` in favor of `start` prop in ListCell. [[#136](https://github.com/coinbase/cds/pull/136)]
+
## 8.20.1 (11/7/2025 PST)
#### 🐞 Fixes
diff --git a/packages/web/package.json b/packages/web/package.json
index 538b8ed3e..110ee7a36 100644
--- a/packages/web/package.json
+++ b/packages/web/package.json
@@ -1,6 +1,6 @@
{
"name": "@coinbase/cds-web",
- "version": "8.20.1",
+ "version": "8.20.2",
"description": "Coinbase Design System - Web",
"repository": {
"type": "git",
diff --git a/packages/web/src/cells/Cell.tsx b/packages/web/src/cells/Cell.tsx
index 63810510c..c3a6d0381 100644
--- a/packages/web/src/cells/Cell.tsx
+++ b/packages/web/src/cells/Cell.tsx
@@ -101,7 +101,11 @@ export type CellBaseProps = Polymorphic.ExtendableProps<
detail?: React.ReactNode;
/** Middle content between main content and detail. */
intermediary?: React.ReactNode;
- /** Media rendered at the start of the cell (icon, avatar, image, etc). */
+ /** Content rendered at the start of the cell (icon, avatar, image, etc). */
+ start?: React.ReactElement;
+ /**
+ * @deprecated Use `start` instead. `media` will be removed in a future major release.
+ */
media?: React.ReactElement;
/**
* @deprecated Use `shouldTruncate` instead. `shouldOverflow` will be removed in a future release.
@@ -136,6 +140,10 @@ export type CellBaseProps = Polymorphic.ExtendableProps<
topContent?: React.CSSProperties;
bottomContent?: React.CSSProperties;
pressable?: React.CSSProperties;
+ start?: React.CSSProperties;
+ /**
+ * @deprecated Use `styles.start` instead. `styles.media` will be removed in a future major release.
+ */
media?: React.CSSProperties;
intermediary?: React.CSSProperties;
/** Applied to the container of detail or action */
@@ -149,6 +157,10 @@ export type CellBaseProps = Polymorphic.ExtendableProps<
topContent?: string;
bottomContent?: string;
pressable?: string;
+ start?: string;
+ /**
+ * @deprecated Use `classNames.start` instead. `classNames.media` will be removed in a future major release.
+ */
media?: string;
intermediary?: string;
/** Applied to the container of detail or action */
@@ -191,6 +203,7 @@ export const Cell: CellComponent = memo(
columnGap,
rowGap = 1,
intermediary,
+ start,
media,
minHeight,
maxHeight,
@@ -258,11 +271,18 @@ export const Cell: CellComponent = memo(
const endWidth = styles?.end?.width ?? detailWidth;
// content that is displayed horizontally above the bottom content
+ const startNode = start ?? media;
+
const topContent = (
<>
- {media && (
-
- {media}
+ {startNode && (
+
+ {startNode}
)}
@@ -343,6 +363,7 @@ export const Cell: CellComponent = memo(
classNames?.contentContainer,
classNames?.topContent,
classNames?.media,
+ classNames?.start,
classNames?.intermediary,
classNames?.end,
classNames?.accessory,
@@ -356,6 +377,7 @@ export const Cell: CellComponent = memo(
styles?.contentContainer,
styles?.topContent,
styles?.media,
+ styles?.start,
styles?.intermediary,
styles?.end,
styles?.accessory,
@@ -363,6 +385,7 @@ export const Cell: CellComponent = memo(
alignItems,
columnGap,
gap,
+ start,
media,
contentTruncationStyle,
priority,
diff --git a/packages/web/src/cells/ListCell.tsx b/packages/web/src/cells/ListCell.tsx
index f1a02bad6..dee992d5a 100644
--- a/packages/web/src/cells/ListCell.tsx
+++ b/packages/web/src/cells/ListCell.tsx
@@ -96,7 +96,11 @@ export type ListCellBaseProps = Polymorphic.ExtendableProps<
helperText?: React.ReactNode;
/** For internal use only. */
intermediary?: React.ReactNode;
- /* Media (icon, asset, image, etc) to display at the start of the cell. */
+ /** Content to display at the start of the cell (icon, asset, image, etc). */
+ start?: React.ReactElement;
+ /**
+ * @deprecated Use `start` instead. `media` will be removed in a future major release.
+ */
media?: React.ReactElement;
/** Allow the description to span multiple lines. This *will* break fixed height requirements, so should not be used in a `FlatList`. */
multiline?: boolean;
@@ -107,6 +111,10 @@ export type ListCellBaseProps = Polymorphic.ExtendableProps<
/** Class names for the components */
classNames?: {
root?: string;
+ start?: string;
+ /**
+ * @deprecated Use `classNames.start` instead. `classNames.media` will be removed in a future major release.
+ */
media?: string;
intermediary?: string;
end?: string;
@@ -121,6 +129,10 @@ export type ListCellBaseProps = Polymorphic.ExtendableProps<
/** Styles for the components */
styles?: {
root?: React.CSSProperties;
+ start?: React.CSSProperties;
+ /**
+ * @deprecated Use `styles.start` instead. `styles.media` will be removed in a future major release.
+ */
media?: React.CSSProperties;
intermediary?: React.CSSProperties;
end?: React.CSSProperties;
@@ -165,6 +177,7 @@ export const ListCell: ListCellComponent = memo(
disableMultilineTitle = false,
disableSelectionAccessory,
helperText,
+ start,
media,
multiline,
selected,
@@ -232,15 +245,16 @@ export const ListCell: ListCellComponent = memo(
innerSpacing ?? (spacingVariant === 'condensed' ? condensedInnerSpacing : undefined)
}
intermediary={intermediary}
- media={media}
minHeight={minHeight}
outerSpacing={
outerSpacing ?? (spacingVariant === 'condensed' ? condensedOuterSpacing : undefined)
}
priority={priority}
selected={selected}
+ start={start ?? media}
style={{ ...style, ...styles?.root }}
styles={{
+ start: styles?.start,
media: styles?.media,
intermediary: styles?.intermediary,
end: styles?.end,
diff --git a/packages/web/src/cells/ListCellFallback.tsx b/packages/web/src/cells/ListCellFallback.tsx
index 5fc8335c0..7f0603c7e 100644
--- a/packages/web/src/cells/ListCellFallback.tsx
+++ b/packages/web/src/cells/ListCellFallback.tsx
@@ -19,7 +19,11 @@ export type ListCellFallbackBaseProps = SharedProps &
detail?: boolean;
/** Display helper text shimmer. */
helperText?: boolean;
- /** Display media shimmer with a shape according to type. */
+ /** Display start shimmer with a shape according to type. */
+ start?: CellMediaType;
+ /**
+ * @deprecated Use `start` instead. `media` will be removed in a future major release.
+ */
media?: CellMediaType;
/** Display subdetail shimmer. */
subdetail?: boolean;
@@ -63,6 +67,7 @@ export const ListCellFallback = memo(function ListCellFallback({
description,
detail,
subdetail,
+ start,
media,
disableRandomRectWidth,
rectWidthVariant,
@@ -190,12 +195,14 @@ export const ListCellFallback = memo(function ListCellFallback({
]);
const mediaFallback = useMemo(() => {
- if (!media) {
+ const startType = start ?? media;
+
+ if (!startType) {
return undefined;
}
- return ;
- }, [media]);
+ return ;
+ }, [media, start]);
return (
diff --git a/packages/web/src/cells/__stories__/ListCell.stories.tsx b/packages/web/src/cells/__stories__/ListCell.stories.tsx
index 4f096f1a8..45585dd7e 100644
--- a/packages/web/src/cells/__stories__/ListCell.stories.tsx
+++ b/packages/web/src/cells/__stories__/ListCell.stories.tsx
@@ -118,8 +118,8 @@ const CustomNodes = () => {
|
}
- media={ }
spacingVariant="condensed"
+ start={ }
titleNode={
@@ -140,8 +140,8 @@ const CustomNodes = () => {
$12,345.00
}
- media={ }
spacingVariant="condensed"
+ start={ }
subdetailNode={
@@ -621,50 +621,50 @@ const WithAccessory = () => (
const WithMedia = () => (
<>
- } spacingVariant="condensed" title="Icon" />
+ } title="Icon" />
}
onClick={onClickConsole}
spacingVariant="condensed"
+ start={ }
title="Icon (pressable)"
/>
}
spacingVariant="condensed"
+ start={ }
title="Icon"
/>
}
spacingVariant="condensed"
+ start={ }
title="Avatar"
/>
}
spacingVariant="condensed"
+ start={ }
subdetail="Neutral"
title="Asset"
/>
}
spacingVariant="condensed"
+ start={ }
title="Image"
/>
}
spacingVariant="condensed"
+ start={ }
title="Pictogram"
/>
>
@@ -790,9 +790,9 @@ const WithHelperText = () => (
Please review this information carefully before proceeding
}
- media={ }
priority="end"
spacingVariant="condensed"
+ start={ }
title="With Media and Helper Text"
/>
@@ -806,9 +806,9 @@ const WithHelperText = () => (
This field contains an error that needs to be corrected
}
- media={ }
priority="end"
spacingVariant="condensed"
+ start={ }
title="With Detail and Helper Text"
variant="negative"
/>
@@ -822,9 +822,9 @@ const WithHelperText = () => (
This action cannot be undone.
}
- media={ }
priority="end"
spacingVariant="condensed"
+ start={ }
title="With Media and Action"
/>
@@ -838,9 +838,9 @@ const SpacingVariant = () => (
description="New design"
detail="$12,345.00"
intermediary={ }
- media={ }
onClick={onClickConsole}
spacingVariant="condensed"
+ start={ }
subdetail="+1.23%"
title="Condensed"
variant="positive"
@@ -852,9 +852,9 @@ const SpacingVariant = () => (
description="Deprecated (use condensed)"
detail="$12,345.00"
intermediary={ }
- media={ }
onClick={onClickConsole}
spacingVariant="compact"
+ start={ }
subdetail="+1.23%"
title="Compact"
variant="positive"
@@ -863,9 +863,9 @@ const SpacingVariant = () => (
accessory="arrow"
detail="$12,345.00"
intermediary={ }
- media={ }
onClick={onClickConsole}
spacingVariant="normal"
+ start={ }
subdetail="+1.23%"
title="Normal"
variant="positive"
@@ -880,9 +880,9 @@ const CondensedListCell = () => {
accessory="more"
description="Description"
detail="Detail"
- media={ }
onClick={onClickConsole}
spacingVariant="condensed"
+ start={ }
subdetail="Subdetail"
title="Title"
/>
@@ -895,9 +895,9 @@ const CondensedListCell = () => {
This is helpful information to guide the user
}
- media={ }
onClick={onClickConsole}
spacingVariant="condensed"
+ start={ }
subdetail="Subdetail"
title="Title"
/>
@@ -906,9 +906,9 @@ const CondensedListCell = () => {
accessory="more"
description="Long description with multiple lines. This section can be arbitrarily long and occupy many many lines."
detail="Detail"
- media={ }
onClick={onClickConsole}
spacingVariant="condensed"
+ start={ }
subdetail="Subdetail"
title="Title"
/>
@@ -917,9 +917,9 @@ const CondensedListCell = () => {
accessory="more"
description="Long description with multiple lines. This section can be arbitrarily long and occupy many many lines."
detail="Detail"
- media={ }
onClick={onClickConsole}
spacingVariant="condensed"
+ start={ }
styles={{
media: {
marginTop: 'var(--space-1)',
@@ -942,9 +942,9 @@ const CondensedListCell = () => {
accessory="more"
description="Description"
detail="Detail"
- media={ }
onClick={onClickConsole}
spacingVariant="condensed"
+ start={ }
subdetail="Subdetail"
title="Title"
/>
@@ -952,9 +952,9 @@ const CondensedListCell = () => {
accessory="more"
description="Description"
detail="Detail"
- media={ }
onClick={onClickConsole}
spacingVariant="condensed"
+ start={ }
subdetail="Subdetail"
title="Title"
/>
@@ -963,9 +963,9 @@ const CondensedListCell = () => {
description="Description"
detail="Detail"
end={Action }
- media={ }
onClick={onClickConsole}
spacingVariant="condensed"
+ start={ }
subdetail="Subdetail"
title="Title"
/>
@@ -974,9 +974,9 @@ const CondensedListCell = () => {
description="Description"
detail="Detail"
intermediary={ }
- media={ }
onClick={onClickConsole}
spacingVariant="condensed"
+ start={ }
subdetail={
@@ -1045,10 +1045,10 @@ const UseCaseShowcase = () => {
}
intermediary={ }
- media={ }
onClick={onClickConsole}
priority="middle"
spacingVariant="condensed"
+ start={ }
styles={{
end: {
width: 100,
@@ -1068,9 +1068,9 @@ const UseCaseShowcase = () => {
}
intermediary={ }
- media={ }
onClick={onClickConsole}
spacingVariant="condensed"
+ start={ }
styles={{
end: {
width: 100,
@@ -1090,9 +1090,9 @@ const UseCaseShowcase = () => {
}
intermediary={ }
- media={ }
onClick={onClickConsole}
spacingVariant="condensed"
+ start={ }
styles={{
end: {
width: 100,
@@ -1109,9 +1109,9 @@ const UseCaseShowcase = () => {
}
intermediary={ }
- media={ }
onClick={onClickConsole}
spacingVariant="condensed"
+ start={ }
styles={{
end: {
width: 100,
@@ -1129,9 +1129,9 @@ const UseCaseShowcase = () => {
}
intermediary={ }
- media={ }
onClick={onClickConsole}
spacingVariant="condensed"
+ start={ }
styles={{
end: {
width: 100,
diff --git a/packages/web/src/cells/__stories__/ListCellFallback.stories.tsx b/packages/web/src/cells/__stories__/ListCellFallback.stories.tsx
index 86e957f35..3d2cf3fbe 100644
--- a/packages/web/src/cells/__stories__/ListCellFallback.stories.tsx
+++ b/packages/web/src/cells/__stories__/ListCellFallback.stories.tsx
@@ -26,15 +26,15 @@ export const Fallbacks = () => {
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
{
disableRandomRectWidth
helperText
title
- media="pictogram"
+ start="pictogram"
styles={{
helperText: {
paddingLeft: 48,
@@ -56,7 +56,7 @@ export const Fallbacks = () => {
helperText
subdetail
title
- media="asset"
+ start="asset"
styles={{
helperText: {
paddingLeft: 48,
@@ -70,7 +70,7 @@ export const Fallbacks = () => {
helperText
subdetail
title
- media="image"
+ start="image"
styles={{
helperText: {
paddingLeft: 64,
@@ -84,8 +84,8 @@ export const Fallbacks = () => {
subdetail
title
innerSpacing={innerSpacing}
- media="asset"
outerSpacing={outerSpacing}
+ start="asset"
/>
>
);