@coinbase/cds-mcp-server 8.41.0 → 8.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/mcp-docs/mobile/components/ContainedAssetCard.txt +1 -1
- package/mcp-docs/mobile/components/ContentCard.txt +220 -174
- package/mcp-docs/mobile/components/ContentCardBody.txt +127 -19
- package/mcp-docs/mobile/components/ContentCardFooter.txt +63 -1
- package/mcp-docs/mobile/components/ContentCardHeader.txt +71 -16
- package/mcp-docs/mobile/components/DataCard.txt +723 -0
- package/mcp-docs/mobile/components/FloatingAssetCard.txt +1 -1
- package/mcp-docs/mobile/components/MediaCard.txt +526 -0
- package/mcp-docs/mobile/components/MessagingCard.txt +1025 -0
- package/mcp-docs/mobile/components/Scrubber.txt +140 -0
- package/mcp-docs/mobile/routes.txt +6 -3
- package/mcp-docs/web/components/ContentCard.txt +419 -327
- package/mcp-docs/web/components/ContentCardBody.txt +91 -16
- package/mcp-docs/web/components/ContentCardFooter.txt +231 -165
- package/mcp-docs/web/components/ContentCardHeader.txt +237 -177
- package/mcp-docs/web/components/DataCard.txt +800 -0
- package/mcp-docs/web/components/MediaCard.txt +559 -0
- package/mcp-docs/web/components/MessagingCard.txt +1054 -0
- package/mcp-docs/web/components/ReferenceLine.txt +1 -0
- package/mcp-docs/web/components/Scrubber.txt +106 -0
- package/mcp-docs/web/routes.txt +3 -0
- package/package.json +1 -1
|
@@ -0,0 +1,1025 @@
|
|
|
1
|
+
# MessagingCard
|
|
2
|
+
|
|
3
|
+
MessagingCard displays promotional or informational content with two variants: 'upsell' for promoting features with a primary background, and 'nudge' for encouraging actions with an alternate background. It replaces the deprecated NudgeCard and UpsellCard components.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { MessagingCard } from '@coinbase/cds-mobile/cards/MessagingCard'
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Examples
|
|
12
|
+
|
|
13
|
+
MessagingCard provides two card types for promotional and informational content.
|
|
14
|
+
|
|
15
|
+
:::info Migrating from NudgeCard or UpsellCard?
|
|
16
|
+
See the [Migration Guide](#migration-from-deprecated-components) at the end of this page.
|
|
17
|
+
:::
|
|
18
|
+
|
|
19
|
+
### Basic Types
|
|
20
|
+
|
|
21
|
+
Use `type` to set the card variant:
|
|
22
|
+
|
|
23
|
+
- `upsell`: Primary background, used for promoting features or products. Use `variant="secondary"` buttons.
|
|
24
|
+
- `nudge`: Alternate background, used for encouraging user actions. Use `variant="tertiary"` (transparent) buttons for a less intrusive appearance.
|
|
25
|
+
|
|
26
|
+
```jsx
|
|
27
|
+
<VStack gap={2}>
|
|
28
|
+
<MessagingCard
|
|
29
|
+
type="upsell"
|
|
30
|
+
title="Upsell Card"
|
|
31
|
+
description="This is an upsell card with primary background"
|
|
32
|
+
width={320}
|
|
33
|
+
action="Get started"
|
|
34
|
+
onActionButtonPress={() => console.log('Action pressed!')}
|
|
35
|
+
media={
|
|
36
|
+
<RemoteImage
|
|
37
|
+
accessibilityLabel="Feature promotional image"
|
|
38
|
+
height={160}
|
|
39
|
+
resizeMode="cover"
|
|
40
|
+
shape="rectangle"
|
|
41
|
+
source={{ uri: 'https://cds.coinbase.com/img/feature.png' }}
|
|
42
|
+
/>
|
|
43
|
+
}
|
|
44
|
+
mediaPlacement="end"
|
|
45
|
+
/>
|
|
46
|
+
<MessagingCard
|
|
47
|
+
type="nudge"
|
|
48
|
+
title="Nudge Card"
|
|
49
|
+
description="This is a nudge card with alternate background"
|
|
50
|
+
width={320}
|
|
51
|
+
action="Learn more"
|
|
52
|
+
onActionButtonPress={() => console.log('Action pressed!')}
|
|
53
|
+
media={<Pictogram dimension="64x64" name="addToWatchlist" />}
|
|
54
|
+
mediaPlacement="end"
|
|
55
|
+
/>
|
|
56
|
+
</VStack>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
:::tip Nudge Button Style
|
|
60
|
+
Use transparent buttons (`variant="tertiary"` or `transparent` prop) for nudge cards. They provide a gentle reminder without being intrusive, blending more seamlessly with the card's alternate background.
|
|
61
|
+
:::
|
|
62
|
+
|
|
63
|
+
### Media Placement
|
|
64
|
+
|
|
65
|
+
Use `mediaPlacement` to control the position of media content.
|
|
66
|
+
|
|
67
|
+
```jsx
|
|
68
|
+
<VStack gap={2}>
|
|
69
|
+
<MessagingCard
|
|
70
|
+
type="nudge"
|
|
71
|
+
title="Media End"
|
|
72
|
+
description="Media placed at the end (right)"
|
|
73
|
+
width={320}
|
|
74
|
+
media={<Pictogram dimension="48x48" name="addToWatchlist" />}
|
|
75
|
+
mediaPlacement="end"
|
|
76
|
+
/>
|
|
77
|
+
<MessagingCard
|
|
78
|
+
type="nudge"
|
|
79
|
+
title="Media Start"
|
|
80
|
+
description="Media placed at the start (left)"
|
|
81
|
+
width={320}
|
|
82
|
+
media={<Pictogram dimension="48x48" name="addToWatchlist" />}
|
|
83
|
+
mediaPlacement="start"
|
|
84
|
+
/>
|
|
85
|
+
</VStack>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Upsell Card Styles
|
|
89
|
+
|
|
90
|
+
MessagingCard with `type="upsell"` supports various background colors to match different promotional purposes. Use the `background` prop for semantic tokens, or `dangerouslySetBackground` for custom spectrum colors.
|
|
91
|
+
|
|
92
|
+
#### General Upsell
|
|
93
|
+
|
|
94
|
+
Utilize the default background for general information and non-urgent promotions. Its versatile design is perfect for a broad range of content, providing a subtle yet effective approach to engage users. It's also the most suitable style for Pictogram illustrations.
|
|
95
|
+
|
|
96
|
+
```jsx
|
|
97
|
+
<MessagingCard
|
|
98
|
+
type="upsell"
|
|
99
|
+
background="bgPrimaryWash"
|
|
100
|
+
title={
|
|
101
|
+
<Text color="fg" font="headline">
|
|
102
|
+
Recurring Buy
|
|
103
|
+
</Text>
|
|
104
|
+
}
|
|
105
|
+
description={
|
|
106
|
+
<Text color="fg" font="label2">
|
|
107
|
+
Want to add funds to your card every week or month?
|
|
108
|
+
</Text>
|
|
109
|
+
}
|
|
110
|
+
width={360}
|
|
111
|
+
action={
|
|
112
|
+
<Button compact variant="secondary">
|
|
113
|
+
Get started
|
|
114
|
+
</Button>
|
|
115
|
+
}
|
|
116
|
+
media={
|
|
117
|
+
<Box paddingEnd={3}>
|
|
118
|
+
<Pictogram name="recurringPurchases" dimension="64x64" />
|
|
119
|
+
</Box>
|
|
120
|
+
}
|
|
121
|
+
mediaPlacement="end"
|
|
122
|
+
onDismissButtonPress={() => {}}
|
|
123
|
+
dismissButtonAccessibilityLabel="Dismiss"
|
|
124
|
+
/>
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
#### Feature Upsell
|
|
128
|
+
|
|
129
|
+
Ideal for highlighting Coinbase tools, innovative features, and unique functionalities. Choose from our palette of distinct colors to make your Feature Upsell stand out. Each color is carefully selected to grab attention while aligning with the specific nature of the feature being promoted.
|
|
130
|
+
|
|
131
|
+
```jsx
|
|
132
|
+
function FeatureUpsell() {
|
|
133
|
+
const { spectrum } = useTheme();
|
|
134
|
+
const image = (
|
|
135
|
+
<RemoteImage
|
|
136
|
+
accessibilityLabel="Feature illustration"
|
|
137
|
+
height={160}
|
|
138
|
+
resizeMode="cover"
|
|
139
|
+
shape="rectangle"
|
|
140
|
+
source={{ uri: 'https://cds.coinbase.com/img/feature.png' }}
|
|
141
|
+
/>
|
|
142
|
+
);
|
|
143
|
+
const cards = [
|
|
144
|
+
{ bg: `rgb(${spectrum.purple70})` },
|
|
145
|
+
{ bg: `rgb(${spectrum.teal50})` },
|
|
146
|
+
{ bg: `rgb(${spectrum.blue80})` },
|
|
147
|
+
{ bg: `rgb(${spectrum.indigo70})` },
|
|
148
|
+
];
|
|
149
|
+
return (
|
|
150
|
+
<VStack gap={2}>
|
|
151
|
+
{cards.map((card, i) => (
|
|
152
|
+
<MessagingCard
|
|
153
|
+
key={i}
|
|
154
|
+
type="upsell"
|
|
155
|
+
dangerouslySetBackground={card.bg}
|
|
156
|
+
title={
|
|
157
|
+
<Text color="fgInverse" font="headline">
|
|
158
|
+
Up to 3.29% APR on ETH
|
|
159
|
+
</Text>
|
|
160
|
+
}
|
|
161
|
+
description={
|
|
162
|
+
<Text font="label2" numberOfLines={3} color="fgInverse">
|
|
163
|
+
Earn staking rewards on ETH by holding it on Coinbase
|
|
164
|
+
</Text>
|
|
165
|
+
}
|
|
166
|
+
width={360}
|
|
167
|
+
action="Start earning"
|
|
168
|
+
onActionButtonPress={() => console.log('Action pressed!')}
|
|
169
|
+
media={image}
|
|
170
|
+
mediaPlacement="end"
|
|
171
|
+
onDismissButtonPress={() => {}}
|
|
172
|
+
dismissButtonAccessibilityLabel="Dismiss"
|
|
173
|
+
/>
|
|
174
|
+
))}
|
|
175
|
+
</VStack>
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
#### Community Upsell
|
|
181
|
+
|
|
182
|
+
Designed for community-focused messaging. Vibrant colors spark enthusiasm and encourage active participation, fostering a sense of community engagement.
|
|
183
|
+
|
|
184
|
+
```jsx
|
|
185
|
+
function CommunityUpsell() {
|
|
186
|
+
const { spectrum } = useTheme();
|
|
187
|
+
const cards = [
|
|
188
|
+
{ bg: `rgb(${spectrum.teal70})`, image: 'https://cds.coinbase.com/img/community.png' },
|
|
189
|
+
{ bg: `rgb(${spectrum.purple70})`, image: 'https://cds.coinbase.com/img/radial.png' },
|
|
190
|
+
];
|
|
191
|
+
return (
|
|
192
|
+
<VStack gap={2}>
|
|
193
|
+
{cards.map((card, i) => (
|
|
194
|
+
<MessagingCard
|
|
195
|
+
key={i}
|
|
196
|
+
type="upsell"
|
|
197
|
+
dangerouslySetBackground={card.bg}
|
|
198
|
+
title={
|
|
199
|
+
<Text color="fgInverse" font="headline">
|
|
200
|
+
Join the community
|
|
201
|
+
</Text>
|
|
202
|
+
}
|
|
203
|
+
description={
|
|
204
|
+
<Text font="label2" numberOfLines={3} color="fgInverse">
|
|
205
|
+
Chat with other devs in our Discord community
|
|
206
|
+
</Text>
|
|
207
|
+
}
|
|
208
|
+
width={360}
|
|
209
|
+
action="Join now"
|
|
210
|
+
onActionButtonPress={() => console.log('Action pressed!')}
|
|
211
|
+
media={
|
|
212
|
+
<RemoteImage
|
|
213
|
+
accessibilityLabel="Community illustration"
|
|
214
|
+
height={160}
|
|
215
|
+
resizeMode="cover"
|
|
216
|
+
shape="rectangle"
|
|
217
|
+
source={{ uri: card.image }}
|
|
218
|
+
/>
|
|
219
|
+
}
|
|
220
|
+
mediaPlacement="end"
|
|
221
|
+
onDismissButtonPress={() => {}}
|
|
222
|
+
dismissButtonAccessibilityLabel="Dismiss"
|
|
223
|
+
/>
|
|
224
|
+
))}
|
|
225
|
+
</VStack>
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
#### Product Upsell
|
|
231
|
+
|
|
232
|
+
Optimal for business products, security features, and functionalities that emphasize trust and reliability, such as Coinbase One and Coinbase Card. Blue and dark backgrounds symbolize stability, trustworthiness, and professionalism.
|
|
233
|
+
|
|
234
|
+
```jsx
|
|
235
|
+
function ProductUpsell() {
|
|
236
|
+
const { spectrum } = useTheme();
|
|
237
|
+
const cards = [
|
|
238
|
+
{
|
|
239
|
+
title: 'Coinbase One offer',
|
|
240
|
+
description: 'Use code NOV60 when you sign up for Coinbase One',
|
|
241
|
+
action: 'Get 60 days free',
|
|
242
|
+
bg: `rgb(${spectrum.blue80})`,
|
|
243
|
+
image: 'https://cds.coinbase.com/img/marketing.png',
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
title: 'Coinbase Card',
|
|
247
|
+
description: 'Spend USDC to get rewards with our Visa® debit card',
|
|
248
|
+
action: 'Get started',
|
|
249
|
+
bg: `rgb(${spectrum.gray100})`,
|
|
250
|
+
image: 'https://cds.coinbase.com/img/object.png',
|
|
251
|
+
},
|
|
252
|
+
];
|
|
253
|
+
return (
|
|
254
|
+
<VStack gap={2}>
|
|
255
|
+
{cards.map((card) => (
|
|
256
|
+
<MessagingCard
|
|
257
|
+
key={card.title}
|
|
258
|
+
type="upsell"
|
|
259
|
+
dangerouslySetBackground={card.bg}
|
|
260
|
+
title={
|
|
261
|
+
<Text color="fgInverse" font="headline">
|
|
262
|
+
{card.title}
|
|
263
|
+
</Text>
|
|
264
|
+
}
|
|
265
|
+
description={
|
|
266
|
+
<Text font="label2" numberOfLines={3} color="fgInverse">
|
|
267
|
+
{card.description}
|
|
268
|
+
</Text>
|
|
269
|
+
}
|
|
270
|
+
width={360}
|
|
271
|
+
action={card.action}
|
|
272
|
+
onActionButtonPress={() => console.log('Action pressed!')}
|
|
273
|
+
media={
|
|
274
|
+
<RemoteImage
|
|
275
|
+
accessibilityLabel="Product illustration"
|
|
276
|
+
height={160}
|
|
277
|
+
resizeMode="cover"
|
|
278
|
+
shape="rectangle"
|
|
279
|
+
source={{ uri: card.image }}
|
|
280
|
+
/>
|
|
281
|
+
}
|
|
282
|
+
mediaPlacement="end"
|
|
283
|
+
onDismissButtonPress={() => {}}
|
|
284
|
+
dismissButtonAccessibilityLabel="Dismiss"
|
|
285
|
+
/>
|
|
286
|
+
))}
|
|
287
|
+
</VStack>
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
#### News Upsell
|
|
293
|
+
|
|
294
|
+
Specifically tailored for company announcements and policy updates. Its design ensures that important information is conveyed clearly and prominently, ensuring users stay well-informed about the latest developments.
|
|
295
|
+
|
|
296
|
+
```jsx
|
|
297
|
+
function NewsUpsell() {
|
|
298
|
+
const { spectrum } = useTheme();
|
|
299
|
+
const cards = [{ bg: `rgb(${spectrum.gray100})` }, { bg: `rgb(${spectrum.indigo70})` }];
|
|
300
|
+
return (
|
|
301
|
+
<VStack gap={2}>
|
|
302
|
+
{cards.map((card, i) => (
|
|
303
|
+
<MessagingCard
|
|
304
|
+
key={i}
|
|
305
|
+
type="upsell"
|
|
306
|
+
dangerouslySetBackground={card.bg}
|
|
307
|
+
title={
|
|
308
|
+
<Text color="fgInverse" font="headline">
|
|
309
|
+
Help defend crypto in America
|
|
310
|
+
</Text>
|
|
311
|
+
}
|
|
312
|
+
description={
|
|
313
|
+
<Text font="label2" numberOfLines={3} color="fgInverse">
|
|
314
|
+
Help us keep crypto in America with a single click
|
|
315
|
+
</Text>
|
|
316
|
+
}
|
|
317
|
+
width={360}
|
|
318
|
+
action="Join the fight"
|
|
319
|
+
onActionButtonPress={() => console.log('Action pressed!')}
|
|
320
|
+
media={
|
|
321
|
+
<RemoteImage
|
|
322
|
+
accessibilityLabel="Place illustration"
|
|
323
|
+
height={160}
|
|
324
|
+
resizeMode="cover"
|
|
325
|
+
shape="rectangle"
|
|
326
|
+
source={{ uri: 'https://cds.coinbase.com/img/place.png' }}
|
|
327
|
+
/>
|
|
328
|
+
}
|
|
329
|
+
mediaPlacement="end"
|
|
330
|
+
onDismissButtonPress={() => {}}
|
|
331
|
+
dismissButtonAccessibilityLabel="Dismiss"
|
|
332
|
+
/>
|
|
333
|
+
))}
|
|
334
|
+
</VStack>
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Nudge Card Style
|
|
340
|
+
|
|
341
|
+
Use `type="nudge"` for gentle reminders or secondary options. Nudge cards use the alternate background and blend more seamlessly with the page. Pair them with Pictogram illustrations and transparent buttons.
|
|
342
|
+
|
|
343
|
+
```jsx
|
|
344
|
+
<VStack gap={2}>
|
|
345
|
+
<MessagingCard
|
|
346
|
+
type="nudge"
|
|
347
|
+
title="Earn more crypto"
|
|
348
|
+
description="You've got unstaked crypto. Stake it now to earn more."
|
|
349
|
+
width={360}
|
|
350
|
+
action="Start earning"
|
|
351
|
+
onActionButtonPress={() => console.log('Action pressed!')}
|
|
352
|
+
media={<Pictogram dimension="64x64" name="key" />}
|
|
353
|
+
mediaPlacement="end"
|
|
354
|
+
onDismissButtonPress={() => {}}
|
|
355
|
+
dismissButtonAccessibilityLabel="Dismiss"
|
|
356
|
+
/>
|
|
357
|
+
<MessagingCard
|
|
358
|
+
type="nudge"
|
|
359
|
+
title="Derivatives Trading"
|
|
360
|
+
description="Derivative Exchange is available for all users"
|
|
361
|
+
width={360}
|
|
362
|
+
media={<Pictogram dimension="48x48" name="derivativesNavigation" />}
|
|
363
|
+
mediaPlacement="end"
|
|
364
|
+
/>
|
|
365
|
+
</VStack>
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### Features
|
|
369
|
+
|
|
370
|
+
#### Dismissible Cards
|
|
371
|
+
|
|
372
|
+
Use `onDismissButtonPress` to add a dismiss button.
|
|
373
|
+
|
|
374
|
+
```jsx
|
|
375
|
+
function DismissibleCards() {
|
|
376
|
+
const { spectrum } = useTheme();
|
|
377
|
+
return (
|
|
378
|
+
<VStack gap={2}>
|
|
379
|
+
<MessagingCard
|
|
380
|
+
type="upsell"
|
|
381
|
+
dangerouslySetBackground={`rgb(${spectrum.teal70})`}
|
|
382
|
+
title="Dismissible Upsell"
|
|
383
|
+
description="Upsell card with dismiss button"
|
|
384
|
+
width={320}
|
|
385
|
+
media={
|
|
386
|
+
<RemoteImage
|
|
387
|
+
accessibilityLabel="Community illustration"
|
|
388
|
+
height={160}
|
|
389
|
+
resizeMode="cover"
|
|
390
|
+
shape="rectangle"
|
|
391
|
+
source={{ uri: 'https://cds.coinbase.com/img/community.png' }}
|
|
392
|
+
/>
|
|
393
|
+
}
|
|
394
|
+
mediaPlacement="end"
|
|
395
|
+
onDismissButtonPress={() => console.log('Card dismissed!')}
|
|
396
|
+
dismissButtonAccessibilityLabel="Close card"
|
|
397
|
+
/>
|
|
398
|
+
<MessagingCard
|
|
399
|
+
type="nudge"
|
|
400
|
+
title="Dismissible Nudge"
|
|
401
|
+
description="Nudge card with dismiss button"
|
|
402
|
+
width={320}
|
|
403
|
+
media={<Pictogram dimension="48x48" name="baseStar" />}
|
|
404
|
+
mediaPlacement="end"
|
|
405
|
+
onDismissButtonPress={() => console.log('Card dismissed!')}
|
|
406
|
+
dismissButtonAccessibilityLabel="Close card"
|
|
407
|
+
/>
|
|
408
|
+
</VStack>
|
|
409
|
+
);
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
#### Tags
|
|
414
|
+
|
|
415
|
+
Use `tag` to add a label badge.
|
|
416
|
+
|
|
417
|
+
```jsx
|
|
418
|
+
<VStack gap={2}>
|
|
419
|
+
<MessagingCard
|
|
420
|
+
type="upsell"
|
|
421
|
+
title="Tagged Upsell"
|
|
422
|
+
description="Upsell card with a tag"
|
|
423
|
+
width={320}
|
|
424
|
+
tag="New"
|
|
425
|
+
media={
|
|
426
|
+
<RemoteImage
|
|
427
|
+
accessibilityLabel="Place illustration"
|
|
428
|
+
height={160}
|
|
429
|
+
resizeMode="cover"
|
|
430
|
+
shape="rectangle"
|
|
431
|
+
source={{ uri: 'https://cds.coinbase.com/img/place.png' }}
|
|
432
|
+
/>
|
|
433
|
+
}
|
|
434
|
+
mediaPlacement="end"
|
|
435
|
+
/>
|
|
436
|
+
<MessagingCard
|
|
437
|
+
type="nudge"
|
|
438
|
+
title="Tagged Nudge"
|
|
439
|
+
description="Nudge card with a tag"
|
|
440
|
+
width={320}
|
|
441
|
+
tag="New"
|
|
442
|
+
media={<Pictogram dimension="48x48" name="key" />}
|
|
443
|
+
mediaPlacement="end"
|
|
444
|
+
/>
|
|
445
|
+
</VStack>
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
#### Actions
|
|
449
|
+
|
|
450
|
+
Use the `action` prop to add an action button. Pass a string to render a default button with `onActionButtonPress`, or pass a custom React element.
|
|
451
|
+
|
|
452
|
+
```jsx
|
|
453
|
+
<VStack gap={2}>
|
|
454
|
+
<MessagingCard
|
|
455
|
+
type="upsell"
|
|
456
|
+
title="Upsell with Action"
|
|
457
|
+
description="Upsell card with action button"
|
|
458
|
+
width={320}
|
|
459
|
+
action="Action"
|
|
460
|
+
onActionButtonPress={() => console.log('Action pressed!')}
|
|
461
|
+
media={
|
|
462
|
+
<RemoteImage
|
|
463
|
+
accessibilityLabel="Feature illustration"
|
|
464
|
+
height={160}
|
|
465
|
+
resizeMode="cover"
|
|
466
|
+
shape="rectangle"
|
|
467
|
+
source={{ uri: 'https://cds.coinbase.com/img/feature.png' }}
|
|
468
|
+
/>
|
|
469
|
+
}
|
|
470
|
+
mediaPlacement="end"
|
|
471
|
+
/>
|
|
472
|
+
<MessagingCard
|
|
473
|
+
type="nudge"
|
|
474
|
+
title="Nudge with Action"
|
|
475
|
+
description="Nudge card with action button"
|
|
476
|
+
width={320}
|
|
477
|
+
action="Learn More"
|
|
478
|
+
onActionButtonPress={() => console.log('Action pressed!')}
|
|
479
|
+
media={<Pictogram dimension="64x64" name="wallet" />}
|
|
480
|
+
mediaPlacement="end"
|
|
481
|
+
/>
|
|
482
|
+
</VStack>
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
#### Complete Example
|
|
486
|
+
|
|
487
|
+
Combine all features in a complete card.
|
|
488
|
+
|
|
489
|
+
```jsx
|
|
490
|
+
<VStack gap={2}>
|
|
491
|
+
<MessagingCard
|
|
492
|
+
type="upsell"
|
|
493
|
+
title="Complete Upsell Card"
|
|
494
|
+
description="Complete upsell card with all features"
|
|
495
|
+
width={360}
|
|
496
|
+
tag="New"
|
|
497
|
+
action="Get Started"
|
|
498
|
+
onActionButtonPress={() => console.log('Action pressed!')}
|
|
499
|
+
onDismissButtonPress={() => console.log('Dismissed')}
|
|
500
|
+
dismissButtonAccessibilityLabel="Dismiss"
|
|
501
|
+
media={
|
|
502
|
+
<RemoteImage
|
|
503
|
+
accessibilityLabel="Marketing illustration"
|
|
504
|
+
height={184}
|
|
505
|
+
resizeMode="cover"
|
|
506
|
+
shape="rectangle"
|
|
507
|
+
source={{ uri: 'https://cds.coinbase.com/img/marketing.png' }}
|
|
508
|
+
/>
|
|
509
|
+
}
|
|
510
|
+
mediaPlacement="end"
|
|
511
|
+
/>
|
|
512
|
+
<MessagingCard
|
|
513
|
+
type="nudge"
|
|
514
|
+
title="Complete Nudge Card"
|
|
515
|
+
description="Complete nudge card with all features"
|
|
516
|
+
width={360}
|
|
517
|
+
tag="New"
|
|
518
|
+
action="Learn More"
|
|
519
|
+
onActionButtonPress={() => console.log('Action pressed!')}
|
|
520
|
+
onDismissButtonPress={() => console.log('Dismissed')}
|
|
521
|
+
dismissButtonAccessibilityLabel="Dismiss"
|
|
522
|
+
media={<Pictogram dimension="64x64" name="giftbox" />}
|
|
523
|
+
mediaPlacement="end"
|
|
524
|
+
/>
|
|
525
|
+
</VStack>
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
### Interactive Dismissible List
|
|
529
|
+
|
|
530
|
+
This example shows a list of cards that can be dismissed interactively. Press the dismiss button to remove cards from the list.
|
|
531
|
+
|
|
532
|
+
```jsx
|
|
533
|
+
function DismissibleCardsList() {
|
|
534
|
+
const { spectrum } = useTheme();
|
|
535
|
+
const cards = [
|
|
536
|
+
{
|
|
537
|
+
id: '1',
|
|
538
|
+
title: 'Welcome to Coinbase',
|
|
539
|
+
description: 'Get started with your crypto journey',
|
|
540
|
+
type: 'upsell',
|
|
541
|
+
},
|
|
542
|
+
{
|
|
543
|
+
id: '2',
|
|
544
|
+
title: 'Complete your profile',
|
|
545
|
+
description: 'Add your details to unlock more features',
|
|
546
|
+
type: 'nudge',
|
|
547
|
+
},
|
|
548
|
+
{
|
|
549
|
+
id: '3',
|
|
550
|
+
title: 'Enable notifications',
|
|
551
|
+
description: 'Stay updated on market movements',
|
|
552
|
+
type: 'upsell',
|
|
553
|
+
},
|
|
554
|
+
{
|
|
555
|
+
id: '4',
|
|
556
|
+
title: 'Invite friends',
|
|
557
|
+
description: 'Earn rewards when friends join',
|
|
558
|
+
type: 'nudge',
|
|
559
|
+
},
|
|
560
|
+
];
|
|
561
|
+
|
|
562
|
+
const [dismissedIds, setDismissedIds] = useState(new Set());
|
|
563
|
+
|
|
564
|
+
const handleDismiss = (id) => {
|
|
565
|
+
setDismissedIds((prev) => new Set(prev).add(id));
|
|
566
|
+
};
|
|
567
|
+
|
|
568
|
+
const handleReset = () => {
|
|
569
|
+
setDismissedIds(new Set());
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
const visibleCards = cards.filter((card) => !dismissedIds.has(card.id));
|
|
573
|
+
|
|
574
|
+
return (
|
|
575
|
+
<VStack gap={2}>
|
|
576
|
+
<VStack gap={2}>
|
|
577
|
+
{visibleCards.map((card) => (
|
|
578
|
+
<MessagingCard
|
|
579
|
+
key={card.id}
|
|
580
|
+
type={card.type}
|
|
581
|
+
dangerouslySetBackground={
|
|
582
|
+
card.type === 'upsell' ? `rgb(${spectrum.gray100})` : undefined
|
|
583
|
+
}
|
|
584
|
+
title={card.title}
|
|
585
|
+
description={card.description}
|
|
586
|
+
media={
|
|
587
|
+
card.type === 'upsell' ? (
|
|
588
|
+
<RemoteImage
|
|
589
|
+
accessibilityLabel="Promotional illustration"
|
|
590
|
+
height={160}
|
|
591
|
+
resizeMode="cover"
|
|
592
|
+
shape="rectangle"
|
|
593
|
+
source={{ uri: 'https://cds.coinbase.com/img/object.png' }}
|
|
594
|
+
width={80}
|
|
595
|
+
/>
|
|
596
|
+
) : (
|
|
597
|
+
<Pictogram dimension="48x48" name="addToWatchlist" />
|
|
598
|
+
)
|
|
599
|
+
}
|
|
600
|
+
mediaPlacement="end"
|
|
601
|
+
onDismissButtonPress={() => handleDismiss(card.id)}
|
|
602
|
+
dismissButtonAccessibilityLabel={`Dismiss ${card.title}`}
|
|
603
|
+
/>
|
|
604
|
+
))}
|
|
605
|
+
{visibleCards.length === 0 && (
|
|
606
|
+
<Text color="fgNegative" font="label1">
|
|
607
|
+
All cards dismissed!
|
|
608
|
+
</Text>
|
|
609
|
+
)}
|
|
610
|
+
</VStack>
|
|
611
|
+
<Button onPress={handleReset} variant="tertiary">
|
|
612
|
+
Reset Cards
|
|
613
|
+
</Button>
|
|
614
|
+
</VStack>
|
|
615
|
+
);
|
|
616
|
+
}
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
### Interactive Cards
|
|
620
|
+
|
|
621
|
+
Use `renderAsPressable` with `onPress` for interactive cards.
|
|
622
|
+
|
|
623
|
+
```jsx
|
|
624
|
+
function InteractiveCards() {
|
|
625
|
+
const { spectrum } = useTheme();
|
|
626
|
+
return (
|
|
627
|
+
<VStack gap={2}>
|
|
628
|
+
<MessagingCard
|
|
629
|
+
renderAsPressable
|
|
630
|
+
onPress={() => console.log('Card pressed!')}
|
|
631
|
+
type="upsell"
|
|
632
|
+
dangerouslySetBackground={`rgb(${spectrum.teal70})`}
|
|
633
|
+
title="Interactive Upsell"
|
|
634
|
+
description="Tap to interact"
|
|
635
|
+
width={320}
|
|
636
|
+
media={
|
|
637
|
+
<RemoteImage
|
|
638
|
+
accessibilityLabel="Community illustration"
|
|
639
|
+
height={160}
|
|
640
|
+
resizeMode="cover"
|
|
641
|
+
shape="rectangle"
|
|
642
|
+
source={{ uri: 'https://cds.coinbase.com/img/community.png' }}
|
|
643
|
+
/>
|
|
644
|
+
}
|
|
645
|
+
mediaPlacement="end"
|
|
646
|
+
/>
|
|
647
|
+
<MessagingCard
|
|
648
|
+
renderAsPressable
|
|
649
|
+
onPress={() => console.log('Card pressed!')}
|
|
650
|
+
type="nudge"
|
|
651
|
+
title="Interactive Nudge"
|
|
652
|
+
description="Tap to interact"
|
|
653
|
+
width={320}
|
|
654
|
+
media={<Pictogram dimension="48x48" name="baseRocket" />}
|
|
655
|
+
mediaPlacement="end"
|
|
656
|
+
/>
|
|
657
|
+
</VStack>
|
|
658
|
+
);
|
|
659
|
+
}
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
### Custom Content
|
|
663
|
+
|
|
664
|
+
Use React nodes for custom styled content.
|
|
665
|
+
|
|
666
|
+
```jsx
|
|
667
|
+
<VStack gap={2}>
|
|
668
|
+
<MessagingCard
|
|
669
|
+
type="upsell"
|
|
670
|
+
title="This is a very long title text that demonstrates text wrapping"
|
|
671
|
+
description="This is a very long description text that demonstrates how the card handles longer content and wraps appropriately within the card layout"
|
|
672
|
+
width={320}
|
|
673
|
+
media={
|
|
674
|
+
<RemoteImage
|
|
675
|
+
accessibilityLabel="Place illustration"
|
|
676
|
+
height={160}
|
|
677
|
+
resizeMode="cover"
|
|
678
|
+
shape="rectangle"
|
|
679
|
+
source={{ uri: 'https://cds.coinbase.com/img/place.png' }}
|
|
680
|
+
/>
|
|
681
|
+
}
|
|
682
|
+
mediaPlacement="end"
|
|
683
|
+
/>
|
|
684
|
+
<MessagingCard
|
|
685
|
+
type="upsell"
|
|
686
|
+
width={320}
|
|
687
|
+
title={
|
|
688
|
+
<Text color="fgInverse" font="title3">
|
|
689
|
+
Custom Title
|
|
690
|
+
</Text>
|
|
691
|
+
}
|
|
692
|
+
tag={
|
|
693
|
+
<Text color="fgInverse" font="label2">
|
|
694
|
+
Custom Tag
|
|
695
|
+
</Text>
|
|
696
|
+
}
|
|
697
|
+
description={
|
|
698
|
+
<Text color="fgInverse" font="label2">
|
|
699
|
+
Custom description with styled text
|
|
700
|
+
</Text>
|
|
701
|
+
}
|
|
702
|
+
media={
|
|
703
|
+
<RemoteImage
|
|
704
|
+
accessibilityLabel="Collection illustration"
|
|
705
|
+
height={160}
|
|
706
|
+
resizeMode="cover"
|
|
707
|
+
shape="rectangle"
|
|
708
|
+
source={{ uri: 'https://cds.coinbase.com/img/collection.png' }}
|
|
709
|
+
/>
|
|
710
|
+
}
|
|
711
|
+
mediaPlacement="end"
|
|
712
|
+
/>
|
|
713
|
+
</VStack>
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
### Multiple Cards
|
|
717
|
+
|
|
718
|
+
Display multiple cards in a carousel.
|
|
719
|
+
|
|
720
|
+
```jsx
|
|
721
|
+
function MultipleCards() {
|
|
722
|
+
const { spectrum } = useTheme();
|
|
723
|
+
return (
|
|
724
|
+
<Carousel styles={{ carousel: { gap: 16 } }}>
|
|
725
|
+
<CarouselItem id="card1">
|
|
726
|
+
<MessagingCard
|
|
727
|
+
type="upsell"
|
|
728
|
+
title="Card 1"
|
|
729
|
+
description="Non-interactive card"
|
|
730
|
+
width={320}
|
|
731
|
+
media={
|
|
732
|
+
<RemoteImage
|
|
733
|
+
accessibilityLabel="Marketing illustration"
|
|
734
|
+
height={160}
|
|
735
|
+
resizeMode="cover"
|
|
736
|
+
shape="rectangle"
|
|
737
|
+
source={{ uri: 'https://cds.coinbase.com/img/marketing.png' }}
|
|
738
|
+
/>
|
|
739
|
+
}
|
|
740
|
+
mediaPlacement="end"
|
|
741
|
+
/>
|
|
742
|
+
</CarouselItem>
|
|
743
|
+
<CarouselItem id="card2">
|
|
744
|
+
<MessagingCard
|
|
745
|
+
renderAsPressable
|
|
746
|
+
onPress={() => {}}
|
|
747
|
+
type="nudge"
|
|
748
|
+
title="Card 2"
|
|
749
|
+
description="Interactive card"
|
|
750
|
+
tag="Tap"
|
|
751
|
+
media={<Pictogram dimension="64x64" name="addToWatchlist" />}
|
|
752
|
+
mediaPlacement="end"
|
|
753
|
+
/>
|
|
754
|
+
</CarouselItem>
|
|
755
|
+
<CarouselItem id="card3">
|
|
756
|
+
<MessagingCard
|
|
757
|
+
renderAsPressable
|
|
758
|
+
onPress={() => console.log('clicked')}
|
|
759
|
+
type="upsell"
|
|
760
|
+
dangerouslySetBackground={`rgb(${spectrum.purple70})`}
|
|
761
|
+
title="Card 3"
|
|
762
|
+
description="Card with onPress handler"
|
|
763
|
+
tag="Action"
|
|
764
|
+
media={
|
|
765
|
+
<RemoteImage
|
|
766
|
+
accessibilityLabel="Radial design"
|
|
767
|
+
height={160}
|
|
768
|
+
resizeMode="cover"
|
|
769
|
+
shape="rectangle"
|
|
770
|
+
source={{ uri: 'https://cds.coinbase.com/img/radial.png' }}
|
|
771
|
+
/>
|
|
772
|
+
}
|
|
773
|
+
mediaPlacement="end"
|
|
774
|
+
/>
|
|
775
|
+
</CarouselItem>
|
|
776
|
+
</Carousel>
|
|
777
|
+
);
|
|
778
|
+
}
|
|
779
|
+
```
|
|
780
|
+
|
|
781
|
+
### Accessibility
|
|
782
|
+
|
|
783
|
+
#### Interactive Cards with Dismiss Button
|
|
784
|
+
|
|
785
|
+
When you need both `onDismissButtonPress` and want the entire card to be pressable, you should handle accessibility carefully to avoid nested interactive elements.
|
|
786
|
+
|
|
787
|
+
**The Problem**: If you use `renderAsPressable` with `onPress` and also have `onDismissButtonPress`, the card becomes a pressable containing another pressable (the dismiss button). This creates accessibility issues for screen reader users.
|
|
788
|
+
|
|
789
|
+
**The Solution**: Mark the card as non-accessible and add a separate action button inside the card with the same action. This allows:
|
|
790
|
+
|
|
791
|
+
- Regular users to tap anywhere on the card
|
|
792
|
+
- Screen reader users to focus on individual interactive elements (action button + dismiss button)
|
|
793
|
+
|
|
794
|
+
```jsx
|
|
795
|
+
<MessagingCard
|
|
796
|
+
renderAsPressable
|
|
797
|
+
accessible={false}
|
|
798
|
+
onPress={() => console.log('Card pressed - navigating...')}
|
|
799
|
+
type="upsell"
|
|
800
|
+
title="Accessible Interactive Card"
|
|
801
|
+
description="Card with both dismiss and card-level action"
|
|
802
|
+
action={
|
|
803
|
+
<Button
|
|
804
|
+
compact
|
|
805
|
+
variant="secondary"
|
|
806
|
+
onPress={() => console.log('Button pressed - navigating...')}
|
|
807
|
+
>
|
|
808
|
+
Learn More
|
|
809
|
+
</Button>
|
|
810
|
+
}
|
|
811
|
+
onDismissButtonPress={() => console.log('Dismissed')}
|
|
812
|
+
dismissButtonAccessibilityLabel="Dismiss promotion"
|
|
813
|
+
media={
|
|
814
|
+
<RemoteImage
|
|
815
|
+
accessibilityLabel="Feature illustration"
|
|
816
|
+
height={160}
|
|
817
|
+
resizeMode="cover"
|
|
818
|
+
shape="rectangle"
|
|
819
|
+
source={{ uri: 'https://cds.coinbase.com/img/feature.png' }}
|
|
820
|
+
width={100}
|
|
821
|
+
/>
|
|
822
|
+
}
|
|
823
|
+
mediaPlacement="end"
|
|
824
|
+
/>
|
|
825
|
+
```
|
|
826
|
+
|
|
827
|
+
**Key points:**
|
|
828
|
+
|
|
829
|
+
- Set `accessible={false}` to remove the card from the accessibility tree
|
|
830
|
+
- Add a `Button` in `actionButton` with the same `onPress` handler for screen reader users
|
|
831
|
+
- Use `actionButtonAccessibilityLabel` and `dismissButtonAccessibilityLabel` to add or override the accessibility label for the action and dismiss buttons
|
|
832
|
+
|
|
833
|
+
#### Color Contrast
|
|
834
|
+
|
|
835
|
+
MessagingCard supports custom backgrounds via `background` and `dangerouslySetBackground` props. When using custom background colors, ensure sufficient color contrast between text and background:
|
|
836
|
+
|
|
837
|
+
- Use `fgInverse` text color with dark backgrounds (e.g., `accentBoldPurple`, `bgInverse`)
|
|
838
|
+
- Use `fg` text color with light backgrounds (e.g., `bgPrimaryWash`, `bgAlternate`)
|
|
839
|
+
- Verify your color combinations meet WCAG AA guidelines (4.5:1 for normal text)
|
|
840
|
+
|
|
841
|
+
### Migration from Deprecated Components
|
|
842
|
+
|
|
843
|
+
#### Migrating from NudgeCard
|
|
844
|
+
|
|
845
|
+
Replace `NudgeCard` with `MessagingCard` using `type="nudge"`.
|
|
846
|
+
|
|
847
|
+
```jsx
|
|
848
|
+
// Before
|
|
849
|
+
<NudgeCard
|
|
850
|
+
title="Title"
|
|
851
|
+
description="Description"
|
|
852
|
+
pictogram="addToWatchlist"
|
|
853
|
+
action="Learn more"
|
|
854
|
+
onActionPress={handleAction}
|
|
855
|
+
onDismissPress={handleDismiss}
|
|
856
|
+
/>
|
|
857
|
+
|
|
858
|
+
// After
|
|
859
|
+
<MessagingCard
|
|
860
|
+
type="nudge"
|
|
861
|
+
title="Title"
|
|
862
|
+
description="Description"
|
|
863
|
+
media={<Pictogram dimension="64x64" name="addToWatchlist" />}
|
|
864
|
+
action="Learn more"
|
|
865
|
+
onActionButtonPress={handleAction}
|
|
866
|
+
onDismissButtonPress={handleDismiss}
|
|
867
|
+
mediaPlacement="end"
|
|
868
|
+
/>
|
|
869
|
+
```
|
|
870
|
+
|
|
871
|
+
#### Migrating from UpsellCard
|
|
872
|
+
|
|
873
|
+
Replace `UpsellCard` with `MessagingCard` using `type="upsell"`.
|
|
874
|
+
|
|
875
|
+
```jsx
|
|
876
|
+
// Before
|
|
877
|
+
<UpsellCard
|
|
878
|
+
title="Title"
|
|
879
|
+
description="Description"
|
|
880
|
+
media={<RemoteImage ... />}
|
|
881
|
+
action="Get Started"
|
|
882
|
+
onActionPress={handleAction}
|
|
883
|
+
onDismissPress={handleDismiss}
|
|
884
|
+
/>
|
|
885
|
+
|
|
886
|
+
// After
|
|
887
|
+
<MessagingCard
|
|
888
|
+
type="upsell"
|
|
889
|
+
title="Title"
|
|
890
|
+
description="Description"
|
|
891
|
+
media={<RemoteImage ... />}
|
|
892
|
+
action="Get Started"
|
|
893
|
+
onActionButtonPress={handleAction}
|
|
894
|
+
onDismissButtonPress={handleDismiss}
|
|
895
|
+
mediaPlacement="end"
|
|
896
|
+
/>
|
|
897
|
+
```
|
|
898
|
+
|
|
899
|
+
## Props
|
|
900
|
+
|
|
901
|
+
| Prop | Type | Required | Default | Description |
|
|
902
|
+
| --- | --- | --- | --- | --- |
|
|
903
|
+
| `mediaPlacement` | `end \| start` | Yes | `'end'` | Placement of the media content relative to the text content. |
|
|
904
|
+
| `type` | `upsell \| nudge` | Yes | `-` | Type of messaging card. Determines background color and text color. |
|
|
905
|
+
| `action` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | Action element to display. Can be a string (renders as default button) or a custom ReactNode. When a string is provided, use onActionButtonPress to handle presses. |
|
|
906
|
+
| `actionButtonAccessibilityLabel` | `string` | No | `action value (when action is a string)` | Accessibility label for the action button. Only used when action is a string. |
|
|
907
|
+
| `alignContent` | `flex-start \| flex-end \| center \| stretch \| space-between \| space-around \| space-evenly` | No | `-` | - |
|
|
908
|
+
| `alignItems` | `flex-start \| flex-end \| center \| stretch \| baseline` | No | `-` | - |
|
|
909
|
+
| `alignSelf` | `auto \| FlexAlignType` | No | `-` | - |
|
|
910
|
+
| `aspectRatio` | `string \| number` | No | `-` | - |
|
|
911
|
+
| `background` | `currentColor \| fg \| fgMuted \| fgInverse \| fgPrimary \| fgWarning \| fgPositive \| fgNegative \| bg \| bgAlternate \| bgInverse \| bgOverlay \| bgElevation1 \| bgElevation2 \| bgPrimary \| bgPrimaryWash \| bgSecondary \| bgTertiary \| bgSecondaryWash \| bgNegative \| bgNegativeWash \| bgPositive \| bgPositiveWash \| bgWarning \| bgWarningWash \| bgLine \| bgLineHeavy \| bgLineInverse \| bgLinePrimary \| bgLinePrimarySubtle \| accentSubtleRed \| accentBoldRed \| accentSubtleGreen \| accentBoldGreen \| accentSubtleBlue \| accentBoldBlue \| accentSubtlePurple \| accentBoldPurple \| accentSubtleYellow \| accentBoldYellow \| accentSubtleGray \| accentBoldGray \| transparent` | No | `-` | Background color of the overlay (element being interacted with). |
|
|
912
|
+
| `blendStyles` | `InteractableBlendStyles` | No | `-` | - |
|
|
913
|
+
| `block` | `boolean` | No | `-` | Set element to block and expand to 100% width. |
|
|
914
|
+
| `borderBottomLeftRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
|
|
915
|
+
| `borderBottomRightRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
|
|
916
|
+
| `borderBottomWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
|
|
917
|
+
| `borderColor` | `currentColor \| fg \| fgMuted \| fgInverse \| fgPrimary \| fgWarning \| fgPositive \| fgNegative \| bg \| bgAlternate \| bgInverse \| bgOverlay \| bgElevation1 \| bgElevation2 \| bgPrimary \| bgPrimaryWash \| bgSecondary \| bgTertiary \| bgSecondaryWash \| bgNegative \| bgNegativeWash \| bgPositive \| bgPositiveWash \| bgWarning \| bgWarningWash \| bgLine \| bgLineHeavy \| bgLineInverse \| bgLinePrimary \| bgLinePrimarySubtle \| accentSubtleRed \| accentBoldRed \| accentSubtleGreen \| accentBoldGreen \| accentSubtleBlue \| accentBoldBlue \| accentSubtlePurple \| accentBoldPurple \| accentSubtleYellow \| accentBoldYellow \| accentSubtleGray \| accentBoldGray \| transparent` | No | `-` | - |
|
|
918
|
+
| `borderEndWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
|
|
919
|
+
| `borderRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
|
|
920
|
+
| `borderStartWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
|
|
921
|
+
| `borderTopLeftRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
|
|
922
|
+
| `borderTopRightRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
|
|
923
|
+
| `borderTopWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
|
|
924
|
+
| `borderWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
|
|
925
|
+
| `bordered` | `boolean` | No | `-` | Add a border around all sides of the box. |
|
|
926
|
+
| `borderedBottom` | `boolean` | No | `-` | Add a border to the bottom side of the box. |
|
|
927
|
+
| `borderedEnd` | `boolean` | No | `-` | Add a border to the trailing side of the box. |
|
|
928
|
+
| `borderedHorizontal` | `boolean` | No | `-` | Add a border to the leading and trailing sides of the box. |
|
|
929
|
+
| `borderedStart` | `boolean` | No | `-` | Add a border to the leading side of the box. |
|
|
930
|
+
| `borderedTop` | `boolean` | No | `-` | Add a border to the top side of the box. |
|
|
931
|
+
| `borderedVertical` | `boolean` | No | `-` | Add a border to the top and bottom sides of the box. |
|
|
932
|
+
| `bottom` | `string \| number` | No | `-` | - |
|
|
933
|
+
| `color` | `currentColor \| fg \| fgMuted \| fgInverse \| fgPrimary \| fgWarning \| fgPositive \| fgNegative \| bg \| bgAlternate \| bgInverse \| bgOverlay \| bgElevation1 \| bgElevation2 \| bgPrimary \| bgPrimaryWash \| bgSecondary \| bgTertiary \| bgSecondaryWash \| bgNegative \| bgNegativeWash \| bgPositive \| bgPositiveWash \| bgWarning \| bgWarningWash \| bgLine \| bgLineHeavy \| bgLineInverse \| bgLinePrimary \| bgLinePrimarySubtle \| accentSubtleRed \| accentBoldRed \| accentSubtleGreen \| accentBoldGreen \| accentSubtleBlue \| accentBoldBlue \| accentSubtlePurple \| accentBoldPurple \| accentSubtleYellow \| accentBoldYellow \| accentSubtleGray \| accentBoldGray \| transparent` | No | `-` | - |
|
|
934
|
+
| `columnGap` | `0 \| 1 \| 2 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10` | No | `-` | - |
|
|
935
|
+
| `contentStyle` | `null \| false \| ViewStyle \| RegisteredStyle<ViewStyle> \| RecursiveArray<ViewStyle \| Falsy \| RegisteredStyle<ViewStyle>>` | No | `-` | Apply animated styles to the inner container. |
|
|
936
|
+
| `dangerouslySetBackground` | `string` | No | `-` | - |
|
|
937
|
+
| `debounceTime` | `number` | No | `500` | The amount of time to wait (in milliseconds) before invoking the debounced function. This prop is used in conjunction with the disableDebounce prop. The debounce function is configured to be invoked as soon as its called, but subsequent calls within the debounceTime period will be ignored. |
|
|
938
|
+
| `description` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | Text or React node to display as the card description. Use a Text component to override default color and font. |
|
|
939
|
+
| `disableDebounce` | `boolean` | No | `-` | React Native is historically trash at debouncing touch events. This can cause a lot of unwanted behavior such as double navigations where we push a screen onto the stack 2 times. Debouncing the event 500 miliseconds, but taking the leading event prevents this effect and the accidental double-tap. |
|
|
940
|
+
| `disabled` | `boolean` | No | `-` | Is the element currently disabled. Whether the press behavior is disabled. |
|
|
941
|
+
| `dismissButton` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | React node to display as the dismiss button. When provided, this will be rendered instead of the default dismiss button. |
|
|
942
|
+
| `dismissButtonAccessibilityLabel` | `string` | No | `'Dismiss {title}' when title is a string, otherwise 'Dismiss card'` | Accessibility label for the dismiss button. |
|
|
943
|
+
| `display` | `flex \| none` | No | `-` | - |
|
|
944
|
+
| `elevation` | `0 \| 1 \| 2` | No | `-` | Determines box shadow styles. Parent should have overflow set to visible to ensure styles are not clipped. Is the element elevated. |
|
|
945
|
+
| `feedback` | `none \| light \| normal \| heavy` | No | `none` | Haptic feedback to trigger when being pressed. |
|
|
946
|
+
| `flexBasis` | `string \| number` | No | `-` | - |
|
|
947
|
+
| `flexDirection` | `row \| column \| row-reverse \| column-reverse` | No | `-` | - |
|
|
948
|
+
| `flexGrow` | `number` | No | `-` | - |
|
|
949
|
+
| `flexShrink` | `number` | No | `-` | - |
|
|
950
|
+
| `flexWrap` | `wrap \| nowrap \| wrap-reverse` | No | `-` | - |
|
|
951
|
+
| `font` | `inherit \| FontFamily` | No | `-` | - |
|
|
952
|
+
| `fontFamily` | `inherit \| FontFamily` | No | `-` | - |
|
|
953
|
+
| `fontSize` | `inherit \| FontSize` | No | `-` | - |
|
|
954
|
+
| `fontWeight` | `inherit \| FontWeight` | No | `-` | - |
|
|
955
|
+
| `gap` | `0 \| 1 \| 2 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10` | No | `-` | - |
|
|
956
|
+
| `height` | `string \| number` | No | `-` | - |
|
|
957
|
+
| `justifyContent` | `flex-start \| flex-end \| center \| space-between \| space-around \| space-evenly` | No | `-` | - |
|
|
958
|
+
| `key` | `Key \| null` | No | `-` | - |
|
|
959
|
+
| `left` | `string \| number` | No | `-` | - |
|
|
960
|
+
| `lineHeight` | `inherit \| LineHeight` | No | `-` | - |
|
|
961
|
+
| `loading` | `boolean` | No | `-` | Is the element currenty loading. When set to true, will disable element from press and keyboard events Is the element currenty loading. |
|
|
962
|
+
| `margin` | `0 \| -1 \| -2 \| -0.25 \| -0.5 \| -0.75 \| -1.5 \| -3 \| -4 \| -5 \| -6 \| -7 \| -8 \| -9 \| -10` | No | `-` | - |
|
|
963
|
+
| `marginBottom` | `0 \| -1 \| -2 \| -0.25 \| -0.5 \| -0.75 \| -1.5 \| -3 \| -4 \| -5 \| -6 \| -7 \| -8 \| -9 \| -10` | No | `-` | - |
|
|
964
|
+
| `marginEnd` | `0 \| -1 \| -2 \| -0.25 \| -0.5 \| -0.75 \| -1.5 \| -3 \| -4 \| -5 \| -6 \| -7 \| -8 \| -9 \| -10` | No | `-` | - |
|
|
965
|
+
| `marginStart` | `0 \| -1 \| -2 \| -0.25 \| -0.5 \| -0.75 \| -1.5 \| -3 \| -4 \| -5 \| -6 \| -7 \| -8 \| -9 \| -10` | No | `-` | - |
|
|
966
|
+
| `marginTop` | `0 \| -1 \| -2 \| -0.25 \| -0.5 \| -0.75 \| -1.5 \| -3 \| -4 \| -5 \| -6 \| -7 \| -8 \| -9 \| -10` | No | `-` | - |
|
|
967
|
+
| `marginX` | `0 \| -1 \| -2 \| -0.25 \| -0.5 \| -0.75 \| -1.5 \| -3 \| -4 \| -5 \| -6 \| -7 \| -8 \| -9 \| -10` | No | `-` | - |
|
|
968
|
+
| `marginY` | `0 \| -1 \| -2 \| -0.25 \| -0.5 \| -0.75 \| -1.5 \| -3 \| -4 \| -5 \| -6 \| -7 \| -8 \| -9 \| -10` | No | `-` | - |
|
|
969
|
+
| `maxHeight` | `string \| number` | No | `-` | - |
|
|
970
|
+
| `maxWidth` | `string \| number` | No | `-` | - |
|
|
971
|
+
| `media` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | React node to display as the main media content. When provided, it will be rendered in an HStack container. |
|
|
972
|
+
| `minHeight` | `string \| number` | No | `-` | - |
|
|
973
|
+
| `minWidth` | `string \| number` | No | `-` | - |
|
|
974
|
+
| `noScaleOnPress` | `boolean` | No | `-` | Dont scale element on press. |
|
|
975
|
+
| `onActionButtonPress` | `((event: GestureResponderEvent) => void)` | No | `-` | Callback fired when the action button is pressed. Only used when action is a string. |
|
|
976
|
+
| `onDismissButtonPress` | `((event: GestureResponderEvent) => void)` | No | `-` | Callback fired when the dismiss button is pressed. When provided, a default dismiss button will be rendered in the top-right corner. |
|
|
977
|
+
| `onPointerCancel` | `((event: PointerEvent) => void)` | No | `-` | - |
|
|
978
|
+
| `onPointerCancelCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
|
|
979
|
+
| `onPointerDown` | `((event: PointerEvent) => void)` | No | `-` | - |
|
|
980
|
+
| `onPointerDownCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
|
|
981
|
+
| `onPointerEnter` | `((event: PointerEvent) => void)` | No | `-` | - |
|
|
982
|
+
| `onPointerEnterCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
|
|
983
|
+
| `onPointerLeave` | `((event: PointerEvent) => void)` | No | `-` | - |
|
|
984
|
+
| `onPointerLeaveCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
|
|
985
|
+
| `onPointerMove` | `((event: PointerEvent) => void)` | No | `-` | - |
|
|
986
|
+
| `onPointerMoveCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
|
|
987
|
+
| `onPointerUp` | `((event: PointerEvent) => void)` | No | `-` | - |
|
|
988
|
+
| `onPointerUpCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
|
|
989
|
+
| `onPress` | `((event: GestureResponderEvent) => void) \| null` | No | `-` | Called when a single tap gesture is detected. |
|
|
990
|
+
| `onPressIn` | `(((event: GestureResponderEvent) => void) & ((event: GestureResponderEvent) => void))` | No | `-` | Callback fired before onPress when button is pressed. Called when a touch is engaged before onPress. |
|
|
991
|
+
| `onPressOut` | `(((event: GestureResponderEvent) => void) & ((event: GestureResponderEvent) => void))` | No | `-` | Callback fired before onPress when button is released. Called when a touch is released before onPress. |
|
|
992
|
+
| `opacity` | `number \| AnimatedNode` | No | `-` | - |
|
|
993
|
+
| `overflow` | `visible \| hidden \| scroll` | No | `-` | - |
|
|
994
|
+
| `padding` | `0 \| 1 \| 2 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10` | No | `-` | - |
|
|
995
|
+
| `paddingBottom` | `0 \| 1 \| 2 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10` | No | `-` | - |
|
|
996
|
+
| `paddingEnd` | `0 \| 1 \| 2 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10` | No | `-` | - |
|
|
997
|
+
| `paddingStart` | `0 \| 1 \| 2 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10` | No | `-` | - |
|
|
998
|
+
| `paddingTop` | `0 \| 1 \| 2 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10` | No | `-` | - |
|
|
999
|
+
| `paddingX` | `0 \| 1 \| 2 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10` | No | `-` | - |
|
|
1000
|
+
| `paddingY` | `0 \| 1 \| 2 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10` | No | `-` | - |
|
|
1001
|
+
| `pin` | `top \| bottom \| left \| right \| all` | No | `-` | Direction in which to absolutely pin the box. |
|
|
1002
|
+
| `position` | `static \| relative \| fixed \| absolute \| sticky` | No | `-` | - |
|
|
1003
|
+
| `ref` | `((instance: View \| null) => void) \| RefObject<View> \| null` | No | `-` | - |
|
|
1004
|
+
| `renderAsPressable` | `boolean` | No | `false` | If true, the CardRoot will be rendered as a Pressable component. When false, renders as an HStack for layout purposes. |
|
|
1005
|
+
| `right` | `string \| number` | No | `-` | - |
|
|
1006
|
+
| `rowGap` | `0 \| 1 \| 2 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10` | No | `-` | - |
|
|
1007
|
+
| `style` | `null \| false \| ViewStyle \| RegisteredStyle<ViewStyle> \| RecursiveArray<ViewStyle \| Falsy \| RegisteredStyle<ViewStyle>>` | No | `-` | - |
|
|
1008
|
+
| `styles` | `({ layoutContainer?: StyleProp<ViewStyle>; contentContainer?: StyleProp<ViewStyle>; textContainer?: StyleProp<ViewStyle>; mediaContainer?: StyleProp<ViewStyle>; dismissButtonContainer?: StyleProp<ViewStyle>; } & { root?: StyleProp<ViewStyle>; })` | No | `-` | - |
|
|
1009
|
+
| `tag` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | Text or React node to display as a tag. When a string is provided, it will be rendered in a Tag component. |
|
|
1010
|
+
| `testID` | `string` | No | `-` | Used to locate this element in unit and end-to-end tests. Used to locate this view in end-to-end tests. |
|
|
1011
|
+
| `textAlign` | `left \| right \| auto \| center \| justify` | No | `-` | - |
|
|
1012
|
+
| `textDecorationLine` | `none \| underline \| line-through \| underline line-through` | No | `-` | - |
|
|
1013
|
+
| `textDecorationStyle` | `solid \| dotted \| dashed \| double` | No | `-` | - |
|
|
1014
|
+
| `textTransform` | `none \| capitalize \| uppercase \| lowercase` | No | `-` | - |
|
|
1015
|
+
| `title` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | Text or React node to display as the card title. Use a Text component to override default color and font. |
|
|
1016
|
+
| `top` | `string \| number` | No | `-` | - |
|
|
1017
|
+
| `transform` | `string \| (({ scaleX: AnimatableNumericValue; } & { scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ scaleY: AnimatableNumericValue; } & { scaleX?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ translateX: AnimatableNumericValue \| ${number}%; } & { scaleX?: undefined; scaleY?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ translateY: AnimatableNumericValue \| ${number}%; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ perspective: AnimatableNumericValue; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ rotate: AnimatableStringValue; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ rotateX: AnimatableStringValue; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ rotateY: AnimatableStringValue; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ rotateZ: AnimatableStringValue; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ scale: AnimatableNumericValue; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ skewX: AnimatableStringValue; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ skewY: AnimatableStringValue; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; matrix?: undefined; }) \| ({ matrix: AnimatableNumericValue[]; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; }))[]` | No | `-` | - |
|
|
1018
|
+
| `transparentWhileInactive` | `boolean` | No | `-` | Mark the background and border as transparent until the element is interacted with (hovered, pressed, etc). Must be used in conjunction with the pressed prop |
|
|
1019
|
+
| `transparentWhilePressed` | `boolean` | No | `-` | Mark the background and border as transparent even while element is interacted with (elevation underlay issue). Must be used in conjunction with the pressed prop |
|
|
1020
|
+
| `userSelect` | `none \| auto \| contain \| text \| all` | No | `-` | - |
|
|
1021
|
+
| `width` | `string \| number` | No | `-` | - |
|
|
1022
|
+
| `wrapperStyles` | `{ base?: StyleProp<ViewStyle>; pressed?: StyleProp<ViewStyle>; disabled?: StyleProp<ViewStyle>; }` | No | `-` | Apply styles to the outer container. |
|
|
1023
|
+
| `zIndex` | `number` | No | `-` | - |
|
|
1024
|
+
|
|
1025
|
+
|