@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.
@@ -0,0 +1,1054 @@
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-web/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 live
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
+ onActionButtonClick={() => alert('Action clicked!')}
35
+ media={
36
+ <RemoteImage
37
+ alt="Feature promotional image"
38
+ height={160}
39
+ resizeMode="cover"
40
+ shape="rectangle"
41
+ source="/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
+ onActionButtonClick={() => alert('Action clicked!')}
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 live
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 live
97
+ <MessagingCard
98
+ type="upsell"
99
+ background="bgPrimaryWash"
100
+ title={
101
+ <Text as="h3" color="fg" font="headline">
102
+ Recurring Buy
103
+ </Text>
104
+ }
105
+ description={
106
+ <Text as="p" 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
+ onDismissButtonClick={() => {}}
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 live
132
+ function FeatureUpsell() {
133
+ const cards = [
134
+ { bg: 'rgb(var(--purple70))', label: 'Purple' },
135
+ { bg: 'rgb(var(--teal50))', label: 'Teal' },
136
+ { bg: 'rgb(var(--blue80))', label: 'Blue' },
137
+ { bg: 'rgb(var(--indigo70))', label: 'Indigo' },
138
+ ];
139
+ return (
140
+ <VStack gap={2}>
141
+ {cards.map((card) => (
142
+ <MessagingCard
143
+ key={card.label}
144
+ type="upsell"
145
+ dangerouslySetBackground={card.bg}
146
+ title={
147
+ <Text color="fgInverse" as="h3" font="headline">
148
+ Up to 3.29% APR on ETH
149
+ </Text>
150
+ }
151
+ description={
152
+ <Text as="p" font="label2" numberOfLines={3} color="fgInverse">
153
+ Earn staking rewards on ETH by holding it on Coinbase
154
+ </Text>
155
+ }
156
+ width={360}
157
+ action="Start earning"
158
+ onActionButtonClick={() => alert('Action clicked!')}
159
+ media={
160
+ <RemoteImage
161
+ alt="Feature illustration"
162
+ height={160}
163
+ resizeMode="cover"
164
+ shape="rectangle"
165
+ source="/img/feature.png"
166
+ />
167
+ }
168
+ mediaPlacement="end"
169
+ onDismissButtonClick={() => {}}
170
+ dismissButtonAccessibilityLabel="Dismiss"
171
+ />
172
+ ))}
173
+ </VStack>
174
+ );
175
+ }
176
+ ```
177
+
178
+ #### Community Upsell
179
+
180
+ Designed for community-focused messaging. Vibrant colors spark enthusiasm and encourage active participation, fostering a sense of community engagement.
181
+
182
+ ```jsx live
183
+ function CommunityUpsell() {
184
+ const cards = [
185
+ { bg: 'rgb(var(--teal70))', image: '/img/community.png' },
186
+ { bg: 'rgb(var(--purple70))', image: '/img/radial.png' },
187
+ ];
188
+ return (
189
+ <VStack gap={2}>
190
+ {cards.map((card, i) => (
191
+ <MessagingCard
192
+ key={i}
193
+ type="upsell"
194
+ dangerouslySetBackground={card.bg}
195
+ title={
196
+ <Text color="fgInverse" as="h3" font="headline">
197
+ Join the community
198
+ </Text>
199
+ }
200
+ description={
201
+ <Text as="p" font="label2" numberOfLines={3} color="fgInverse">
202
+ Chat with other devs in our Discord community
203
+ </Text>
204
+ }
205
+ width={360}
206
+ action="Join now"
207
+ onActionButtonClick={() => alert('Action clicked!')}
208
+ media={
209
+ <RemoteImage
210
+ alt="Community illustration"
211
+ height={160}
212
+ resizeMode="cover"
213
+ shape="rectangle"
214
+ source={card.image}
215
+ />
216
+ }
217
+ mediaPlacement="end"
218
+ onDismissButtonClick={() => {}}
219
+ dismissButtonAccessibilityLabel="Dismiss"
220
+ />
221
+ ))}
222
+ </VStack>
223
+ );
224
+ }
225
+ ```
226
+
227
+ #### Product Upsell
228
+
229
+ 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.
230
+
231
+ ```jsx live
232
+ function ProductUpsell() {
233
+ const cards = [
234
+ {
235
+ title: 'Coinbase One offer',
236
+ description: 'Use code NOV60 when you sign up for Coinbase One',
237
+ action: 'Get 60 days free',
238
+ bg: 'rgb(var(--blue80))',
239
+ image: '/img/marketing.png',
240
+ },
241
+ {
242
+ title: 'Coinbase Card',
243
+ description: 'Spend USDC to get rewards with our Visa® debit card',
244
+ action: 'Get started',
245
+ bg: 'rgb(var(--gray100))',
246
+ image: '/img/object.png',
247
+ },
248
+ ];
249
+ return (
250
+ <VStack gap={2}>
251
+ {cards.map((card) => (
252
+ <MessagingCard
253
+ key={card.title}
254
+ type="upsell"
255
+ dangerouslySetBackground={card.bg}
256
+ title={
257
+ <Text color="fgInverse" as="h3" font="headline">
258
+ {card.title}
259
+ </Text>
260
+ }
261
+ description={
262
+ <Text as="p" font="label2" numberOfLines={3} color="fgInverse">
263
+ {card.description}
264
+ </Text>
265
+ }
266
+ width={360}
267
+ action={card.action}
268
+ onActionButtonClick={() => alert('Action clicked!')}
269
+ media={
270
+ <RemoteImage
271
+ alt="Product illustration"
272
+ height={160}
273
+ resizeMode="cover"
274
+ shape="rectangle"
275
+ source={card.image}
276
+ />
277
+ }
278
+ mediaPlacement="end"
279
+ onDismissButtonClick={() => {}}
280
+ dismissButtonAccessibilityLabel="Dismiss"
281
+ />
282
+ ))}
283
+ </VStack>
284
+ );
285
+ }
286
+ ```
287
+
288
+ #### News Upsell
289
+
290
+ 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.
291
+
292
+ ```jsx live
293
+ function NewsUpsell() {
294
+ const cards = [{ bg: 'rgb(var(--gray100))' }, { bg: 'rgb(var(--indigo70))' }];
295
+ return (
296
+ <VStack gap={2}>
297
+ {cards.map((card, i) => (
298
+ <MessagingCard
299
+ key={i}
300
+ type="upsell"
301
+ dangerouslySetBackground={card.bg}
302
+ title={
303
+ <Text color="fgInverse" as="h3" font="headline">
304
+ Help defend crypto in America
305
+ </Text>
306
+ }
307
+ description={
308
+ <Text as="p" font="label2" numberOfLines={3} color="fgInverse">
309
+ Help us keep crypto in America with a single click
310
+ </Text>
311
+ }
312
+ width={360}
313
+ action="Join the fight"
314
+ onActionButtonClick={() => alert('Action clicked!')}
315
+ media={
316
+ <RemoteImage
317
+ alt="Place illustration"
318
+ height={180}
319
+ resizeMode="cover"
320
+ shape="rectangle"
321
+ source="/img/place.png"
322
+ />
323
+ }
324
+ mediaPlacement="end"
325
+ onDismissButtonClick={() => {}}
326
+ dismissButtonAccessibilityLabel="Dismiss"
327
+ />
328
+ ))}
329
+ </VStack>
330
+ );
331
+ }
332
+ ```
333
+
334
+ ### Nudge Card Style
335
+
336
+ 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.
337
+
338
+ ```jsx live
339
+ <VStack gap={2}>
340
+ <MessagingCard
341
+ type="nudge"
342
+ title="Earn more crypto"
343
+ description="You've got unstaked crypto. Stake it now to earn more."
344
+ width={360}
345
+ action="Start earning"
346
+ onActionButtonClick={() => alert('Action clicked!')}
347
+ media={<Pictogram dimension="64x64" name="key" />}
348
+ mediaPlacement="end"
349
+ onDismissButtonClick={() => {}}
350
+ dismissButtonAccessibilityLabel="Dismiss"
351
+ />
352
+ <MessagingCard
353
+ type="nudge"
354
+ title="Derivatives Trading"
355
+ description="Derivative Exchange is available for all users"
356
+ width={360}
357
+ media={<Pictogram dimension="48x48" name="derivativesNavigation" />}
358
+ mediaPlacement="end"
359
+ />
360
+ </VStack>
361
+ ```
362
+
363
+ ### Features
364
+
365
+ #### Dismissible Cards
366
+
367
+ Use `onDismissButtonClick` to add a dismiss button.
368
+
369
+ ```jsx live
370
+ <VStack gap={2}>
371
+ <MessagingCard
372
+ type="upsell"
373
+ title="Dismissible Upsell"
374
+ description="Upsell card with dismiss button"
375
+ width={320}
376
+ media={
377
+ <RemoteImage
378
+ alt="Community illustration"
379
+ height={160}
380
+ resizeMode="cover"
381
+ shape="rectangle"
382
+ source="/img/community.png"
383
+ />
384
+ }
385
+ mediaPlacement="end"
386
+ onDismissButtonClick={() => alert('Card dismissed!')}
387
+ dismissButtonAccessibilityLabel="Close card"
388
+ dangerouslySetBackground="rgb(var(--teal70))"
389
+ />
390
+ <MessagingCard
391
+ type="nudge"
392
+ title="Dismissible Nudge"
393
+ description="Nudge card with dismiss button"
394
+ width={320}
395
+ media={<Pictogram dimension="48x48" name="baseStar" />}
396
+ mediaPlacement="end"
397
+ onDismissButtonClick={() => alert('Card dismissed!')}
398
+ dismissButtonAccessibilityLabel="Close card"
399
+ />
400
+ </VStack>
401
+ ```
402
+
403
+ #### Tags
404
+
405
+ Use `tag` to add a label badge.
406
+
407
+ ```jsx live
408
+ <VStack gap={2}>
409
+ <MessagingCard
410
+ type="upsell"
411
+ title="Tagged Upsell"
412
+ description="Upsell card with a tag"
413
+ width={320}
414
+ tag="New"
415
+ media={
416
+ <RemoteImage
417
+ alt="Place illustration"
418
+ height={160}
419
+ resizeMode="cover"
420
+ shape="rectangle"
421
+ source="/img/place.png"
422
+ />
423
+ }
424
+ mediaPlacement="end"
425
+ />
426
+ <MessagingCard
427
+ type="nudge"
428
+ title="Tagged Nudge"
429
+ description="Nudge card with a tag"
430
+ width={320}
431
+ tag="New"
432
+ media={<Pictogram dimension="48x48" name="key" />}
433
+ mediaPlacement="end"
434
+ />
435
+ </VStack>
436
+ ```
437
+
438
+ #### Actions
439
+
440
+ Use the `action` prop to add an action button. Pass a string to render a default button with `onActionButtonClick`, or pass a custom React element.
441
+
442
+ ```jsx live
443
+ <VStack gap={2}>
444
+ <MessagingCard
445
+ type="upsell"
446
+ title="Upsell with Action"
447
+ description="Upsell card with action button"
448
+ width={320}
449
+ action="Action"
450
+ onActionButtonClick={() => alert('Action clicked!')}
451
+ media={
452
+ <RemoteImage
453
+ alt="Feature illustration"
454
+ height={160}
455
+ resizeMode="cover"
456
+ shape="rectangle"
457
+ source="/img/feature.png"
458
+ />
459
+ }
460
+ mediaPlacement="end"
461
+ />
462
+ <MessagingCard
463
+ type="nudge"
464
+ title="Nudge with Action"
465
+ description="Nudge card with action button"
466
+ width={320}
467
+ action="Learn More"
468
+ onActionButtonClick={() => alert('Action clicked!')}
469
+ media={<Pictogram dimension="64x64" name="wallet" />}
470
+ mediaPlacement="end"
471
+ />
472
+ </VStack>
473
+ ```
474
+
475
+ #### Complete Example
476
+
477
+ Combine all features in a complete card.
478
+
479
+ ```jsx live
480
+ <VStack gap={2}>
481
+ <MessagingCard
482
+ type="upsell"
483
+ title="Complete Upsell Card"
484
+ description="Complete upsell card with all features"
485
+ width={360}
486
+ tag="New"
487
+ action="Get Started"
488
+ onActionButtonClick={() => alert('Action clicked!')}
489
+ onDismissButtonClick={() => alert('Dismissed')}
490
+ dismissButtonAccessibilityLabel="Dismiss"
491
+ media={
492
+ <RemoteImage
493
+ alt="Marketing illustration"
494
+ height={184}
495
+ resizeMode="cover"
496
+ shape="rectangle"
497
+ source="/img/marketing.png"
498
+ />
499
+ }
500
+ mediaPlacement="end"
501
+ />
502
+ <MessagingCard
503
+ type="nudge"
504
+ title="Complete Nudge Card"
505
+ description="Complete nudge card with all features"
506
+ width={360}
507
+ tag="New"
508
+ action="Learn More"
509
+ onActionButtonClick={() => alert('Action clicked!')}
510
+ onDismissButtonClick={() => alert('Dismissed')}
511
+ dismissButtonAccessibilityLabel="Dismiss"
512
+ media={<Pictogram dimension="64x64" name="giftbox" />}
513
+ mediaPlacement="end"
514
+ />
515
+ </VStack>
516
+ ```
517
+
518
+ ### Interactive Dismissible List
519
+
520
+ This example shows a list of cards that can be dismissed interactively. Click the dismiss button to remove cards from the list.
521
+
522
+ ```jsx live
523
+ function DismissibleCards() {
524
+ const cards = [
525
+ {
526
+ id: '1',
527
+ title: 'Welcome to Coinbase',
528
+ description: 'Get started with your crypto journey',
529
+ type: 'upsell',
530
+ },
531
+ {
532
+ id: '2',
533
+ title: 'Complete your profile',
534
+ description: 'Add your details to unlock more features',
535
+ type: 'nudge',
536
+ },
537
+ {
538
+ id: '3',
539
+ title: 'Enable notifications',
540
+ description: 'Stay updated on market movements',
541
+ type: 'upsell',
542
+ },
543
+ {
544
+ id: '4',
545
+ title: 'Invite friends',
546
+ description: 'Earn rewards when friends join',
547
+ type: 'nudge',
548
+ },
549
+ ];
550
+
551
+ const [dismissedIds, setDismissedIds] = React.useState(new Set());
552
+
553
+ const handleDismiss = (id) => {
554
+ setDismissedIds((prev) => new Set(prev).add(id));
555
+ };
556
+
557
+ const handleReset = () => {
558
+ setDismissedIds(new Set());
559
+ };
560
+
561
+ const visibleCards = cards.filter((card) => !dismissedIds.has(card.id));
562
+
563
+ return (
564
+ <VStack gap={2}>
565
+ <HStack gap={2} flexWrap="wrap">
566
+ {visibleCards.map((card) => (
567
+ <MessagingCard
568
+ key={card.id}
569
+ type={card.type}
570
+ dangerouslySetBackground={card.type === 'upsell' ? 'rgb(var(--gray100))' : undefined}
571
+ title={card.title}
572
+ description={card.description}
573
+ width={360}
574
+ media={
575
+ card.type === 'upsell' ? (
576
+ <RemoteImage
577
+ alt="Promotional illustration"
578
+ height={160}
579
+ resizeMode="cover"
580
+ shape="rectangle"
581
+ source="/img/object.png"
582
+ />
583
+ ) : (
584
+ <Pictogram dimension="48x48" name="addToWatchlist" />
585
+ )
586
+ }
587
+ mediaPlacement="end"
588
+ onDismissButtonClick={() => handleDismiss(card.id)}
589
+ dismissButtonAccessibilityLabel={`Dismiss ${card.title}`}
590
+ />
591
+ ))}
592
+ {visibleCards.length === 0 && (
593
+ <Text color="fgNegative" font="label1">
594
+ All cards dismissed!
595
+ </Text>
596
+ )}
597
+ </HStack>
598
+ <Button onClick={handleReset} variant="tertiary">
599
+ Reset Cards
600
+ </Button>
601
+ </VStack>
602
+ );
603
+ }
604
+ ```
605
+
606
+ ### Polymorphic and Interactive
607
+
608
+ MessagingCard supports polymorphic rendering with `as` and can be made interactive with `renderAsPressable`.
609
+
610
+ ```jsx live
611
+ <VStack gap={2}>
612
+ <MessagingCard
613
+ as="article"
614
+ type="upsell"
615
+ dangerouslySetBackground="rgb(var(--teal70))"
616
+ title="Title"
617
+ description="Description"
618
+ width={320}
619
+ media={
620
+ <RemoteImage
621
+ alt="Community illustration"
622
+ height={160}
623
+ resizeMode="cover"
624
+ shape="rectangle"
625
+ source="/img/community.png"
626
+ />
627
+ }
628
+ mediaPlacement="end"
629
+ />
630
+ <MessagingCard
631
+ renderAsPressable
632
+ as="a"
633
+ href="https://www.coinbase.com"
634
+ target="_blank"
635
+ type="upsell"
636
+ dangerouslySetBackground="rgb(var(--purple70))"
637
+ title="Interactive Upsell"
638
+ description="Clickable card with href"
639
+ width={320}
640
+ media={
641
+ <RemoteImage
642
+ alt="Radial design"
643
+ height={160}
644
+ resizeMode="cover"
645
+ shape="rectangle"
646
+ source="/img/radial.png"
647
+ />
648
+ }
649
+ mediaPlacement="end"
650
+ />
651
+ <MessagingCard
652
+ renderAsPressable
653
+ as="a"
654
+ href="https://www.coinbase.com"
655
+ target="_blank"
656
+ type="nudge"
657
+ title="Interactive Nudge"
658
+ description="Clickable nudge with href"
659
+ width={320}
660
+ media={<Pictogram dimension="48x48" name="baseRocket" />}
661
+ mediaPlacement="end"
662
+ />
663
+ <MessagingCard
664
+ renderAsPressable
665
+ as="button"
666
+ onClick={() => alert('Card clicked!')}
667
+ type="upsell"
668
+ dangerouslySetBackground="rgb(var(--gray100))"
669
+ title="Interactive Card"
670
+ description="Clickable card with onClick handler"
671
+ width={320}
672
+ media={
673
+ <RemoteImage
674
+ alt="Object illustration"
675
+ height={160}
676
+ resizeMode="cover"
677
+ shape="rectangle"
678
+ source="/img/object.png"
679
+ />
680
+ }
681
+ mediaPlacement="end"
682
+ />
683
+ </VStack>
684
+ ```
685
+
686
+ ### Custom Content
687
+
688
+ Use React nodes for custom styled content.
689
+
690
+ ```jsx live
691
+ <VStack gap={2}>
692
+ <MessagingCard
693
+ type="upsell"
694
+ title="This is a very long title text that demonstrates text wrapping"
695
+ description="This is a very long description text that demonstrates how the card handles longer content and wraps appropriately within the card layout"
696
+ width={320}
697
+ media={
698
+ <RemoteImage
699
+ alt="Place illustration"
700
+ height={160}
701
+ resizeMode="cover"
702
+ shape="rectangle"
703
+ source="/img/place.png"
704
+ />
705
+ }
706
+ mediaPlacement="end"
707
+ />
708
+ <MessagingCard
709
+ type="upsell"
710
+ width={320}
711
+ height={160}
712
+ title={
713
+ <Text color="fgInverse" font="title3">
714
+ Custom Title
715
+ </Text>
716
+ }
717
+ tag={
718
+ <Text color="fgInverse" font="label2">
719
+ Custom Tag
720
+ </Text>
721
+ }
722
+ description={
723
+ <Text color="fgInverse" font="label2" numberOfLines={3}>
724
+ Custom description with <strong>bold text</strong> and <em>italic text</em>
725
+ </Text>
726
+ }
727
+ media={
728
+ <RemoteImage
729
+ alt="Collection illustration"
730
+ height={160}
731
+ resizeMode="cover"
732
+ shape="rectangle"
733
+ source="/img/collection.png"
734
+ />
735
+ }
736
+ mediaPlacement="end"
737
+ />
738
+ </VStack>
739
+ ```
740
+
741
+ ### Multiple Cards
742
+
743
+ Display multiple cards in a carousel.
744
+
745
+ ```jsx live
746
+ <Carousel styles={{ carousel: { gap: 16 } }}>
747
+ <CarouselItem id="card1">
748
+ <MessagingCard
749
+ as="article"
750
+ type="upsell"
751
+ title="Card 1"
752
+ description="Non-interactive card"
753
+ width={320}
754
+ media={
755
+ <RemoteImage
756
+ alt="Marketing illustration"
757
+ height={160}
758
+ resizeMode="cover"
759
+ shape="rectangle"
760
+ source="/img/marketing.png"
761
+ />
762
+ }
763
+ mediaPlacement="end"
764
+ />
765
+ </CarouselItem>
766
+ <CarouselItem id="card2">
767
+ <MessagingCard
768
+ renderAsPressable
769
+ as="a"
770
+ href="https://www.coinbase.com"
771
+ target="_blank"
772
+ type="nudge"
773
+ title="Card 2"
774
+ description="Clickable card with href"
775
+ tag="Link"
776
+ media={<Pictogram dimension="64x64" name="addToWatchlist" />}
777
+ mediaPlacement="end"
778
+ />
779
+ </CarouselItem>
780
+ <CarouselItem id="card3">
781
+ <MessagingCard
782
+ renderAsPressable
783
+ as="button"
784
+ onClick={() => console.log('clicked')}
785
+ type="upsell"
786
+ dangerouslySetBackground="rgb(var(--purple70))"
787
+ title="Card 3"
788
+ description="Card with onClick handler"
789
+ tag="Action"
790
+ media={
791
+ <RemoteImage
792
+ alt="Radial design"
793
+ height={160}
794
+ resizeMode="cover"
795
+ shape="rectangle"
796
+ source="/img/radial.png"
797
+ />
798
+ }
799
+ mediaPlacement="end"
800
+ />
801
+ </CarouselItem>
802
+ </Carousel>
803
+ ```
804
+
805
+ ### Accessibility
806
+
807
+ #### Interactive Cards with Dismiss Button
808
+
809
+ When you need both `onDismissButtonClick` and want the entire card to be clickable, you should handle accessibility carefully to avoid nested interactive elements.
810
+
811
+ **The Problem**: If you use `renderAsPressable` with `onClick` and also have `onDismissButtonClick`, the card becomes a button containing another button (the dismiss button). This creates accessibility issues for screen reader users.
812
+
813
+ **The Solution**: Mark the card as non-accessible and add a separate action button inside the card with the same action. This allows:
814
+
815
+ - Regular users to click anywhere on the card
816
+ - Screen reader users to focus on individual interactive elements (action button + dismiss button)
817
+
818
+ ```jsx live
819
+ <MessagingCard
820
+ renderAsPressable
821
+ tabIndex={-1}
822
+ as="div"
823
+ onClick={() => alert('Card clicked - navigating...')}
824
+ type="upsell"
825
+ title="Accessible Interactive Card"
826
+ description="Card with both dismiss and card-level action"
827
+ width={360}
828
+ action={
829
+ <Button
830
+ compact
831
+ variant="secondary"
832
+ onClick={(event) => {
833
+ event.stopPropagation();
834
+ alert('Button clicked - navigating...');
835
+ }}
836
+ >
837
+ Learn More
838
+ </Button>
839
+ }
840
+ background="accentBoldPurple"
841
+ onDismissButtonClick={() => alert('Dismissed')}
842
+ dismissButtonAccessibilityLabel="Dismiss promotion"
843
+ media={
844
+ <RemoteImage
845
+ alt="Feature illustration"
846
+ height={160}
847
+ resizeMode="cover"
848
+ shape="rectangle"
849
+ source="/img/feature.png"
850
+ />
851
+ }
852
+ mediaPlacement="end"
853
+ />
854
+ ```
855
+
856
+ **Key points:**
857
+
858
+ - Use `as="div"` to avoid rendering as a semantic button
859
+ - When using `as="div"` with `renderAsPressable`, the card remains keyboard focusable. Set `tabIndex={-1}` to remove it from the tab order if needed
860
+ - Call `event.stopPropagation()` at the beginning of the event handler method passed into the `onClick` prop for action buttons. This will prevent two click events from firing if the user directly clicks the action button.
861
+ - Use `actionButtonAccessibilityLabel` and `dismissButtonAccessibilityLabel` to add or override the `aria-label` for the action and dismiss buttons
862
+
863
+ #### Color Contrast
864
+
865
+ MessagingCard supports custom backgrounds via `background` and `dangerouslySetBackground` props. When using custom background colors, ensure sufficient color contrast between text and background:
866
+
867
+ - Use `fgInverse` text color with dark backgrounds (e.g., `accentBoldPurple`, `bgInverse`)
868
+ - Use `fg` text color with light backgrounds (e.g., `bgPrimaryWash`, `bgAlternate`)
869
+ - Use the [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/) to verify your color combinations meet WCAG AA guidelines (4.5:1 for normal text)
870
+
871
+ ### Migration from Deprecated Components
872
+
873
+ #### Migrating from NudgeCard
874
+
875
+ Replace `NudgeCard` with `MessagingCard` using `type="nudge"`.
876
+
877
+ ```jsx
878
+ // Before
879
+ <NudgeCard
880
+ title="Title"
881
+ description="Description"
882
+ pictogram="addToWatchlist"
883
+ action="Learn more"
884
+ onActionPress={handleAction}
885
+ onDismissPress={handleDismiss}
886
+ />
887
+
888
+ // After
889
+ <MessagingCard
890
+ type="nudge"
891
+ title="Title"
892
+ description="Description"
893
+ media={<Pictogram dimension="64x64" name="addToWatchlist" />}
894
+ action="Learn more"
895
+ onActionButtonClick={handleAction}
896
+ onDismissButtonClick={handleDismiss}
897
+ mediaPlacement="end"
898
+ />
899
+ ```
900
+
901
+ #### Migrating from UpsellCard
902
+
903
+ Replace `UpsellCard` with `MessagingCard` using `type="upsell"`.
904
+
905
+ ```jsx
906
+ // Before
907
+ <UpsellCard
908
+ title="Title"
909
+ description="Description"
910
+ media={<RemoteImage ... />}
911
+ action="Get Started"
912
+ onActionPress={handleAction}
913
+ onDismissPress={handleDismiss}
914
+ />
915
+
916
+ // After
917
+ <MessagingCard
918
+ type="upsell"
919
+ title="Title"
920
+ description="Description"
921
+ media={<RemoteImage ... />}
922
+ action="Get Started"
923
+ onActionButtonClick={handleAction}
924
+ onDismissButtonClick={handleDismiss}
925
+ mediaPlacement="end"
926
+ />
927
+ ```
928
+
929
+ ## Props
930
+
931
+ | Prop | Type | Required | Default | Description |
932
+ | --- | --- | --- | --- | --- |
933
+ | `mediaPlacement` | `start \| end` | Yes | `'end'` | Placement of the media content relative to the text content. |
934
+ | `type` | `upsell \| nudge` | Yes | `-` | Type of messaging card. Determines background color and text color. |
935
+ | `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 onActionButtonClick to handle clicks. |
936
+ | `actionButtonAccessibilityLabel` | `string` | No | `action value (when action is a string)` | Accessibility label for the action button. Only used when action is a string. |
937
+ | `alignContent` | `ResponsiveProp<center \| normal \| start \| end \| flex-start \| flex-end \| stretch \| baseline \| first baseline \| last baseline \| space-between \| space-around \| space-evenly>` | No | `-` | - |
938
+ | `alignItems` | `ResponsiveProp<center \| normal \| start \| end \| flex-start \| flex-end \| self-start \| self-end \| stretch \| baseline \| first baseline \| last baseline>` | No | `-` | - |
939
+ | `alignSelf` | `ResponsiveProp<center \| normal \| auto \| start \| end \| flex-start \| flex-end \| self-start \| self-end \| stretch \| baseline \| first baseline \| last baseline>` | No | `-` | - |
940
+ | `as` | `symbol \| object \| style \| div \| a \| abbr \| address \| area \| article \| aside \| audio \| b \| base \| bdi \| bdo \| big \| blockquote \| body \| br \| button \| canvas \| caption \| center \| cite \| code \| col \| colgroup \| data \| datalist \| dd \| del \| details \| dfn \| dialog \| dl \| dt \| em \| embed \| fieldset \| figcaption \| figure \| footer \| form \| h1 \| h2 \| h3 \| h4 \| h5 \| h6 \| head \| header \| hgroup \| hr \| html \| i \| iframe \| img \| input \| ins \| kbd \| keygen \| label \| legend \| li \| link \| main \| map \| mark \| menu \| menuitem \| meta \| meter \| nav \| noindex \| noscript \| ol \| optgroup \| option \| output \| p \| param \| picture \| pre \| progress \| q \| rp \| rt \| ruby \| s \| samp \| search \| slot \| script \| section \| select \| small \| source \| span \| strong \| sub \| summary \| sup \| table \| template \| tbody \| td \| textarea \| tfoot \| th \| thead \| time \| title \| tr \| track \| u \| ul \| var \| video \| wbr \| webview \| svg \| animate \| animateMotion \| animateTransform \| circle \| clipPath \| defs \| desc \| ellipse \| feBlend \| feColorMatrix \| feComponentTransfer \| feComposite \| feConvolveMatrix \| feDiffuseLighting \| feDisplacementMap \| feDistantLight \| feDropShadow \| feFlood \| feFuncA \| feFuncB \| feFuncG \| feFuncR \| feGaussianBlur \| feImage \| feMerge \| feMergeNode \| feMorphology \| feOffset \| fePointLight \| feSpecularLighting \| feSpotLight \| feTile \| feTurbulence \| filter \| foreignObject \| g \| image \| line \| linearGradient \| marker \| mask \| metadata \| mpath \| path \| pattern \| polygon \| polyline \| radialGradient \| rect \| set \| stop \| switch \| text \| textPath \| tspan \| use \| view \| ComponentClass<any, any> \| FunctionComponent<any>` | No | `-` | The underlying element or component the polymorphic component will render. Changing as also changes the inherited native props (e.g. href for as=a) and the expected ref type. |
941
+ | `aspectRatio` | `inherit \| auto \| revert \| -moz-initial \| initial \| revert-layer \| unset` | No | `-` | - |
942
+ | `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). |
943
+ | `blendStyles` | `InteractableBlendStyles` | No | `-` | - |
944
+ | `block` | `boolean` | No | `-` | Set element to block and expand to 100% width. |
945
+ | `borderBottomLeftRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
946
+ | `borderBottomRightRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
947
+ | `borderBottomWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
948
+ | `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 | `-` | Border color of the element. |
949
+ | `borderEndWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
950
+ | `borderRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
951
+ | `borderStartWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
952
+ | `borderTopLeftRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
953
+ | `borderTopRightRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
954
+ | `borderTopWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
955
+ | `borderWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
956
+ | `bordered` | `boolean` | No | `-` | Add a border around all sides of the box. |
957
+ | `borderedBottom` | `boolean` | No | `-` | Add a border to the bottom side of the box. |
958
+ | `borderedEnd` | `boolean` | No | `-` | Add a border to the trailing side of the box. |
959
+ | `borderedHorizontal` | `boolean` | No | `-` | Add a border to the leading and trailing sides of the box. |
960
+ | `borderedStart` | `boolean` | No | `-` | Add a border to the leading side of the box. |
961
+ | `borderedTop` | `boolean` | No | `-` | Add a border to the top side of the box. |
962
+ | `borderedVertical` | `boolean` | No | `-` | Add a border to the top and bottom sides of the box. |
963
+ | `bottom` | `ResponsiveProp<Bottom<string \| number>>` | No | `-` | - |
964
+ | `className` | `string` | No | `-` | Apply class names to the outer container. |
965
+ | `classNames` | `({ layoutContainer?: string; contentContainer?: string \| undefined; textContainer?: string \| undefined; mediaContainer?: string \| undefined; dismissButtonContainer?: string \| undefined; } & { root?: string \| undefined; }) \| undefined` | No | `-` | - |
966
+ | `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 | `-` | - |
967
+ | `columnGap` | `0 \| 1 \| 2 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10` | No | `-` | - |
968
+ | `dangerouslySetBackground` | `string` | No | `-` | - |
969
+ | `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. |
970
+ | `disabled` | `boolean` | No | `-` | Is the element currently disabled. |
971
+ | `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. |
972
+ | `dismissButtonAccessibilityLabel` | `string` | No | `'Dismiss {title}' when title is a string, otherwise 'Dismiss card'` | Accessibility label for the dismiss button. |
973
+ | `display` | `ResponsiveProp<grid \| revert \| none \| block \| inline \| inline-block \| flex \| inline-flex \| inline-grid \| contents \| flow-root \| list-item>` | No | `-` | - |
974
+ | `elevation` | `0 \| 1 \| 2` | No | `-` | - |
975
+ | `flexBasis` | `ResponsiveProp<FlexBasis<string \| number>>` | No | `-` | - |
976
+ | `flexDirection` | `ResponsiveProp<column \| row \| row-reverse \| column-reverse>` | No | `-` | - |
977
+ | `flexGrow` | `inherit \| revert \| -moz-initial \| initial \| revert-layer \| unset` | No | `-` | - |
978
+ | `flexShrink` | `inherit \| revert \| -moz-initial \| initial \| revert-layer \| unset` | No | `-` | - |
979
+ | `flexWrap` | `ResponsiveProp<nowrap \| wrap \| wrap-reverse>` | No | `-` | - |
980
+ | `focusable` | `boolean` | No | `-` | - |
981
+ | `font` | `ResponsiveProp<FontFamily \| inherit>` | No | `-` | - |
982
+ | `fontFamily` | `ResponsiveProp<FontFamily \| inherit>` | No | `-` | - |
983
+ | `fontSize` | `ResponsiveProp<FontSize \| inherit>` | No | `-` | - |
984
+ | `fontWeight` | `ResponsiveProp<FontWeight \| inherit>` | No | `-` | - |
985
+ | `gap` | `0 \| 1 \| 2 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10` | No | `-` | - |
986
+ | `grid` | `inherit \| none \| revert \| -moz-initial \| initial \| revert-layer \| unset` | No | `-` | - |
987
+ | `gridArea` | `inherit \| auto \| revert \| -moz-initial \| initial \| revert-layer \| unset` | No | `-` | - |
988
+ | `gridAutoColumns` | `ResponsiveProp<GridAutoColumns<string \| number>>` | No | `-` | - |
989
+ | `gridAutoFlow` | `inherit \| revert \| row \| column \| -moz-initial \| initial \| revert-layer \| unset \| dense` | No | `-` | - |
990
+ | `gridAutoRows` | `ResponsiveProp<GridAutoRows<string \| number>>` | No | `-` | - |
991
+ | `gridColumn` | `inherit \| auto \| revert \| -moz-initial \| initial \| revert-layer \| unset` | No | `-` | - |
992
+ | `gridColumnEnd` | `inherit \| auto \| revert \| -moz-initial \| initial \| revert-layer \| unset` | No | `-` | - |
993
+ | `gridColumnStart` | `inherit \| auto \| revert \| -moz-initial \| initial \| revert-layer \| unset` | No | `-` | - |
994
+ | `gridRow` | `inherit \| auto \| revert \| -moz-initial \| initial \| revert-layer \| unset` | No | `-` | - |
995
+ | `gridRowEnd` | `inherit \| auto \| revert \| -moz-initial \| initial \| revert-layer \| unset` | No | `-` | - |
996
+ | `gridRowStart` | `inherit \| auto \| revert \| -moz-initial \| initial \| revert-layer \| unset` | No | `-` | - |
997
+ | `gridTemplate` | `inherit \| none \| revert \| -moz-initial \| initial \| revert-layer \| unset` | No | `-` | - |
998
+ | `gridTemplateAreas` | `inherit \| none \| revert \| -moz-initial \| initial \| revert-layer \| unset` | No | `-` | - |
999
+ | `gridTemplateColumns` | `ResponsiveProp<GridTemplateColumns<string \| number>>` | No | `-` | - |
1000
+ | `gridTemplateRows` | `ResponsiveProp<GridTemplateRows<string \| number>>` | No | `-` | - |
1001
+ | `height` | `ResponsiveProp<Height<string \| number>>` | No | `-` | - |
1002
+ | `justifyContent` | `ResponsiveProp<left \| right \| center \| normal \| start \| end \| flex-start \| flex-end \| stretch \| space-between \| space-around \| space-evenly>` | No | `-` | - |
1003
+ | `left` | `ResponsiveProp<Left<string \| number>>` | No | `-` | - |
1004
+ | `lineHeight` | `ResponsiveProp<LineHeight \| inherit>` | No | `-` | - |
1005
+ | `loading` | `boolean` | No | `-` | Is the element currenty loading. When set to true, will disable element from press and keyboard events |
1006
+ | `margin` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
1007
+ | `marginBottom` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
1008
+ | `marginEnd` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
1009
+ | `marginStart` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
1010
+ | `marginTop` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
1011
+ | `marginX` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
1012
+ | `marginY` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
1013
+ | `maxHeight` | `ResponsiveProp<MaxHeight<string \| number>>` | No | `-` | - |
1014
+ | `maxWidth` | `ResponsiveProp<MaxWidth<string \| number>>` | No | `-` | - |
1015
+ | `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 a Box container. |
1016
+ | `minHeight` | `ResponsiveProp<MinHeight<string \| number>>` | No | `-` | - |
1017
+ | `minWidth` | `ResponsiveProp<MinWidth<string \| number>>` | No | `-` | - |
1018
+ | `noScaleOnPress` | `boolean` | No | `-` | Dont scale element on press. |
1019
+ | `onActionButtonClick` | `((event: MouseEvent<HTMLButtonElement, MouseEvent>) => void)` | No | `-` | Callback fired when the action button is clicked. Only used when action is a string. |
1020
+ | `onDismissButtonClick` | `((event: MouseEvent<HTMLButtonElement, MouseEvent>) => void)` | No | `-` | Callback fired when the dismiss button is clicked. When provided, a default dismiss button will be rendered in the top-right corner. |
1021
+ | `opacity` | `inherit \| revert \| -moz-initial \| initial \| revert-layer \| unset` | No | `-` | - |
1022
+ | `overflow` | `ResponsiveProp<hidden \| auto \| visible \| clip \| scroll>` | No | `-` | - |
1023
+ | `padding` | `0 \| 1 \| 2 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10` | No | `-` | - |
1024
+ | `paddingBottom` | `0 \| 1 \| 2 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10` | No | `-` | - |
1025
+ | `paddingEnd` | `0 \| 1 \| 2 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10` | No | `-` | - |
1026
+ | `paddingStart` | `0 \| 1 \| 2 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10` | No | `-` | - |
1027
+ | `paddingTop` | `0 \| 1 \| 2 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10` | No | `-` | - |
1028
+ | `paddingX` | `0 \| 1 \| 2 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10` | No | `-` | - |
1029
+ | `paddingY` | `0 \| 1 \| 2 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10` | No | `-` | - |
1030
+ | `pin` | `top \| bottom \| left \| right \| all` | No | `-` | Direction in which to absolutely pin the box. |
1031
+ | `position` | `ResponsiveProp<fixed \| static \| relative \| absolute \| sticky>` | No | `-` | - |
1032
+ | `pressed` | `boolean` | No | `-` | Is the element being pressed. Primarily a mobile feature, but can be used on the web. |
1033
+ | `ref` | `any` | No | `-` | - |
1034
+ | `renderAsPressable` | `boolean` | No | `true if `as` is 'button' or 'a', otherwise false` | If true, the CardRoot will be rendered as a Pressable component. When false, renders as an HStack for layout purposes. |
1035
+ | `right` | `ResponsiveProp<Right<string \| number>>` | No | `-` | - |
1036
+ | `rowGap` | `0 \| 1 \| 2 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10` | No | `-` | - |
1037
+ | `style` | `CSSProperties` | No | `-` | - |
1038
+ | `styles` | `({ layoutContainer?: CSSProperties; contentContainer?: CSSProperties \| undefined; textContainer?: CSSProperties \| undefined; mediaContainer?: CSSProperties \| undefined; dismissButtonContainer?: CSSProperties \| undefined; } & { root?: CSSProperties \| undefined; }) \| undefined` | No | `-` | - |
1039
+ | `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. |
1040
+ | `testID` | `string` | No | `-` | Used to locate this element in unit and end-to-end tests. Under the hood, testID translates to data-testid on Web. On Mobile, testID stays the same - testID |
1041
+ | `textAlign` | `ResponsiveProp<center \| start \| end \| justify>` | No | `-` | - |
1042
+ | `textDecoration` | `ResponsiveProp<none \| underline \| overline \| line-through \| underline overline \| underline double>` | No | `-` | - |
1043
+ | `textTransform` | `ResponsiveProp<capitalize \| lowercase \| none \| uppercase>` | No | `-` | - |
1044
+ | `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. |
1045
+ | `top` | `ResponsiveProp<Top<string \| number>>` | No | `-` | - |
1046
+ | `transform` | `inherit \| none \| revert \| -moz-initial \| initial \| revert-layer \| unset` | No | `-` | - |
1047
+ | `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 |
1048
+ | `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 |
1049
+ | `userSelect` | `ResponsiveProp<text \| none \| auto \| all>` | No | `-` | - |
1050
+ | `visibility` | `ResponsiveProp<hidden \| visible>` | No | `-` | - |
1051
+ | `width` | `ResponsiveProp<Width<string \| number>>` | No | `-` | - |
1052
+ | `zIndex` | `inherit \| auto \| revert \| -moz-initial \| initial \| revert-layer \| unset` | No | `-` | - |
1053
+
1054
+