@rescui/card 0.14.0 → 0.14.1-RUI-293-Update-menu-component-6ca9d26d3.22

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,1397 @@
1
+ # cardCn
2
+
3
+ cardCn allows you to make any HTML tag appear as a card.
4
+
5
+ ## Usage
6
+
7
+ #### cardCn vs Cards Catalog
8
+
9
+ Use this guide to figure out what tools you need to implement a card on the website:
10
+
11
+ 1. If you need to use a standard card, use [cardCn](/components/card-cn/)
12
+ 2. If you need to use a non-standard card with minor changes, customize cardCn or build a custom [clickable](/cards/clickable/)/[non clickable (tiles)](/cards/tiles/) card using [Card Catalog](/cards/)
13
+ 3. If you need to use a non-standard card with major changes, build a custom card using [Card Catalog](/cards/) and [this guide](/cards/guide/)
14
+
15
+ ### Features showcase
16
+
17
+ #### General use
18
+
19
+ Card may be created on top of `div`, `button` and `a` elements. `div` element is used for `isClickable: false` cards. `a` element is used for `isClickable: true` cards with `href` attribute. `button` element is used for other `isClickable: true` cards. Grid and layout styles inside the card are not provided with generator, you need to set them up in your project. You can check out layout styles used in the examples below by inspecting a page in your browser.
20
+
21
+ #### Default card
22
+
23
+ No additional properties are added to the default card
24
+
25
+ ##### Properties:
26
+
27
+ ```
28
+ {
29
+ isClickable: false,
30
+ mode: classic,
31
+ theme: light,
32
+ padding: 24,
33
+ borderRadius: 8
34
+ }
35
+ ```
36
+
37
+ - Layout styles are not provided with `cardCn`
38
+ - [custom no-cardCn implementation](/cards/tiles/#base-example)
39
+
40
+ ```tsx
41
+ import { cardCn } from '@rescui/card';
42
+ import { textCn } from '@rescui/typography';
43
+ import cn from 'classnames';
44
+ import { PersonIcon, TeamIcon } from '@rescui/icons';
45
+ import avatarImage from '@/parts/card-cn/avatar.png';
46
+
47
+ const MyCard = () => {
48
+ return (
49
+ <div
50
+ className={cn(cardCn(), 'card-1')}
51
+ style={{ '--card-image-url': `url(${avatarImage.src})` }}
52
+ >
53
+ <div className={cn('card-1__header-wrapper')}>
54
+ <div className={'card-1__image'} />
55
+ <div className="card-1__heading-info">
56
+ <h3 className={cn(textCn('rs-h3'), 'card-1__heading')}>
57
+ Konstantin Konstantinopolsky
58
+ </h3>
59
+ </div>
60
+ </div>
61
+ <p className={cn(textCn('rs-text-2'), 'card-1__text')}>
62
+ Lorem ipsum dolor sit amet,duis voluptate velit esse cillum dolore empor
63
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
64
+ quis nostrud. Lorem ipsum dolor.
65
+ </p>
66
+ <div className="card-1__tags">
67
+ <span className={cn(textCn('rs-text-3'), 'card-1__text')}>
68
+ <PersonIcon size={'s'} className={'card-1__icon'} /> Murcia, Spain
69
+ </span>
70
+ <span className={cn(textCn('rs-text-3'), 'card-1__text')}>
71
+ <TeamIcon size={'s'} className={'card-1__icon'} /> Design
72
+ </span>
73
+ </div>
74
+ </div>
75
+ );
76
+ };
77
+
78
+ render(<MyCard />);
79
+ ```
80
+
81
+ ```postcss
82
+ .card-1 {
83
+ max-width: 406px;
84
+ }
85
+
86
+ .card-1__header-wrapper {
87
+ display: flex;
88
+ flex-direction: row;
89
+ }
90
+
91
+ .card-1__image {
92
+ min-width: 72px;
93
+ height: 72px;
94
+ max-width: 100%;
95
+ flex-basis: auto;
96
+ background: transparent var(--card-image-url) no-repeat 0 0;
97
+ background-size: 72px 72px;
98
+ }
99
+
100
+ .card-1__heading-info {
101
+ flex-grow: 1;
102
+ margin-left: 16px;
103
+ }
104
+
105
+ .card-1__heading {
106
+ margin-top: 8px;
107
+ }
108
+
109
+ .card-1__text {
110
+ margin-top: 16px;
111
+ }
112
+
113
+ .card-1__icon {
114
+ margin-right: 4px;
115
+
116
+ vertical-align: bottom;
117
+ }
118
+
119
+ .card-1__tags {
120
+ display: flex;
121
+ flex-wrap: wrap;
122
+ gap: 12px;
123
+ margin-top: 48px;
124
+ margin-right: -2px;
125
+ margin-left: -2px;
126
+ }
127
+ ```
128
+
129
+ #### Default clickable card
130
+
131
+ - `isClickable: true`
132
+ - `button` element is used instead of the `div` element
133
+ - Layout styles are not provided with `cardCn`
134
+ - [custom no-cardCn implementation](/cards/clickable/#base-example)
135
+
136
+ ```tsx
137
+ import { cardCn } from '@rescui/card';
138
+ import { textCn } from '@rescui/typography';
139
+ import cn from 'classnames';
140
+ import { PersonIcon, TeamIcon } from '@rescui/icons';
141
+ import avatarImage from '@/parts/card-cn/avatar.png';
142
+
143
+ const MyCard = () => {
144
+ return (
145
+ <button
146
+ type="button"
147
+ className={cn(cardCn({ isClickable: true }), 'card-1-clickable')}
148
+ style={{ '--card-image-url': `url(${avatarImage.src})` }}
149
+ >
150
+ <div className={cn('card-1-clickable__header-wrapper')}>
151
+ <div className={'card-1-clickable__image'} />
152
+ <div className="card-1-clickable__heading-info">
153
+ <h3 className={cn(textCn('rs-h3'), 'card-1-clickable__heading')}>
154
+ Konstantin Konstantinopolsky
155
+ </h3>
156
+ </div>
157
+ </div>
158
+ <p className={cn(textCn('rs-text-2'), 'card-1-clickable__text')}>
159
+ Lorem ipsum dolor sit amet,duis voluptate velit esse cillum dolore empor
160
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
161
+ quis nostrud. Lorem ipsum dolor.
162
+ </p>
163
+ <div className="card-1-clickable__tags">
164
+ <span className={cn(textCn('rs-text-3'), 'card-1-clickable__text')}>
165
+ <PersonIcon size={'s'} className={'card-1-clickable__icon'} /> Murcia,
166
+ Spain
167
+ </span>
168
+ <span className={cn(textCn('rs-text-3'), 'card-1-clickable__text')}>
169
+ <TeamIcon size={'s'} className={'card-1-clickable__icon'} /> Design
170
+ </span>
171
+ </div>
172
+ </button>
173
+ );
174
+ };
175
+
176
+ render(<MyCard />);
177
+ ```
178
+
179
+ ```postcss
180
+ .card-1-clickable {
181
+ max-width: 406px;
182
+ }
183
+
184
+ .card-1-clickable__header-wrapper {
185
+ display: flex;
186
+ flex-direction: row;
187
+ }
188
+
189
+ .card-1-clickable__image {
190
+ min-width: 72px;
191
+ height: 72px;
192
+ max-width: 100%;
193
+ flex-basis: auto;
194
+ background: transparent var(--card-image-url) no-repeat 0 0;
195
+ background-size: 72px 72px;
196
+ }
197
+
198
+ .card-1-clickable__heading-info {
199
+ flex-grow: 1;
200
+ margin-left: 16px;
201
+ }
202
+
203
+ .card-1-clickable__heading {
204
+ margin-top: 8px;
205
+ }
206
+
207
+ .card-1-clickable__text {
208
+ margin-top: 16px;
209
+ }
210
+
211
+ .card-1-clickable__icon {
212
+ margin-right: 4px;
213
+
214
+ vertical-align: bottom;
215
+ }
216
+
217
+ .card-1-clickable__tags {
218
+ display: flex;
219
+ flex-wrap: wrap;
220
+ gap: 12px;
221
+ margin-top: 48px;
222
+ margin-right: -2px;
223
+ margin-left: -2px;
224
+ }
225
+ ```
226
+
227
+ #### Theme dark
228
+
229
+ - Layout styles are not provided with `cardCn`
230
+ - Typography styles are not provided with this mode. Use `--rs-theme-dark` to get smart text styles
231
+ - `a` tag with `href` attribute is used instead of `div` element
232
+ - [custom no-cardCn implementation](/cards/clickable/#dark-theme)
233
+
234
+ ```tsx
235
+ import { cardCn } from '@rescui/card';
236
+ import { textCn } from '@rescui/typography';
237
+ import cn from 'classnames';
238
+ import { PersonIcon, TeamIcon } from '@rescui/icons';
239
+ import avatarImage from '@/parts/card-cn/avatar.png';
240
+
241
+ const MyCard = () => (
242
+ <section
243
+ style={{ background: '#27282c', '--rs-theme-dark': 1 }}
244
+ className="doc-section-with-paddings"
245
+ >
246
+ <a
247
+ href={'#'}
248
+ className={cn(cardCn({ isClickable: true }), 'card-2')}
249
+ style={{ '--card-image-url': `url(${avatarImage.src})` }}
250
+ >
251
+ <div className={cn('card-2__header-wrapper')}>
252
+ <div className={'card-2__image'} />
253
+ <div className="card-2__heading-info">
254
+ <h3 className={cn(textCn('rs-h3'), 'card-2__heading')}>
255
+ Konstantin Konstantinopolsky
256
+ </h3>
257
+ </div>
258
+ </div>
259
+ <p className={cn(textCn('rs-text-2'), 'card-2__text')}>
260
+ Lorem ipsum dolor sit amet,duis voluptate velit esse cillum dolore empor
261
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
262
+ quis nostrud. Lorem ipsum dolor.
263
+ </p>
264
+ <div className="card-2__tags">
265
+ <span className={cn(textCn('rs-text-3'), 'card-2__text')}>
266
+ <PersonIcon size={'s'} className={'card-2__icon'} /> Murcia, Spain
267
+ </span>
268
+ <span className={cn(textCn('rs-text-3'), 'card-2__text')}>
269
+ <TeamIcon size={'s'} className={'card-2__icon'} /> Design
270
+ </span>
271
+ </div>
272
+ </a>
273
+ </section>
274
+ );
275
+
276
+ render(<MyCard />);
277
+ ```
278
+
279
+ ```postcss
280
+ .card-2 {
281
+ max-width: 406px;
282
+ }
283
+
284
+ .card-2__header-wrapper {
285
+ display: flex;
286
+ flex-direction: row;
287
+ }
288
+
289
+ .card-2__image {
290
+ min-width: 72px;
291
+ height: 72px;
292
+ max-width: 100%;
293
+ flex-basis: auto;
294
+ background: transparent var(--card-image-url) no-repeat 0 0;
295
+ background-size: 72px 72px;
296
+ }
297
+
298
+ .card-2__heading-info {
299
+ flex-grow: 1;
300
+ margin-left: 16px;
301
+ }
302
+
303
+ .card-2__heading {
304
+ margin-top: 8px;
305
+ }
306
+
307
+ .card-2__heading_two-lines {
308
+ height: 56px;
309
+ position: relative;
310
+ display: -webkit-box;
311
+ -webkit-box-orient: vertical;
312
+ -webkit-line-clamp: 2;
313
+ overflow: hidden;
314
+ }
315
+
316
+ .card-2__text {
317
+ margin-top: 16px;
318
+ }
319
+
320
+ .card-2__icon {
321
+ margin-right: 4px;
322
+
323
+ vertical-align: bottom;
324
+ }
325
+
326
+ .card-2__tags {
327
+ display: flex;
328
+ flex-wrap: wrap;
329
+ gap: 12px;
330
+ margin-top: 48px;
331
+ margin-right: -2px;
332
+ margin-left: -2px;
333
+ }
334
+ ```
335
+
336
+ #### Theme dark with ThemeProvider
337
+
338
+ If you use [`ThemeContext`](/utils/ui-contexts/#themecontext) to manage the theme of your application, use `useCardCn` hook.
339
+
340
+ ```tsx
341
+ import { useCardCn } from '@rescui/card';
342
+ import { useTextStyles } from '@rescui/typography';
343
+ import { ThemeProvider } from '@rescui/ui-contexts';
344
+ import cn from 'classnames';
345
+ import { PersonIcon, TeamIcon } from '@rescui/icons';
346
+ import avatarImage from '@/parts/card-cn/avatar.png';
347
+
348
+ const MyCard = () => {
349
+ const cardCn = useCardCn();
350
+ const textCn = useTextStyles();
351
+
352
+ return (
353
+ <section
354
+ style={{ background: '#27282c' }}
355
+ className="doc-section-with-paddings"
356
+ >
357
+ <a
358
+ href={'#'}
359
+ className={cn(cardCn({ isClickable: true }), 'card-2-prv')}
360
+ style={{ '--card-image-url': `url(${avatarImage.src})` }}
361
+ >
362
+ <div className={cn('card-2-prv__header-wrapper')}>
363
+ <div className={'card-2-prv__image'} />
364
+ <div className="card-2-prv__heading-info">
365
+ <h3 className={cn(textCn('rs-h3'), 'card-2-prv__heading')}>
366
+ Konstantin Konstantinopolsky
367
+ </h3>
368
+ </div>
369
+ </div>
370
+ <p className={cn(textCn('rs-text-2'), 'card-2-prv__text')}>
371
+ Lorem ipsum dolor sit amet,duis voluptate velit esse cillum dolore
372
+ empor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
373
+ veniam, quis nostrud. Lorem ipsum dolor.
374
+ </p>
375
+ <div className="card-2-prv__tags">
376
+ <span className={cn(textCn('rs-text-3'), 'card-2-prv__text')}>
377
+ <PersonIcon size={'s'} className={'card-2-prv__icon'} /> Murcia,
378
+ Spain
379
+ </span>
380
+ <span className={cn(textCn('rs-text-3'), 'card-2-prv__text')}>
381
+ <TeamIcon size={'s'} className={'card-2-prv__icon'} /> Design
382
+ </span>
383
+ </div>
384
+ </a>
385
+ </section>
386
+ );
387
+ };
388
+
389
+ render(
390
+ <ThemeProvider theme="dark">
391
+ <MyCard />
392
+ </ThemeProvider>
393
+ );
394
+ ```
395
+
396
+ ```postcss
397
+ .card-2-prv {
398
+ max-width: 406px;
399
+ }
400
+
401
+ .card-2-prv__header-wrapper {
402
+ display: flex;
403
+ flex-direction: row;
404
+ }
405
+
406
+ .card-2-prv__image {
407
+ min-width: 72px;
408
+ height: 72px;
409
+ max-width: 100%;
410
+ flex-basis: auto;
411
+ background: transparent var(--card-image-url) no-repeat 0 0;
412
+ background-size: 72px 72px;
413
+ }
414
+
415
+ .card-2-prv__heading-info {
416
+ flex-grow: 1;
417
+ margin-left: 16px;
418
+ }
419
+
420
+ .card-2-prv__heading {
421
+ margin-top: 8px;
422
+ }
423
+
424
+ .card-2-prv__heading_two-lines {
425
+ height: 56px;
426
+ position: relative;
427
+ display: -webkit-box;
428
+ -webkit-box-orient: vertical;
429
+ -webkit-line-clamp: 2;
430
+ overflow: hidden;
431
+ }
432
+
433
+ .card-2-prv__text {
434
+ margin-top: 16px;
435
+ }
436
+
437
+ .card-2-prv__icon {
438
+ margin-right: 4px;
439
+
440
+ vertical-align: bottom;
441
+ }
442
+
443
+ .card-2-prv__tags {
444
+ display: flex;
445
+ flex-wrap: wrap;
446
+ gap: 12px;
447
+ margin-top: 48px;
448
+ margin-right: -2px;
449
+ margin-left: -2px;
450
+ }
451
+ ```
452
+
453
+ #### Mode `rock`
454
+
455
+ - Can be used with both `light` and `dark` themes
456
+ - Combine with `theme` property to get `dark-rock` cards
457
+ - Typography color styles are provided with rock mode
458
+ - **Avoid** using `rock` mode for non-clickable cards
459
+ - [custom no-cardCn implementation](/cards/clickable/#rock-mode)
460
+
461
+ ```tsx
462
+ import { cardCn } from '@rescui/card';
463
+ import { textCn } from '@rescui/typography';
464
+ import cn from 'classnames';
465
+ import { PersonIcon, TeamIcon } from '@rescui/icons';
466
+ import avatarImage from '@/parts/card-cn/avatar.png';
467
+
468
+ const MyCard = () => {
469
+ return (
470
+ <button
471
+ type="button"
472
+ className={cn(cardCn({ mode: 'rock', isClickable: true }), 'card-3')}
473
+ style={{ '--card-image-url': `url(${avatarImage.src})` }}
474
+ >
475
+ <div className={cn('card-3__header-wrapper')}>
476
+ <div className={'card-3__image'} />
477
+ <div className="card-3__heading-info">
478
+ <h3 className={cn(textCn('rs-h3'), 'card-3__heading')}>
479
+ Konstantin Konstantinopolsky
480
+ </h3>
481
+ </div>
482
+ </div>
483
+ <p className={cn(textCn('rs-text-2'), 'card-3__text')}>
484
+ Lorem ipsum dolor sit amet,duis voluptate velit esse cillum dolore empor
485
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
486
+ quis nostrud. Lorem ipsum dolor.
487
+ </p>
488
+ <div className="rs-docs-offset-top-48 rs-docs-row">
489
+ <span
490
+ className={cn(textCn('rs-text-3'), 'rs-docs-col card-3__text-small')}
491
+ >
492
+ <PersonIcon size={'s'} className={'card-3__icon'} /> Murcia, Spain
493
+ </span>
494
+ <span
495
+ className={cn(textCn('rs-text-3'), 'rs-docs-col card-3__text-small')}
496
+ >
497
+ <TeamIcon size={'s'} className={'card-3__icon'} /> Design
498
+ </span>
499
+ </div>
500
+ </button>
501
+ );
502
+ };
503
+
504
+ render(<MyCard />);
505
+ ```
506
+
507
+ ```postcss
508
+ .card-3 {
509
+ max-width: 406px;
510
+ }
511
+
512
+ .card-3__header-wrapper {
513
+ display: flex;
514
+ flex-direction: row;
515
+ }
516
+
517
+ .card-3__image {
518
+ min-width: 72px;
519
+ height: 72px;
520
+ max-width: 100%;
521
+ flex-basis: auto;
522
+ background: transparent var(--card-image-url) no-repeat 0 0;
523
+ background-size: 72px 72px;
524
+ }
525
+
526
+ .card-3__heading-info {
527
+ flex-grow: 1;
528
+ margin-left: 16px;
529
+ }
530
+
531
+ .card-3__heading {
532
+ margin-top: 8px;
533
+ }
534
+
535
+ .card-3__heading_two-lines {
536
+ height: 56px;
537
+ position: relative;
538
+ display: -webkit-box;
539
+ -webkit-box-orient: vertical;
540
+ -webkit-line-clamp: 2;
541
+ overflow: hidden;
542
+ }
543
+
544
+ .card-3__text {
545
+ margin-top: 16px;
546
+ }
547
+
548
+ .card-3__icon {
549
+ margin-right: 4px;
550
+
551
+ vertical-align: bottom;
552
+ }
553
+
554
+ .card-3__tags {
555
+ display: flex;
556
+ flex-wrap: wrap;
557
+ gap: 12px;
558
+ margin-top: 48px;
559
+ margin-right: -2px;
560
+ margin-left: -2px;
561
+ }
562
+ ```
563
+
564
+ #### With Glow-hover
565
+
566
+ - `Glow-hover` card type does not include `glow-hover` effect itself - it should be added alongside
567
+ - Can be used with both for `light` and `dark` theme
568
+ - Can be used with both `clickable` and `non-clickable` cards
569
+ - You can use different glow-hover presets on cards. See more at [@rescui/useGlowHover](/components/use-glow-hover/presets/)
570
+ - **Avoid** using with 'rock' mode
571
+ - **Avoid** using on cards with `image` sections
572
+ - **Avoid** using on cards with more than one action as this is a bad UX pattern. For example, avoid 'glow-hover' in a `Buy` card with a button and link
573
+ - [custom no-cardCn implementation](/cards/clickable/#with-glow-hover)
574
+
575
+ ```tsx
576
+ import { cardCn } from '@rescui/card';
577
+ import { textCn } from '@rescui/typography';
578
+ import cn from 'classnames';
579
+ import { PersonIcon, TeamIcon } from '@rescui/icons';
580
+ import { useGlowHover } from '@rescui/use-glow-hover';
581
+ import avatarImage from '@/parts/card-cn/avatar.png';
582
+
583
+ const MyCard = () => {
584
+ const cardRef = useGlowHover({ lightColor: '#5B96EF', enableBurst: true });
585
+
586
+ return (
587
+ <div
588
+ ref={cardRef}
589
+ className={cn(cardCn({ isClickable: true }), 'card-4')}
590
+ style={{ '--card-image-url': `url(${avatarImage.src})` }}
591
+ >
592
+ <div className={cn('card-4__header-wrapper')}>
593
+ <div className={'card-4__image'} />
594
+ <div className="card-4__heading-info">
595
+ <h3 className={cn(textCn('rs-h3'), 'card-4__heading')}>
596
+ Konstantin Konstantinopolsky
597
+ </h3>
598
+ </div>
599
+ </div>
600
+ <p className={cn(textCn('rs-text-2'), 'card-4__text')}>
601
+ Lorem ipsum dolor sit amet,duis voluptate velit esse cillum dolore empor
602
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
603
+ quis nostrud. Lorem ipsum dolor.
604
+ </p>
605
+ <div className="rs-docs-offset-top-48 rs-docs-row">
606
+ <span
607
+ className={cn(textCn('rs-text-3'), 'rs-docs-col card-4__text-small')}
608
+ >
609
+ <PersonIcon size={'s'} className={'card-4__icon'} /> Murcia, Spain
610
+ </span>
611
+ <span
612
+ className={cn(textCn('rs-text-3'), 'rs-docs-col card-4__text-small')}
613
+ >
614
+ <TeamIcon size={'s'} className={'card-4__icon'} /> Design
615
+ </span>
616
+ </div>
617
+ </div>
618
+ );
619
+ };
620
+
621
+ render(<MyCard />);
622
+ ```
623
+
624
+ ```postcss
625
+ .card-4 {
626
+ max-width: 406px;
627
+ }
628
+
629
+ .card-4__header-wrapper {
630
+ display: flex;
631
+ flex-direction: row;
632
+ }
633
+
634
+ .card-4__image {
635
+ min-width: 72px;
636
+ height: 72px;
637
+ max-width: 100%;
638
+ flex-basis: auto;
639
+ background: transparent var(--card-image-url) no-repeat 0 0;
640
+ background-size: 72px 72px;
641
+ }
642
+
643
+ .card-4__heading-info {
644
+ flex-grow: 1;
645
+ margin-left: 16px;
646
+ }
647
+
648
+ .card-4__heading {
649
+ margin-top: 8px;
650
+ }
651
+
652
+ .card-4__heading_two-lines {
653
+ height: 56px;
654
+ position: relative;
655
+ display: -webkit-box;
656
+ -webkit-box-orient: vertical;
657
+ -webkit-line-clamp: 2;
658
+ overflow: hidden;
659
+ }
660
+
661
+ .card-4__text {
662
+ margin-top: 16px;
663
+ }
664
+
665
+ .card-4__icon {
666
+ margin-right: 4px;
667
+
668
+ vertical-align: bottom;
669
+ }
670
+
671
+ .card-4__tags {
672
+ display: flex;
673
+ flex-wrap: wrap;
674
+ gap: 12px;
675
+ margin-top: 48px;
676
+ margin-right: -2px;
677
+ margin-left: -2px;
678
+ }
679
+ ```
680
+
681
+ #### With image via img tag
682
+
683
+ - Use `cardImageCn` on the section with an image
684
+ - Use `disableBorderTransparency` prop on the card
685
+ - Section images always go first
686
+ - Image height is static and equals `188px` + paddings
687
+ - Full container size depends on card paddings and will change accordingly
688
+ - Provide image in `img src` property
689
+ - Can be used with both light and dark themes
690
+ - Can be used only with `classic` mode now. Use it with `rock` mode at your own risk
691
+ - **Avoid** using with GlowHover effect
692
+ - **Avoid** using if you need text on images. Instead, use card image with DIV solution
693
+ - [custom no-cardCn implementation](/cards/clickable/#newsletter-cards)
694
+
695
+ ```tsx
696
+ import { cardCn, cardImageCn } from '@rescui/card';
697
+ import { textCn } from '@rescui/typography';
698
+ import cn from 'classnames';
699
+ import { Button } from '@rescui/button';
700
+ import { Input } from '@rescui/input';
701
+ import testImage from '@/parts/card-cn/card-background.jpg';
702
+
703
+ const MyCard = () => {
704
+ return (
705
+ <div
706
+ className={cardCn({ isClickable: true, disableBorderTransparency: true })}
707
+ style={{ maxWidth: 406 }}
708
+ >
709
+ <span className={cardImageCn({ cardImageType: 'cardImageImg' })}>
710
+ <img src={testImage.src} alt={'test img'} />
711
+ </span>
712
+ <h3 className={textCn('rs-h3')}>
713
+ JetBrains Community Newsletter (Monthly)
714
+ </h3>
715
+ <Input placeholder={'Email'} className="rs-docs-offset-top-8" />
716
+ <p className={cn(textCn('rs-text-3'), 'rs-docs-offset-top-12')}>
717
+ By submitting this form, I agree that my name, email address, and
718
+ location data may be used by JetBrains to send me newsletters, including
719
+ commercial communications, and to process my personal data for this
720
+ purpose. I agree that JetBrains may process said data using third-party
721
+ services for this purpose in accordance with the JetBrains Privacy
722
+ Policy. I understand that I can revoke this consent at any time in my
723
+ profile. In addition, an unsubscribe link is included in each email.
724
+ </p>
725
+ <Button mode="rock" className={'rs-docs-offset-top-24'}>
726
+ Subscribe
727
+ </Button>
728
+ </div>
729
+ );
730
+ };
731
+
732
+ render(<MyCard />);
733
+ ```
734
+
735
+ #### With image via div tag
736
+
737
+ - Use if you need to use an image with text
738
+ - Use `cardImageCn` on sections with an image
739
+ - Use `disableBorderTransparency` prop on the card
740
+ - Section image always go first
741
+ - Image height is static and equals `188px` + paddings
742
+ - Full container size depends on card paddings and will change accordingly
743
+ - Provide image in `css` or `inline styles` with `background-image` property
744
+ - Can be used with both `light` and `dark` themes
745
+ - Can be used only with `classic` mode now. Use it with `rock` mode at your own risk
746
+ - **Avoid** using with GlowHover effect
747
+
748
+ ```tsx
749
+ import { cardCn, cardImageCn } from '@rescui/card';
750
+ import { textCn } from '@rescui/typography';
751
+ import cn from 'classnames';
752
+ import { Button } from '@rescui/button';
753
+ import { Input } from '@rescui/input';
754
+ import testImage from '@/parts/card-cn/card-background.jpg';
755
+
756
+ const MyCard = () => {
757
+ return (
758
+ <div
759
+ className={cardCn({
760
+ isClickable: false,
761
+ disableBorderTransparency: true
762
+ })}
763
+ style={{ maxWidth: 406 }}
764
+ >
765
+ <div
766
+ className={cardImageCn({ cardImageType: 'cardImageDiv' })}
767
+ style={{ backgroundImage: `url(${testImage.src})` }}
768
+ >
769
+ <div style={{ '--rs-theme-dark': 1 }} className={textCn('rs-h3')}>
770
+ IntelliJ Idea
771
+ </div>
772
+ </div>
773
+ <h3 className={textCn('rs-h3')}>
774
+ JetBrains Community Newsletter (Monthly)
775
+ </h3>
776
+ <Input placeholder="Email" className="rs-docs-offset-top-8" />
777
+ <p className={cn(textCn('rs-text-3'), 'rs-docs-offset-top-12')}>
778
+ By submitting this form, I agree that my name, email address, and
779
+ location data may be used by JetBrains to send me newsletters, including
780
+ commercial communications, and to process my personal data for this
781
+ purpose. I agree that JetBrains may process said data using third-party
782
+ services for this purpose in accordance with the JetBrains Privacy
783
+ Policy. I understand that I can revoke this consent at any time in my
784
+ profile. In addition, an unsubscribe link is included in each email.
785
+ </p>
786
+ <Button mode="rock" className={'rs-docs-offset-top-24'}>
787
+ Subscribe
788
+ </Button>
789
+ </div>
790
+ );
791
+ };
792
+
793
+ render(<MyCard />);
794
+ ```
795
+
796
+ #### Without fixed image height
797
+
798
+ Use `disableFixedHeight: true` option if an aspect ratio of the image is important
799
+
800
+ ```tsx
801
+ import { cardCn, cardImageCn } from '@rescui/card';
802
+ import { textCn } from '@rescui/typography';
803
+ import cn from 'classnames';
804
+ import testImage from '@/parts/card-cn/card-fleet-background.png';
805
+
806
+ const MyCard = () => {
807
+ return (
808
+ <div
809
+ className={cardCn({ isClickable: true, disableBorderTransparency: true })}
810
+ style={{ maxWidth: 506 }}
811
+ >
812
+ <span
813
+ className={cardImageCn({
814
+ cardImageType: 'cardImageImg',
815
+ disableFixedHeight: true
816
+ })}
817
+ >
818
+ <img src={testImage.src} alt={'test img'} />
819
+ </span>
820
+ <h3 className={textCn('rs-h3')}>Fleet landing page</h3>
821
+ <p className={cn(textCn('rs-text-2'), 'rs-docs-offset-top-16')}>
822
+ Stylish next-generation IDE landing page with some image animation on
823
+ scroll and subscribing form
824
+ </p>
825
+ <p className={cn(textCn('rs-text-2'), 'rs-docs-offset-top-24')}>
826
+ <a
827
+ className={textCn('rs-link', { external: true, mode: 'standalone' })}
828
+ >
829
+ Explore
830
+ </a>
831
+ </p>
832
+ </div>
833
+ );
834
+ };
835
+
836
+ render(<MyCard />);
837
+ ```
838
+
839
+ #### With image on the side
840
+
841
+ - use custom CSS to position an image
842
+ - use `disableBorderTransparency` prop on the card
843
+ - image takes a fixed percentage of the card width
844
+ - transforms into a vertical card on `--sm`
845
+
846
+ ```tsx
847
+ import { cardCn } from '@rescui/card';
848
+ import { textCn } from '@rescui/typography';
849
+ import cn from 'classnames';
850
+ import testImage from '@/parts/card-cn/card-fleet-background.png';
851
+
852
+ const MyCard = () => {
853
+ return (
854
+ <div
855
+ className={cardCn({ disableBorderTransparency: true })}
856
+ style={{ maxWidth: 900 }}
857
+ >
858
+ <div className="card-with-img-on-left">
859
+ <span className="card-with-img-on-left__img">
860
+ <img src={testImage.src} alt={'test img'} />
861
+ </span>
862
+ <div>
863
+ <h3 className={textCn('rs-h3')}>Fleet landing page</h3>
864
+ <p className={cn(textCn('rs-text-2'), 'rs-docs-offset-top-16')}>
865
+ Stylish next-generation IDE landing page with some image animation
866
+ on scroll and subscribing form
867
+ </p>
868
+ <p className={cn(textCn('rs-text-2'), 'rs-docs-offset-top-24')}>
869
+ <a
870
+ className={textCn('rs-link', {
871
+ external: true,
872
+ mode: 'standalone'
873
+ })}
874
+ >
875
+ Explore
876
+ </a>
877
+ </p>
878
+ </div>
879
+ </div>
880
+ </div>
881
+ );
882
+ };
883
+
884
+ render(<MyCard />);
885
+ ```
886
+
887
+ ```postcss
888
+ .card-with-img-on-left {
889
+ display: flex;
890
+
891
+ @media (--sm) {
892
+ flex-direction: column;
893
+ }
894
+
895
+ &__img {
896
+ position: relative;
897
+ top: calc(-1 * var(--rs-out-card-padding));
898
+ left: calc(-1 * var(--rs-out-card-padding));
899
+
900
+ display: flex;
901
+ flex: 1 0 auto;
902
+ justify-content: center;
903
+ align-items: center;
904
+
905
+ width: calc(50% + var(--rs-out-card-padding));
906
+ margin-bottom: calc(-2 * var(--rs-out-card-padding));
907
+
908
+ @media (--sm) {
909
+ top: calc(-1 * var(--rs-out-card-padding));
910
+ left: calc(-1 * var(--rs-out-card-padding));
911
+
912
+ width: calc(100% + var(--rs-out-card-padding) * 2);
913
+ margin-bottom: 0;
914
+ }
915
+
916
+ img {
917
+ width: 100%;
918
+ height: 100%;
919
+ object-fit: cover;
920
+ }
921
+ }
922
+ }
923
+ ```
924
+
925
+ #### With Different border radius
926
+
927
+ - Card can use the following border-radius values with props: `0`, `8`, `16`, and `24`
928
+ - Default border radius value is `8`
929
+ - If you wish to substitute border-radius property in your project, use `--rs-card-border-radius` css-var
930
+
931
+ ```tsx
932
+ import { cardCn } from '@rescui/card';
933
+ import { textCn } from '@rescui/typography';
934
+ import cn from 'classnames';
935
+ import { WebstormLogo } from '@jetbrains/logos/react';
936
+ import { Button } from '@rescui/button';
937
+
938
+ const MyCards = () => {
939
+ return (
940
+ <div className="rs-docs-row">
941
+ <div className="rs-docs-col-auto-fill" style={{ maxWidth: 400 }}>
942
+ <div className={cardCn({ isClickable: true, borderRadius: 0 })}>
943
+ <WebstormLogo style={{ width: 64, height: 64 }} />
944
+ <h3 className={cn(textCn('rs-h3'), 'rs-docs-offset-top-16')}>
945
+ WebStorm
946
+ </h3>
947
+ <p className={cn(textCn('rs-text-2'), 'rs-docs-offset-top-16')}>
948
+ The JavaScript and TypeScript IDE
949
+ </p>
950
+ <div
951
+ className={
952
+ 'rs-docs-row rs-docs-row_vertical-center rs-docs-offset-top-48'
953
+ }
954
+ >
955
+ <Button mode="rock" className={'rs-docs-col rs-docs-col-inline'}>
956
+ Buy
957
+ </Button>
958
+ <span
959
+ className={cn(
960
+ textCn('rs-link', { mode: 'standalone' }),
961
+ 'rs-docs-col rs-docs-col-inline'
962
+ )}
963
+ >
964
+ Learn more
965
+ </span>
966
+ </div>
967
+ </div>
968
+ </div>
969
+
970
+ <div className="rs-docs-col-auto-fill" style={{ maxWidth: 400 }}>
971
+ <div className={cardCn({ isClickable: true })}>
972
+ <WebstormLogo style={{ width: 64, height: 64 }} />
973
+ <h3 className={cn(textCn('rs-h3'), 'rs-docs-offset-top-16')}>
974
+ WebStorm
975
+ </h3>
976
+ <p className={cn(textCn('rs-text-2'), 'rs-docs-offset-top-16')}>
977
+ The JavaScript and TypeScript IDE
978
+ </p>
979
+ <div
980
+ className={
981
+ 'rs-docs-row rs-docs-row_vertical-center rs-docs-offset-top-48'
982
+ }
983
+ >
984
+ <Button mode="rock" className={'rs-docs-col rs-docs-col-inline'}>
985
+ Buy
986
+ </Button>
987
+ <span
988
+ className={cn(
989
+ textCn('rs-link', { mode: 'standalone' }),
990
+ 'rs-docs-col rs-docs-col-inline'
991
+ )}
992
+ >
993
+ Learn more
994
+ </span>
995
+ </div>
996
+ </div>
997
+ </div>
998
+ </div>
999
+ );
1000
+ };
1001
+
1002
+ render(<MyCards />);
1003
+ ```
1004
+
1005
+ #### With Different paddings
1006
+
1007
+ - Card can use the following padding values with props: `0` (set the correct padding manually), `16`, `24`, and `32`
1008
+ - Default border radius value is `24`
1009
+
1010
+ ```tsx
1011
+ import { cardCn } from '@rescui/card';
1012
+ import { textCn } from '@rescui/typography';
1013
+ import cn from 'classnames';
1014
+ import { Button } from '@rescui/button';
1015
+
1016
+ const MyCard = () => {
1017
+ return (
1018
+ <div
1019
+ className={cardCn({ isClickable: true, paddings: 32 })}
1020
+ style={{ maxWidth: 500 }}
1021
+ >
1022
+ <h2 className={textCn('rs-h2')}>All ReSharper Ultimate+Rider</h2>
1023
+ <p className={cn(textCn('rs-text-2'), 'rs-docs-offset-top-16')}>
1024
+ Lorem ipsum dolor sit amet,duis voluptate velit esse cillum dolore empor
1025
+ incididunt ut labore.
1026
+ </p>
1027
+ <p className={cn(textCn('rs-digits-2'), 'rs-docs-offset-top-16')}>
1028
+ $27 665.00
1029
+ </p>
1030
+ <p className={textCn('rs-text-3')}>/user 1st year</p>
1031
+
1032
+ <p className={cn(textCn('rs-text-3'), 'rs-docs-offset-top-16')}>
1033
+ $399.00 2nd year
1034
+ </p>
1035
+ <p className={textCn('rs-text-3')}>$299.00 3rd year onwards</p>
1036
+ <div
1037
+ className={
1038
+ 'rs-docs-row rs-docs-row_vertical-center rs-docs-offset-top-48'
1039
+ }
1040
+ >
1041
+ <Button mode="rock" className={'rs-docs-col rs-docs-col-inline'}>
1042
+ Buy
1043
+ </Button>
1044
+ <div className={'rs-docs-col rs-docs-col-auto-fill'}>
1045
+ <div className={'rs-docs-row rs-docs-row_right '}>
1046
+ <span
1047
+ className={cn(
1048
+ textCn('rs-link', { mode: 'standalone' }),
1049
+ 'rs-docs-col-inline '
1050
+ )}
1051
+ >
1052
+ Get quote
1053
+ </span>
1054
+ <span
1055
+ className={cn(
1056
+ textCn('rs-link', { mode: 'standalone' }),
1057
+ 'rs-docs-col rs-docs-col-inline'
1058
+ )}
1059
+ >
1060
+ Learn more
1061
+ </span>
1062
+ </div>
1063
+ </div>
1064
+ </div>
1065
+ </div>
1066
+ );
1067
+ };
1068
+
1069
+ render(<MyCard />);
1070
+ ```
1071
+
1072
+ #### With dark theme and every available property included
1073
+
1074
+ - This example of card (plugin content) contains all non-default properties
1075
+ - You can use `--rs-theme-dark` css variable to set the section theme. The card's theme will be set automatically
1076
+ - For plugin card layout **avoid** using plugin names longer than 2 lines
1077
+ - The layout in this example hides the rest of the name with `line-clamp` css property
1078
+
1079
+ ```tsx
1080
+ import { cardCn } from '@rescui/card';
1081
+ import { textCn } from '@rescui/typography';
1082
+ import cn from 'classnames';
1083
+ import { StarIcon } from '@rescui/icons';
1084
+ import { AmperLogo } from '@jetbrains/logos/react';
1085
+
1086
+ const PluginCard = () => {
1087
+ return (
1088
+ <section
1089
+ style={{ background: '#27282c', '--rs-theme-dark': 1 }}
1090
+ className="doc-section-with-paddings"
1091
+ >
1092
+ <div
1093
+ className={cn(
1094
+ cardCn({
1095
+ isClickable: true,
1096
+ paddings: 32,
1097
+ borderRadius: 24,
1098
+ mode: 'rock'
1099
+ }),
1100
+ 'card-5'
1101
+ )}
1102
+ >
1103
+ <div className={cn('card-5__header-wrapper')}>
1104
+ <AmperLogo className={'card-5__logo'} />
1105
+ <div className="card-5__heading-info">
1106
+ <h3 className={textCn('rs-h3')}>Amper</h3>
1107
+ <p className={cn(textCn('rs-text-3'), 'rs-docs-rating')}>
1108
+ {[1, 2, 3, 4, 5].map((e, i) => (
1109
+ <StarIcon
1110
+ key={`star${i}`}
1111
+ size={'m'}
1112
+ className={'rs-docs-offset-top-8 rs-docs-rating-item'}
1113
+ />
1114
+ ))}
1115
+ </p>
1116
+ </div>
1117
+ </div>
1118
+ <p className={cn(textCn('rs-text-2'), 'card-5__text')}>
1119
+ Provides support for Amper project configuration tool.
1120
+ </p>
1121
+ <div className="rs-docs-offset-top-48 rs-docs-row">
1122
+ <span
1123
+ className={cn(
1124
+ textCn('rs-text-3'),
1125
+ 'rs-docs-col rs-docs-col-auto-fill card-5__text-small'
1126
+ )}
1127
+ >
1128
+ 2,370 downloads
1129
+ </span>
1130
+ <span
1131
+ className={cn(
1132
+ textCn('rs-text-3'),
1133
+ 'rs-docs-col rs-docs-col-inline card-5__text-small'
1134
+ )}
1135
+ >
1136
+ Free
1137
+ </span>
1138
+ </div>
1139
+ </div>
1140
+ </section>
1141
+ );
1142
+ };
1143
+
1144
+ render(<PluginCard />);
1145
+ ```
1146
+
1147
+ ```postcss attached
1148
+ .card-5 {
1149
+ max-width: 406px;
1150
+ }
1151
+
1152
+ .card-5__header-wrapper {
1153
+ display: flex;
1154
+ flex-direction: row;
1155
+ }
1156
+
1157
+ .card-5__logo {
1158
+ min-width: 72px;
1159
+ height: 72px;
1160
+ max-width: 100%;
1161
+ flex-basis: auto;
1162
+ }
1163
+
1164
+ .card-5__heading-info {
1165
+ flex-grow: 1;
1166
+ margin-left: 16px;
1167
+ }
1168
+
1169
+ .card-5__text {
1170
+ margin-top: 16px;
1171
+ }
1172
+
1173
+ .card-5__icon {
1174
+ margin-right: 4px;
1175
+
1176
+ vertical-align: bottom;
1177
+ }
1178
+
1179
+ .card-5__tags {
1180
+ display: flex;
1181
+ flex-wrap: wrap;
1182
+ gap: 12px;
1183
+ margin-top: 48px;
1184
+ margin-right: -2px;
1185
+ margin-left: -2px;
1186
+ }
1187
+ ```
1188
+
1189
+ #### With action button inside
1190
+
1191
+ When you need to forward card states to the `Button` component inside, you can use `cardButtonCn` helper. Important details:
1192
+
1193
+ - This method only works for `isClickable: true` card
1194
+ - Avoid using more than one dynamic element cards like this
1195
+ - [Custom no-cardCn implementation](/cards/clickable/#with-action-button-inside)
1196
+
1197
+ ```tsx
1198
+ import cn from 'classnames';
1199
+ import { textCn } from '@rescui/typography';
1200
+ import { Button } from '@rescui/button';
1201
+ import { cardCn, cardButtonCn } from '@rescui/card';
1202
+
1203
+ const Demo = () => {
1204
+ return (
1205
+ <button
1206
+ type="button"
1207
+ onClick={() => console.log('Card onClick called')}
1208
+ className={cardCn({ isClickable: true })}
1209
+ style={{ maxWidth: 400 }}
1210
+ >
1211
+ <h3 className={textCn('rs-h3')}>Card title</h3>
1212
+ <p className={cn(textCn('rs-text-2'), 'rs-docs-offset-top-24')}>
1213
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab animi
1214
+ aspernatur autem commodi consequuntur esse laudantium nobis numquam
1215
+ officiis omnis, perferendis perspiciatis, possimus qui quidem, quis
1216
+ repellat tempore unde veniam?
1217
+ </p>
1218
+ <div className="rs-docs-offset-top-24">
1219
+ <Button notFocusable className={cardButtonCn()}>
1220
+ Click me
1221
+ </Button>
1222
+ </div>
1223
+ </button>
1224
+ );
1225
+ };
1226
+
1227
+ render(<Demo />);
1228
+ ```
1229
+
1230
+ #### With action link inside
1231
+
1232
+ When you need to forward card states to the `rs-link` inside, you can use `cardLinkCn` helper. Important details:
1233
+
1234
+ - This method works only for `isClickable: true` card
1235
+ - Avoid using more than one dynamic element cards like this
1236
+ - [Custom no-cardCn implementation](/cards/clickable/#with-action-link-inside)
1237
+
1238
+ ```tsx
1239
+ import cn from 'classnames';
1240
+ import { textCn } from '@rescui/typography';
1241
+ import { cardCn, cardLinkCn } from '@rescui/card';
1242
+
1243
+ const Demo = () => {
1244
+ return (
1245
+ <a
1246
+ href="#with-action-link-inside"
1247
+ className={cardCn({ isClickable: true })}
1248
+ style={{ maxWidth: 400 }}
1249
+ >
1250
+ <h3 className={textCn('rs-h3')}>Card title</h3>
1251
+ <p className={cn(textCn('rs-text-2'), 'rs-docs-offset-top-24')}>
1252
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab animi
1253
+ aspernatur autem commodi consequuntur esse laudantium nobis numquam
1254
+ officiis omnis, perferendis perspiciatis, possimus qui quidem, quis
1255
+ repellat tempore unde veniam?
1256
+ </p>
1257
+ <div className={cn(textCn('rs-text-2'), 'rs-docs-offset-top-24')}>
1258
+ <span
1259
+ className={cn(
1260
+ textCn('rs-link', { mode: 'standalone' }),
1261
+ cardLinkCn()
1262
+ )}
1263
+ >
1264
+ Click me
1265
+ </span>
1266
+ </div>
1267
+ </a>
1268
+ );
1269
+ };
1270
+
1271
+ render(<Demo />);
1272
+ ```
1273
+
1274
+ ## CSS API
1275
+
1276
+ ### Clickable cards
1277
+
1278
+ | Variable | Syntax | Description |
1279
+ | --- | --- | --- |
1280
+ | `--rs-card-padding` | `<length>` | Inner padding of the card |
1281
+ | `--rs-card-border-radius` | [border-radius](https://developer.mozilla.org/en-US/docs/Web/CSS/border-radius) | Border radius of the card |
1282
+ | `--rs-card-static-background` | [background](https://developer.mozilla.org/en-US/docs/Web/CSS/background) | Background of the card |
1283
+ | `--rs-card-static-border-width` | `<length>` | Border width of the card |
1284
+ | `--rs-card-static-border-color` | `<color>` | Border color of the card |
1285
+ | `--rs-card-hover-background` | [background](https://developer.mozilla.org/en-US/docs/Web/CSS/background) | Background of the card in the `:hover` state |
1286
+ | `--rs-card-hover-border-width` | `<length>` | Border width of the card in the `:hover` state |
1287
+ | `--rs-card-hover-border-color` | `<color>` | Border color of the card in the `:hover` state |
1288
+ | `--rs-card-focus-background` | [background](https://developer.mozilla.org/en-US/docs/Web/CSS/background) | Background of the card in the `:focus-visible` state |
1289
+ | `--rs-card-focus-border-width` | `<length>` | Border width of the card in the `:focus-visible` state |
1290
+ | `--rs-card-focus-border-color` | `<color>` | Border color of the card in the `:focus-visible` state |
1291
+ | `--rs-card-active-background` | [background](https://developer.mozilla.org/en-US/docs/Web/CSS/background) | Background of the card in the `:active` state |
1292
+ | `--rs-card-active-border-width` | `<length>` | Border width of the card in the `:active` state |
1293
+ | `--rs-card-active-border-color` | `<color>` | Border color of the card in the `:active` state |
1294
+
1295
+ ### Non-clickable tiles
1296
+
1297
+ | Variable | Syntax | Description |
1298
+ | --- | --- | --- |
1299
+ | `--rs-card-padding` | `<length>` | Inner padding of the card |
1300
+ | `--rs-card-border-radius` | [border-radius](https://developer.mozilla.org/en-US/docs/Web/CSS/border-radius) | Border radius of the card |
1301
+ | `--rs-card-static-background` | [background](https://developer.mozilla.org/en-US/docs/Web/CSS/background) | Background of the card |
1302
+ | `--rs-card-static-border-width` | `<length>` | Border width of the card |
1303
+ | `--rs-card-static-border-color` | `<color>` | Border color of the card |
1304
+
1305
+ ### Examples
1306
+
1307
+ #### Borderless card
1308
+
1309
+ Remember to customize variables for all states when customizing clickable card
1310
+
1311
+ [Custom no-cardCn implementation](/cards/clickable/#borderless-example)
1312
+
1313
+ ```tsx
1314
+ import cn from 'classnames';
1315
+ import { textCn } from '@rescui/typography';
1316
+ import { cardCn } from '@rescui/card';
1317
+
1318
+ const Demo = () => {
1319
+ return (
1320
+ <a
1321
+ href="#borderless-card"
1322
+ className={cn(cardCn({ isClickable: true }), 'borderless-card-cn')}
1323
+ style={{ maxWidth: 400 }}
1324
+ >
1325
+ <h3 className={textCn('rs-h3')}>Card title</h3>
1326
+ <p className={cn(textCn('rs-text-2'), 'rs-docs-offset-top-24')}>
1327
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab animi
1328
+ aspernatur autem commodi consequuntur esse laudantium nobis numquam
1329
+ officiis omnis, perferendis perspiciatis, possimus qui quidem, quis
1330
+ repellat tempore unde veniam?
1331
+ </p>
1332
+ </a>
1333
+ );
1334
+ };
1335
+
1336
+ render(<Demo />);
1337
+ ```
1338
+
1339
+ ```postcss attached
1340
+ .borderless-card-cn {
1341
+ --rs-card-static-border-width: 0px;
1342
+ --rs-card-hover-border-width: 0px;
1343
+ --rs-card-focus-border-width: 0px;
1344
+ --rs-card-active-border-width: 0px;
1345
+ --rs-card-static-background: var(--rs-color-grey-5);
1346
+ --rs-card-hover-background: var(--rs-color-grey-10);
1347
+ --rs-card-focus-background: var(--rs-color-grey-10);
1348
+ --rs-card-active-background: var(--rs-color-grey-20);
1349
+ }
1350
+ ```
1351
+
1352
+ #### Colorful border
1353
+
1354
+ ```tsx
1355
+ import cn from 'classnames';
1356
+ import { textCn } from '@rescui/typography';
1357
+ import { cardCn } from '@rescui/card';
1358
+
1359
+ const Demo = () => {
1360
+ return (
1361
+ <div style={{ padding: 48, background: '#000', '--rs-theme-dark': '1' }}>
1362
+ <a
1363
+ href="#colorful-border"
1364
+ className={cn(cardCn({ isClickable: true }), 'colorful-card-cn')}
1365
+ style={{ maxWidth: 400 }}
1366
+ >
1367
+ <h3 className={textCn('rs-h3')}>Card title</h3>
1368
+ <p className={cn(textCn('rs-text-2'), 'rs-docs-offset-top-24')}>
1369
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab animi
1370
+ aspernatur autem commodi consequuntur esse laudantium nobis numquam
1371
+ officiis omnis, perferendis perspiciatis, possimus qui quidem, quis
1372
+ repellat tempore unde veniam?
1373
+ </p>
1374
+ </a>
1375
+ </div>
1376
+ );
1377
+ };
1378
+
1379
+ render(<Demo />);
1380
+ ```
1381
+
1382
+ ```postcss
1383
+ .colorful-card-cn {
1384
+ --rs-card-static-border-width: 1px;
1385
+ --rs-card-hover-border-width: 2px;
1386
+ --rs-card-focus-border-width: 3px;
1387
+ --rs-card-active-border-width: 3px;
1388
+ --rs-card-static-border-color: rgba(141, 72, 255, 0.8);
1389
+ --rs-card-hover-border-color: rgba(141, 72, 255, 0.8);
1390
+ --rs-card-focus-border-color: rgba(141, 72, 255, 0.8);
1391
+ --rs-card-active-border-color: rgba(141, 72, 255, 0.8);
1392
+ --rs-card-static-background: transparent;
1393
+ --rs-card-hover-background: transparent;
1394
+ --rs-card-focus-background: transparent;
1395
+ --rs-card-active-background: transparent;
1396
+ }
1397
+ ```