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 This is a warning message. } - media={} + start={} end={} /> ` has a value for t This is an error message. } - media={} + start={} end={} /> @@ -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 This is a warning message. } - media={} + start={} end={} /> ` has a value for t This is an error message. } - media={} + start={} end={} /> @@ -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={} - 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={} - 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" /> );