@catalystsoftware/ui 1.0.5 → 1.0.7

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.
Files changed (155) hide show
  1. package/dist/data/data.tsx +29 -29
  2. package/dist/data/tailwind.config.js +3821 -261
  3. package/dist/data.tsx +29 -29
  4. package/package.json +4 -3
  5. package/components/catalyst-ui/buttons/burger.tsx +0 -207
  6. package/components/catalyst-ui/core/data-display/timeline.tsx +0 -210
  7. package/components/catalyst-ui/core/feedback/alert.tsx +0 -491
  8. package/components/catalyst-ui/core/feedback/spinner-1.tsx +0 -65
  9. package/components/catalyst-ui/core/feedback/toast.tsx +0 -1857
  10. package/components/catalyst-ui/core/navigation/menu.tsx +0 -164
  11. package/components/catalyst-ui/forms/toggle-class.tsx +0 -176
  12. package/components/catalyst-ui/hooks/use-copy-to-clipboard.tsx +0 -419
  13. package/components/catalyst-ui/hooks/use-counter.tsx +0 -13
  14. package/components/catalyst-ui/hooks/use-event-listener.tsx +0 -23
  15. package/components/catalyst-ui/hooks/use-export-markdown.tsx +0 -47
  16. package/components/catalyst-ui/hooks/use-focus.tsx +0 -17
  17. package/components/catalyst-ui/hooks/use-interval.tsx +0 -23
  18. package/components/catalyst-ui/hooks/use-is-client.tsx +0 -16
  19. package/components/catalyst-ui/hooks/use-media-query.tsx +0 -19
  20. package/components/catalyst-ui/hooks/use-mobile.tsx +0 -19
  21. package/components/catalyst-ui/hooks/use-resize-observer.tsx +0 -81
  22. package/components/catalyst-ui/hooks/use-timeout.tsx +0 -21
  23. package/components/catalyst-ui/hooks/use-timer.tsx +0 -209
  24. package/components/catalyst-ui/hooks/use-toggle.tsx +0 -12
  25. package/components/catalyst-ui/media/image.tsx +0 -13
  26. package/components/catalyst-ui/overlays/dual-sidebar.tsx +0 -4142
  27. package/components/catalyst-ui/overlays/sidebar-original.tsx +0 -726
  28. package/components/catalyst-ui/primitives/accordion.tsx +0 -250
  29. package/components/catalyst-ui/primitives/alert-dialog.tsx +0 -126
  30. package/components/catalyst-ui/primitives/aspect-ratio.tsx +0 -9
  31. package/components/catalyst-ui/primitives/avatar.tsx +0 -296
  32. package/components/catalyst-ui/primitives/badge.tsx +0 -57
  33. package/components/catalyst-ui/primitives/breadcrumb.tsx +0 -101
  34. package/components/catalyst-ui/primitives/button.tsx +0 -265
  35. package/components/catalyst-ui/primitives/calendar-v4.tsx +0 -208
  36. package/components/catalyst-ui/primitives/calendar.tsx +0 -295
  37. package/components/catalyst-ui/primitives/card.tsx +0 -618
  38. package/components/catalyst-ui/primitives/carousel.tsx +0 -238
  39. package/components/catalyst-ui/primitives/chart.tsx +0 -347
  40. package/components/catalyst-ui/primitives/checkbox.tsx +0 -225
  41. package/components/catalyst-ui/primitives/collapsible.tsx +0 -212
  42. package/components/catalyst-ui/primitives/command.tsx +0 -393
  43. package/components/catalyst-ui/primitives/context-menu.tsx +0 -236
  44. package/components/catalyst-ui/primitives/dialog.tsx +0 -471
  45. package/components/catalyst-ui/primitives/drawer.tsx +0 -761
  46. package/components/catalyst-ui/primitives/dropdown-menu.tsx +0 -290
  47. package/components/catalyst-ui/primitives/empty.tsx +0 -104
  48. package/components/catalyst-ui/primitives/field.tsx +0 -244
  49. package/components/catalyst-ui/primitives/hover-card.tsx +0 -124
  50. package/components/catalyst-ui/primitives/input-otp.tsx +0 -76
  51. package/components/catalyst-ui/primitives/input.tsx +0 -64
  52. package/components/catalyst-ui/primitives/item.tsx +0 -196
  53. package/components/catalyst-ui/primitives/kbd.tsx +0 -75
  54. package/components/catalyst-ui/primitives/label.tsx +0 -24
  55. package/components/catalyst-ui/primitives/navigation-menu.tsx +0 -150
  56. package/components/catalyst-ui/primitives/pagination.tsx +0 -198
  57. package/components/catalyst-ui/primitives/popover.tsx +0 -232
  58. package/components/catalyst-ui/primitives/progress.tsx +0 -34
  59. package/components/catalyst-ui/primitives/radio-group.tsx +0 -43
  60. package/components/catalyst-ui/primitives/resizable.tsx +0 -56
  61. package/components/catalyst-ui/primitives/select.tsx +0 -155
  62. package/components/catalyst-ui/primitives/separator.tsx +0 -74
  63. package/components/catalyst-ui/primitives/sheet.tsx +0 -126
  64. package/components/catalyst-ui/primitives/skeleton.tsx +0 -15
  65. package/components/catalyst-ui/primitives/slider.tsx +0 -27
  66. package/components/catalyst-ui/primitives/switch.tsx +0 -187
  67. package/components/catalyst-ui/primitives/tabs.tsx +0 -335
  68. package/components/catalyst-ui/primitives/textarea.tsx +0 -24
  69. package/components/catalyst-ui/primitives/toggle-group.tsx +0 -55
  70. package/components/catalyst-ui/primitives/toggle.tsx +0 -42
  71. package/components/catalyst-ui/primitives/tooltip.tsx +0 -116
  72. package/components/catalyst-ui/utils/basic-auth.tsx +0 -40
  73. package/components/catalyst-ui/utils/context-storage.tsx +0 -19
  74. package/components/catalyst-ui/utils/cors-middleware.tsx +0 -71
  75. package/components/catalyst-ui/utils/deferred-content.tsx +0 -595
  76. package/components/catalyst-ui/utils/honeypot-middleware.tsx +0 -38
  77. package/components/catalyst-ui/utils/incId.tsx +0 -75
  78. package/components/catalyst-ui/utils/jwk-auth.tsx +0 -36
  79. package/components/catalyst-ui/utils/request-id.tsx +0 -14
  80. package/components/catalyst-ui/utils/secure-headers.tsx +0 -37
  81. package/components/catalyst-ui/utils/server-timing.tsx +0 -23
  82. package/components/catalyst-ui/utils/utils.ts +0 -43
  83. package/components/catalyst-ui/utils/with-cookie.tsx +0 -43
  84. package/components/catalyst-ui/x/accordian-x.tsx +0 -428
  85. package/components/catalyst-ui/x/alert-x.tsx +0 -413
  86. package/components/catalyst-ui/x/animated-text-x.tsx +0 -2242
  87. package/components/catalyst-ui/x/avatar-x.tsx +0 -515
  88. package/components/catalyst-ui/x/badge-x.tsx +0 -670
  89. package/components/catalyst-ui/x/button-X.tsx +0 -2857
  90. package/components/catalyst-ui/x/button-group-x.tsx +0 -847
  91. package/components/catalyst-ui/x/calendar-x.tsx +0 -1910
  92. package/components/catalyst-ui/x/card-x.tsx +0 -2597
  93. package/components/catalyst-ui/x/checkbox-x.tsx +0 -656
  94. package/components/catalyst-ui/x/collapsible-x.tsx +0 -1360
  95. package/components/catalyst-ui/x/combobox-x.tsx +0 -911
  96. package/components/catalyst-ui/x/data-table-x.tsx +0 -1753
  97. package/components/catalyst-ui/x/date-picker-x.tsx +0 -648
  98. package/components/catalyst-ui/x/dialog-x.tsx +0 -659
  99. package/components/catalyst-ui/x/dropdown-menu-x.tsx +0 -612
  100. package/components/catalyst-ui/x/hover-card-x.tsx +0 -375
  101. package/components/catalyst-ui/x/icon-x.tsx +0 -840
  102. package/components/catalyst-ui/x/input-mask-x.tsx +0 -981
  103. package/components/catalyst-ui/x/input-otp-x.tsx +0 -659
  104. package/components/catalyst-ui/x/loader-x.tsx +0 -1757
  105. package/components/catalyst-ui/x/pagination-x.tsx +0 -622
  106. package/components/catalyst-ui/x/popover-x.tsx +0 -744
  107. package/components/catalyst-ui/x/radio-group-x.tsx +0 -499
  108. package/components/catalyst-ui/x/select-x.tsx +0 -1127
  109. package/components/catalyst-ui/x/sheet-x.tsx +0 -668
  110. package/components/catalyst-ui/x/switch-x.tsx +0 -681
  111. package/components/catalyst-ui/x/table-x.tsx +0 -574
  112. package/components/catalyst-ui/x/tabs-x.tsx +0 -839
  113. package/components/catalyst-ui/x/textarea-x.tsx +0 -1263
  114. package/components/catalyst-ui/x/tooltip-x.tsx +0 -396
  115. package/components/catalyst-ui/x/tracker-x.tsx +0 -560
  116. package/data/bg-data.tsx +0 -901
  117. package/data/buttons-data.tsx +0 -2327
  118. package/data/charts-data.tsx +0 -102
  119. package/data/chat-data.tsx +0 -83
  120. package/data/code-data.tsx +0 -1040
  121. package/data/comboboxes-data.tsx +0 -1843
  122. package/data/command-data.tsx +0 -1381
  123. package/data/core-data.tsx +0 -15953
  124. package/data/crm-data.tsx +0 -47
  125. package/data/data.tsx +0 -159
  126. package/data/date-and-time-data.tsx +0 -554
  127. package/data/dependencies.tsx +0 -7
  128. package/data/ecommerce-data.tsx +0 -1387
  129. package/data/forms-data.tsx +0 -7890
  130. package/data/hooks-data.tsx +0 -5487
  131. package/data/index.ts +0 -34
  132. package/data/inputs-data.tsx +0 -557
  133. package/data/interactive-data.tsx +0 -5394
  134. package/data/lofi-data.tsx +0 -18295
  135. package/data/marketing-data.tsx +0 -2546
  136. package/data/media-data.tsx +0 -1510
  137. package/data/motion-data.tsx +0 -5801
  138. package/data/overlay-data.tsx +0 -4136
  139. package/data/pdf-data.tsx +0 -124
  140. package/data/pos-data.tsx +0 -213
  141. package/data/postcss.config.js +0 -6
  142. package/data/primitive-data.tsx +0 -5170
  143. package/data/prompt-data.tsx +0 -1226
  144. package/data/requiredLibs.ts +0 -4
  145. package/data/sandbox-data.tsx +0 -1
  146. package/data/sidebars-data.tsx +0 -5421
  147. package/data/stacks-data.tsx +0 -32
  148. package/data/table-data.tsx +0 -706
  149. package/data/tailwind.config.js +0 -270
  150. package/data/tailwind.config.ngin.js +0 -3830
  151. package/data/tailwind.css +0 -431
  152. package/data/tools-data.tsx +0 -6910
  153. package/data/typography-data.tsx +0 -2050
  154. package/data/utils-data.tsx +0 -6500
  155. package/data/x-data.tsx +0 -1171
@@ -1,2597 +0,0 @@
1
- import React, { useState, useEffect, useRef, createContext } from 'react'
2
- import { cn } from '~/components/catalyst-ui'
3
- import {
4
- Card,
5
- CardHeader,
6
- CardContent,
7
- CardFooter,
8
- CardTitle,
9
- CardDescription,
10
- CardAction,
11
- CardImage,
12
- CardHeart,
13
- CardProduct,
14
- cardVariants,
15
- cardHeaderVariants,
16
- cardTitleVariants,
17
- cardDescriptionVariants,
18
- cardContentVariants,
19
- cardFooterVariants,
20
- cardActionVariants,
21
- } from '~/components/catalyst-ui/primitives/card'
22
- import { Avatar, AvatarImage, AvatarFallback } from '~/components/catalyst-ui'
23
- import { Button } from '~/components/catalyst-ui'
24
- import { Badge } from '~/components/catalyst-ui'
25
- import { Tabs, TabsList, TabsTrigger, TabsContent } from '~/components/catalyst-ui'
26
- import type { LucideIcon } from 'lucide-react'
27
- import {
28
- XIcon,
29
- HeartIcon,
30
- MessageCircleIcon,
31
- RepeatIcon,
32
- SendIcon,
33
- BadgeCheckIcon,
34
- UserPlusIcon,
35
- EllipsisIcon,
36
- StarIcon,
37
- CircleFadingPlusIcon
38
- } from 'lucide-react'
39
- import {
40
- DropdownMenu,
41
- DropdownMenuContent,
42
- DropdownMenuGroup,
43
- DropdownMenuItem,
44
- DropdownMenuTrigger,
45
- } from '~/components/catalyst-ui'
46
-
47
- /**
48
- * ★ ━━━━ ☆ ━━━━ CardX ━━━━ ☆ ━━━━ ★
49
- * type CardXType =
50
- * | 'default' | 'spotlight' | '3d' | 'closable' | 'tweet' | 'product' // Interactive & Social
51
- * | 'productTop' | 'productBottom' | 'productLeft' | 'productRight' // Product Layouts
52
- * | 'testimonial' | 'overlay' | 'horizontal' | 'topImage' | 'bottomImage' // Content Display
53
- * | 'meeting' | 'invite' // Functional
54
- *
55
- * ★ ━━━━ ☆ ━━━━ USAGE ━━━━ ☆ ━━━━ ★
56
- *
57
- * ★ ━━━━━━━━━ Default Card ━━━━━━━━━ ★
58
- * ```jsx
59
- * <CardX className="max-w-md">
60
- * <CardXHeader>
61
- * <CardXTitle>Card Title</CardXTitle>
62
- * <CardXDescription>Card description goes here</CardXDescription>
63
- * </CardXHeader>
64
- * <CardXContent>
65
- * This is the default card content. You can put any content here.
66
- * </CardXContent>
67
- * <CardXFooter>
68
- * <Button>Action</Button>
69
- * </CardXFooter>
70
- * </CardX>
71
- * ```
72
- *
73
- * ★ ━━━━━━━━━ Spotlight Card ━━━━━━━━━ ★
74
- * ```jsx
75
- * <CardX card="spotlight">
76
- * <CardXHeader>
77
- * <CardXTitle>Spotlight Card</CardXTitle>
78
- * <CardXDescription>Hover to see the effect</CardXDescription>
79
- * </CardXHeader>
80
- * <CardXContent>
81
- * This card has a beautiful spotlight effect that follows your cursor.
82
- * </CardXContent>
83
- * </CardX>
84
- * ```
85
- *
86
- * ★ ━━━━━━━━━ 3D Card ━━━━━━━━━ ★
87
- * ```jsx
88
- * <div className="card-3d-wrapper">
89
- * <CardX card="3d" className="max-w-md">
90
- * <CardXHeader>
91
- * <CardXTitle>3D Interactive Card</CardXTitle>
92
- * <CardXDescription>Hover to see 3D effect</CardXDescription>
93
- * </CardXHeader>
94
- * <CardXContent image="https://example.com/image.jpg">
95
- * This card tilts in 3D when you hover over it.
96
- * </CardXContent>
97
- * </CardX>
98
- * </div>
99
- * ```
100
- *
101
- * ★ ━━━━━━━━━ Closable Card ━━━━━━━━━ ★
102
- * ```jsx
103
- * {closableActive && (
104
- * <CardX card="closable" className="max-w-md">
105
- * <CardXHeader onClose={() => setClosableActive(false)}>
106
- * Important Notice
107
- * </CardXHeader>
108
- * <CardXContent actionText="Got it">
109
- * This is an important message that can be dismissed.
110
- * </CardXContent>
111
- * </CardX>
112
- * )}
113
- * ```
114
- *
115
- * ★ ━━━━━━━━━ Tweet Card ━━━━━━━━━ ★
116
- * ```jsx
117
- * <CardX card="tweet" className="max-w-md">
118
- * <CardXHeader
119
- * avatar="https://example.com/avatar.jpg"
120
- * name="John Doe"
121
- * handle="johndoe"
122
- * verified={true}
123
- * />
124
- * <CardXContent image="https://example.com/image.jpg">
125
- * Just shipped a new feature! Check it out and let me know what you think. 🚀
126
- * </CardXContent>
127
- * <CardXFooter
128
- * state={tweetState}
129
- * setState={setTweetState}
130
- * likes="124"
131
- * comments="32"
132
- * retweets="18"
133
- * shares="7"
134
- * />
135
- * </CardX>
136
- *
137
- * // Tweet state management
138
- * const [tweetState, setTweetState] = useState({
139
- * liked: false,
140
- * commented: false,
141
- * retweeted: false,
142
- * shared: false
143
- * });
144
- * ```
145
- *
146
- * ★ ━━━━━━━━━ Product Card ━━━━━━━━━ ★
147
- * ```jsx
148
- * <CardX card="product" className="max-w-md border-none">
149
- * <CardXProduct src="https://example.com/product.jpg" liked={productLiked} setLiked={setProductLiked}>
150
- * <Card className="border-none">
151
- * <CardXHeader title="Nike Air Max" info1="EU42" info2="Black/White" />
152
- * <CardXContent>
153
- * Crossing hardwood comfort with off-court flair.
154
- * </CardXContent>
155
- * <CardXFooter price1="Price" price2="$129.99" buttonLabel="Add to cart" onAddToCart={() => console.log('Added')} />
156
- * </Card>
157
- * </CardXProduct>
158
- * </CardX>
159
- * ```
160
- *
161
- * ★ ━━━━━━━━━ Product Card Layouts ━━━━━━━━━ ★
162
- * ```jsx
163
- * // Product Top Image
164
- * <CardX card="productTop" className="border-none">
165
- * <CardXProduct src="https://example.com/product.jpg" liked={productLiked} setLiked={setProductLiked}>
166
- * <Card className="border-none">
167
- * <CardXHeader title="Nike Air Max" info1="EU42" info2="Black/White" />
168
- * <CardXContent>Premium materials and timeless design.</CardXContent>
169
- * <CardXFooter price2="$129.99" buttonLabel="Buy Now" />
170
- * </Card>
171
- * </CardXProduct>
172
- * </CardX>
173
- *
174
- * // Product Bottom Image
175
- * <CardX card="productBottom" className="border-none">
176
- * <CardXProduct src="https://example.com/product.jpg" liked={productLiked} setLiked={setProductLiked}>
177
- * <Card className="border-none">
178
- * <CardXHeader title="Nike Air Max" info1="EU42" info2="Black/White" />
179
- * <CardXContent>Premium materials and timeless design.</CardXContent>
180
- * <CardXFooter price2="$129.99" buttonLabel="Buy Now" />
181
- * </Card>
182
- * </CardXProduct>
183
- * </CardX>
184
- *
185
- * // Product Left Image
186
- * <CardX card="productLeft" className="border-none">
187
- * <CardXProduct src="https://example.com/product.jpg" liked={productLiked} setLiked={setProductLiked}>
188
- * <Card className="border-none">
189
- * <CardXHeader title="Nike Air Max" info1="EU42" info2="Black/White" />
190
- * <CardXContent>Premium materials and timeless design.</CardXContent>
191
- * <CardXFooter price2="$129.99" buttonLabel="Buy Now" />
192
- * </Card>
193
- * </CardXProduct>
194
- * </CardX>
195
- *
196
- * // Product Right Image
197
- * <CardX card="productRight" className="border-none">
198
- * <CardXProduct src="https://example.com/product.jpg" liked={productLiked} setLiked={setProductLiked}>
199
- * <Card className="border-none">
200
- * <CardXHeader title="Nike Air Max" info1="EU42" info2="Black/White" />
201
- * <CardXContent>Premium materials and timeless design.</CardXContent>
202
- * <CardXFooter price2="$129.99" buttonLabel="Buy Now" />
203
- * </Card>
204
- * </CardXProduct>
205
- * </CardX>
206
- * ```
207
- *
208
- * ★ ━━━━━━━━━ Testimonial Card ━━━━━━━━━ ★
209
- * ```jsx
210
- * <CardX card="testimonial" className="max-w-md">
211
- * <CardXContent>
212
- * "This product has completely transformed how I work. The attention to detail is incredible!"
213
- * </CardXContent>
214
- * <CardXFooter
215
- * avatar="https://example.com/avatar.jpg"
216
- * name="Sarah Johnson"
217
- * handle="sarahj"
218
- * rating={5}
219
- * />
220
- * </CardX>
221
- * ```
222
- *
223
- * ★ ━━━━━━━━━ Overlay Card ━━━━━━━━━ ★
224
- * ```jsx
225
- * <CardX card="overlay">
226
- * <CardXHeader>Stunning Destination</CardXHeader>
227
- * <CardXContent image="https://example.com/image.jpg">
228
- * Discover the beauty of nature in this breathtaking location.
229
- * </CardXContent>
230
- * </CardX>
231
- * ```
232
- *
233
- * ★ ━━━━━━━━━ Horizontal Card ━━━━━━━━━ ★
234
- * ```jsx
235
- * <CardX card="horizontal" className="max-w-2xl">
236
- * <CardXContent
237
- * title="Featured Article"
238
- * description="Learn about the latest trends"
239
- * actionText="Read More"
240
- * >
241
- * <img
242
- * src="https://example.com/image.jpg"
243
- * alt="Article"
244
- * className="h-full w-full rounded-l-xl object-cover"
245
- * />
246
- * </CardXContent>
247
- * </CardX>
248
- * ```
249
- *
250
- * ★ ━━━━━━━━━ Top Image Card ━━━━━━━━━ ★
251
- * ```jsx
252
- * <CardX card="topImage" className="max-w-md">
253
- * <CardXContent image="https://example.com/image.jpg" />
254
- * <CardXHeader>
255
- * <CardXTitle>Beautiful Landscape</CardXTitle>
256
- * <CardXDescription>Explore the wonders of nature</CardXDescription>
257
- * </CardXHeader>
258
- * <CardXFooter showActions onClick={() => console.log('explore')} onClick2={() => console.log('download')} />
259
- * </CardX>
260
- * ```
261
- *
262
- * ★ ━━━━━━━━━ Bottom Image Card ━━━━━━━━━ ★
263
- * ```jsx
264
- * <CardX card="bottomImage" className="max-w-md">
265
- * <CardXHeader>
266
- * <CardXTitle>Amazing View</CardXTitle>
267
- * <CardXDescription>Experience the beauty</CardXDescription>
268
- * </CardXHeader>
269
- * <CardXContent image="https://example.com/image.jpg" />
270
- * </CardX>
271
- * ```
272
- *
273
- * ★ ━━━━━━━━━ Meeting Card ━━━━━━━━━ ★
274
- * ```jsx
275
- * <CardX card="meeting" className="max-w-md">
276
- * <CardXHeader>
277
- * <CardXTitle>Team Meeting</CardXTitle>
278
- * <CardXDescription>Wednesday, 2:00 PM</CardXDescription>
279
- * </CardXHeader>
280
- * <CardXContent
281
- * items={[
282
- * 'Review Q4 goals',
283
- * 'Discuss new project timeline',
284
- * 'Team feedback session'
285
- * ]}
286
- * >
287
- * Join us for our weekly sync to align on priorities.
288
- * </CardXContent>
289
- * <CardXFooter
290
- * avatars={[
291
- * { src: 'https://example.com/avatar1.jpg', name: 'John', fallback: 'JD' },
292
- * { src: 'https://example.com/avatar2.jpg', name: 'Sarah', fallback: 'SJ' }
293
- * ]}
294
- * />
295
- * </CardX>
296
- * ```
297
- *
298
- * ★ ━━━━━━━━━ Invite Card ━━━━━━━━━ ★
299
- * ```jsx
300
- * <CardX card="invite" className="max-w-md">
301
- * <CardXHeader>
302
- * <CardXTitle>Team Members</CardXTitle>
303
- * <CardXDescription>Manage your team</CardXDescription>
304
- * </CardXHeader>
305
- * <CardXContent
306
- * showInvite
307
- * members={[
308
- * { avatar: 'https://example.com/avatar1.jpg', name: 'John Doe', role: 'Developer', fallback: 'JD' },
309
- * { avatar: 'https://example.com/avatar2.jpg', name: 'Sarah Smith', role: 'Designer', fallback: 'SS' }
310
- * ]}
311
- * />
312
- * </CardX>
313
- * ```
314
- *
315
- * ★ ━━━━━━━━━ Card Groups ━━━━━━━━━ ★
316
- * ```jsx
317
- * // Horizontal Card Group (Default)
318
- * <CardXGroup>
319
- * <CardX>
320
- * <CardXHeader>
321
- * <CardXTitle>Card 1</CardXTitle>
322
- * </CardXHeader>
323
- * <CardXContent>First card content</CardXContent>
324
- * </CardX>
325
- * <CardX>
326
- * <CardXHeader>
327
- * <CardXTitle>Card 2</CardXTitle>
328
- * </CardXHeader>
329
- * <CardXContent>Second card content</CardXContent>
330
- * </CardX>
331
- * <CardX>
332
- * <CardXHeader>
333
- * <CardXTitle>Card 3</CardXTitle>
334
- * </CardXHeader>
335
- * <CardXContent>Third card content</CardXContent>
336
- * </CardX>
337
- * </CardXGroup>
338
- *
339
- * // Vertical Card Group
340
- * <CardXGroup variant="vertical" className="max-w-md">
341
- * <CardX>
342
- * <CardXHeader>
343
- * <CardXTitle>First Card</CardXTitle>
344
- * </CardXHeader>
345
- * <CardXContent>Content for first card</CardXContent>
346
- * </CardX>
347
- * <CardX>
348
- * <CardXHeader>
349
- * <CardXTitle>Second Card</CardXTitle>
350
- * </CardXHeader>
351
- * <CardXContent>Content for second card</CardXContent>
352
- * </CardX>
353
- * <CardX>
354
- * <CardXHeader>
355
- * <CardXTitle>Third Card</CardXTitle>
356
- * </CardXHeader>
357
- * <CardXContent>Content for third card</CardXContent>
358
- * </CardX>
359
- * </CardXGroup>
360
- * ```
361
- *
362
- * ★ ━━━━━━━━━ Props ━━━━━━━━━ ★
363
- *
364
- * CardX Props:
365
- * - `card`: CardXType - Specifies which variant to use
366
- * - `className`: string - Additional CSS classes
367
- *
368
- * CardXHeader Props (for tweet variant):
369
- * - `avatar`: string - Avatar image URL
370
- * - `name`: string - Display name
371
- * - `handle`: string - Twitter handle
372
- * - `verified`: boolean - Show verified badge
373
- *
374
- * CardXHeader Props (for product variant):
375
- * - `title`: string - Product title
376
- * - `info1`: string - Product info 1 (e.g., size)
377
- * - `info2`: string - Product info 2 (e.g., color)
378
- *
379
- * CardXContent Props:
380
- * - `image`: string - Image URL to display
381
- * - `actionText`: string - Call to action text (for closable card)
382
- * - `items`: string[] - Bullet point items (for meeting card)
383
- * - `showInvite`: boolean - Show invite UI (for invite card)
384
- * - `members`: Array<{ avatar: string, name: string, role: string, fallback: string }> - Team members
385
- *
386
- * CardXFooter Props (for tweet variant):
387
- * - `state`: { liked: boolean, commented: boolean, retweeted: boolean, shared: boolean }
388
- * - `setState`: (state) => void - State update function
389
- * - `likes`: string - Number of likes
390
- * - `comments`: string - Number of comments
391
- * - `retweets`: string - Number of retweets
392
- * - `shares`: string - Number of shares
393
- *
394
- * CardXFooter Props (for testimonial variant):
395
- * - `avatar`: string - Reviewer avatar
396
- * - `name`: string - Reviewer name
397
- * - `handle`: string - Reviewer handle
398
- * - `rating`: number - Star rating 1-5
399
- *
400
- * CardXFooter Props (for product variant):
401
- * - `price1`: string - Price label
402
- * - `price2`: string - Price amount
403
- * - `buttonLabel`: string - Button text
404
- * - `onAddToCart`: () => void - Add to cart callback
405
- *
406
- * CardXFooter Props (for meeting variant):
407
- * - `avatars`: Array<{ src: string, name: string, fallback: string }> - Avatar list
408
- *
409
- * CardXFooter Props (for general use):
410
- * - `showActions`: boolean - Show action buttons
411
- * - `onClick`: () => void - Primary action callback
412
- * - `onClick2`: () => void - Secondary action callback
413
- *
414
- * CardXProduct Props:
415
- * - `src`: string - Product image URL
416
- * - `liked`: boolean - Whether product is liked
417
- * - `setLiked`: (liked: boolean) => void - Like state update
418
- * - `children`: ReactNode - Product content card
419
- *
420
- * CardXGroup Props:
421
- * - `variant`: 'horizontal' | 'vertical' - Group layout direction
422
- * - `className`: string - Additional CSS classes
423
- * - `children`: ReactNode - CardX components
424
- *
425
- */
426
-
427
-
428
- // #endregion ===========================================================================
429
- // TYPE DEFINITIONS
430
- // #region ===========================================================================
431
- type CardType =
432
- | 'default'
433
- | 'spotlight'
434
- | '3d'
435
- | 'closable'
436
- | 'tweet'
437
- | 'product'
438
- | 'productTop'
439
- | 'productBottom'
440
- | 'productLeft'
441
- | 'productRight'
442
- | 'testimonial'
443
- | 'overlay'
444
- | 'horizontal'
445
- | 'topImage'
446
- | 'bottomImage'
447
- | 'meeting'
448
- | 'invite'
449
-
450
-
451
- interface CardContextValue {
452
- variant?: string
453
- size?: string
454
- align?: string
455
- card?: CardType
456
- padding?: string
457
- spacing?: string
458
- position?: string
459
- weight?: string
460
- interactive?: boolean
461
- }
462
-
463
- const CardContext = createContext<CardContextValue>({})
464
-
465
- const useCardContext = () => useContext(CardContext)
466
-
467
-
468
- // #endregion ===========================================================================
469
- // CONTEXT
470
- // #region ===========================================================================
471
- const CardXContext = React.createContext<CardType>('default')
472
-
473
-
474
- interface CardContextValue {
475
- variant?: string
476
- size?: string
477
- interactive?: boolean
478
- }
479
-
480
-
481
- // #endregion ===========================================================================
482
- // CARDX PARENT WRAPPER
483
- // #region ===========================================================================
484
- export function CardX({ card = 'default', variant, size, interactive, align, weight, spacing, padding, layout, justify, gap, className, children, ...props }: any) {
485
- const contextValue: CardContextValue = { card, variant, size, interactive, align, weight, spacing, padding, position, layout, justify, gap, }
486
- switch (card) {
487
- case 'spotlight':
488
- return (
489
- <CardXContext.Provider value={card}>
490
- <CardContext.Provider value={contextValue}>
491
- <div className='h-max w-max'>
492
- <div className='spotlight-card group bg-border relative overflow-hidden rounded-xl p-px transition-all duration-300 ease-in-out'>
493
- <Card className={cn(cardVariants({ variant, size, interactive, align }), 'group-hover:bg-card/90 max-w-80 border-none transition-all duration-300 ease-in-out group-hover:backdrop-blur-[20px]', className)} {...props} >
494
- {children}
495
- </Card>
496
- <div className='blob absolute top-0 left-0 size-20 rounded-full bg-sky-600/60 opacity-0 blur-2xl transition-all duration-300 ease-in-out dark:bg-sky-400/60' />
497
- <div className='fake-blob absolute top-0 left-0 size-20 rounded-full' />
498
- </div>
499
- </div>
500
- </CardContext.Provider>
501
- </CardXContext.Provider>
502
- )
503
-
504
- case 'overlay':
505
- return (
506
- <CardXContext.Provider value={card}>
507
- <CardContext.Provider value={contextValue}>
508
- <Card className={cn(cardVariants({ variant, size, interactive, align }), 'before:bg-primary/70 relative max-w-md py-0 before:absolute before:size-full before:rounded-xl', className)} {...props} >
509
- {children}
510
- </Card>
511
- </CardContext.Provider>
512
- </CardXContext.Provider>
513
- )
514
-
515
- default:
516
- return (
517
- <CardXContext.Provider value={card}>
518
- <CardContext.Provider value={contextValue}>
519
- <Card className={cn(cardVariants({ variant, size, interactive, align }), className)} {...props} >
520
- {children}
521
- </Card>
522
- </CardContext.Provider>
523
- </CardXContext.Provider>
524
- )
525
- }
526
- }
527
-
528
- // #endregion ===========================================================================
529
- // CARDX HEADER - STRUCTURAL VARIANTS
530
- // #region ===========================================================================
531
- export function CardXHeader({ children, ...props }: any) {
532
- const { card, spacing, align } = useCardContext()
533
-
534
- switch (card) {
535
- case 'product':
536
- case 'productTop':
537
- case 'productBottom':
538
- case 'productLeft':
539
- case 'productRight':
540
- return (
541
- <CardHeader className={cn(cardHeaderVariants({ spacing, align }), props.className)}>
542
- <CardTitle>{props.title}</CardTitle>
543
- <CardDescription className='flex items-center gap-2'>
544
- {props.info1 && <Badge variant='outline' className='rounded-sm'>{props.info1}</Badge>}
545
- {props.info2 && <Badge variant='outline' className='rounded-sm'>{props.info2}</Badge>}
546
- {children}
547
- </CardDescription>
548
- </CardHeader>
549
- )
550
- case 'tweet':
551
- return (
552
- <CardHeader className={cn(cardHeaderVariants({ spacing, align, }), 'flex-row items-center justify-between gap-3', props.className)}>
553
- <div className='flex items-center gap-3'>
554
- <Avatar className='ring-ring ring-2'>
555
- <AvatarImage src={props.avatar} alt={props.name} />
556
- <AvatarFallback className='text-xs'>{props.name?.[0]}</AvatarFallback>
557
- </Avatar>
558
- <div className='flex flex-col gap-0.5'>
559
- <CardTitle className='flex items-center gap-1 text-sm'>
560
- {props.name} {props.verified && <BadgeCheckIcon className='size-4 fill-sky-600 stroke-white dark:fill-sky-400' />}
561
- </CardTitle>
562
- <CardDescription>@{props.handle}</CardDescription>
563
- </div>
564
- </div>
565
- <CardXAction />
566
- </CardHeader>
567
- )
568
-
569
- case 'closable':
570
- return (
571
- <CardHeader className={cn(cardHeaderVariants({ spacing, align, }), 'relative', props.className)}>
572
- <Button
573
- variant='ghost'
574
- size='icon'
575
- onClick={props.onClose}
576
- className='absolute top-2 right-2 rounded-full'
577
- >
578
- <XIcon />
579
- <span className='sr-only'>Close</span>
580
- </Button>
581
- <CardTitle className='text-center'>{children}</CardTitle>
582
- </CardHeader>
583
- )
584
-
585
- case 'overlay':
586
- return (
587
- <CardHeader className={cn(cardHeaderVariants({ spacing, align, }), 'text-primary-foreground w-full pt-6 absolute', props.className)}>
588
- <CardTitle>{children}</CardTitle>
589
- </CardHeader>
590
- )
591
-
592
- default:
593
- return (
594
- <CardHeader
595
- className={cn(
596
- cardHeaderVariants({
597
- spacing,
598
- align: align || (context.variant === 'default' ? 'left' : undefined)
599
- }),
600
- props.className
601
- )}
602
- {...props}
603
- />
604
- )
605
- }
606
- }
607
-
608
- // #endregion ===========================================================================
609
- // CARDX TITLE - PASSTHROUGH
610
- // #region ===========================================================================
611
- export function CardXTitle({ ...props }: any) {
612
- const { card, size, weight } = useCardContext()
613
- switch (card) {
614
- default:
615
- return (
616
- <CardTitle
617
- className={cn(cardTitleVariants({ size, weight }), className)}
618
- {...props}
619
- />
620
- )
621
- }
622
- }
623
-
624
- // #endregion ===========================================================================
625
- // CARDX DESCRIPTION - PASSTHROUGH
626
- // #region ===========================================================================
627
- export function CardXDescription({ ...props }: any) {
628
- const { card, size, } = useCardContext()
629
-
630
- switch (card) {
631
- default:
632
- return (
633
- <CardDescription
634
- className={cn(cardDescriptionVariants({ size }), props.className)}
635
- {...props}
636
- />
637
- )
638
- }
639
- }
640
-
641
- // #endregion ===========================================================================
642
- // CARDX ACTION - PASSTHROUGH
643
- // #region ===========================================================================
644
- export function CardXAction({ onClick, items, ...props }: any) {
645
- const { card, position } = useCardContext()
646
- switch (card) {
647
- case 'tweet':
648
- return (
649
- <div className='flex items-center gap-2'>
650
- <Button variant='outline' size='sm' onClick={onClick}>
651
- <UserPlusIcon />
652
- Follow
653
- </Button>
654
- <DropdownMenu>
655
- <DropdownMenuTrigger asChild>
656
- <Button variant='ghost' size='icon' aria-label='Toggle menu'>
657
- <EllipsisIcon />
658
- </Button>
659
- </DropdownMenuTrigger>
660
- <DropdownMenuContent className="w-56" align="start">
661
- <DropdownMenuGroup>
662
- {items?.map((item: any, index: number) => (
663
- <DropdownMenuItem key={index} onSelect={item.onSelect}>
664
- {item.name}
665
- </DropdownMenuItem>
666
- ))}
667
- </DropdownMenuGroup>
668
- </DropdownMenuContent>
669
- </DropdownMenu>
670
- </div>
671
- )
672
- default:
673
- return (
674
- <CardAction
675
- data-slot="card-action"
676
- className={cn(cardActionVariants({ position }), props.className)}
677
- {...props}
678
- />
679
- )
680
- }
681
- }
682
-
683
- // #endregion ===========================================================================
684
- // CARDX CONTENT - STRUCTURAL VARIANTS
685
- // #region ===========================================================================
686
- export function CardXContent({ children, ...props }: any) {
687
- const { card, padding, spacing } = useCardContext()
688
- const cardRef = useRef<HTMLDivElement>(null)
689
- const imageRef = useRef<HTMLImageElement>(null)
690
- const animationFrameRef = useRef<number | undefined>(undefined)
691
- const lastMousePosition = useRef({ x: 0, y: 0 })
692
- // Spotlight effect
693
- useEffect(() => {
694
- if (card !== 'spotlight') return
695
-
696
- const all = document.querySelectorAll('.spotlight-card')
697
-
698
- const handleMouseMove = (ev: MouseEvent) => {
699
- all.forEach(e => {
700
- const blob = e.querySelector('.blob') as HTMLElement
701
- const fblob = e.querySelector('.fake-blob') as HTMLElement
702
-
703
- if (!blob || !fblob) return
704
-
705
- const rec = fblob.getBoundingClientRect()
706
- blob.style.opacity = '1'
707
-
708
- blob.animate(
709
- [
710
- {
711
- transform: `translate(${ev.clientX - rec.left - rec.width / 2
712
- }px, ${ev.clientY - rec.top - rec.height / 2}px)`
713
- }
714
- ],
715
- {
716
- duration: 300,
717
- fill: 'forwards'
718
- }
719
- )
720
- })
721
- }
722
-
723
- window.addEventListener('mousemove', handleMouseMove)
724
- return () => window.removeEventListener('mousemove', handleMouseMove)
725
- }, [card])
726
-
727
- // 3D effect
728
- useEffect(() => {
729
- if (card !== '3d') return
730
-
731
- const card = cardRef.current?.closest('.card-3d-wrapper') as HTMLElement
732
- const image = imageRef.current
733
-
734
- if (!card || !image) return
735
-
736
- let rect: DOMRect
737
- let centerX: number
738
- let centerY: number
739
-
740
- const updateCardTransform = (mouseX: number, mouseY: number) => {
741
- if (!rect) {
742
- rect = card.getBoundingClientRect()
743
- centerX = rect.left + rect.width / 2
744
- centerY = rect.top + rect.height / 2
745
- }
746
-
747
- const relativeX = mouseX - centerX
748
- const relativeY = mouseY - centerY
749
-
750
- const cardTransform: CardTransform = {
751
- rotateX: -relativeY * 0.035,
752
- rotateY: relativeX * 0.035,
753
- scale: 1.025
754
- }
755
-
756
- const imageTransform: CardTransform = {
757
- rotateX: -relativeY * 0.025,
758
- rotateY: relativeX * 0.025,
759
- scale: 1.05
760
- }
761
-
762
- return { cardTransform, imageTransform }
763
- }
764
-
765
- const animate = () => {
766
- const { cardTransform, imageTransform } = updateCardTransform(
767
- lastMousePosition.current.x,
768
- lastMousePosition.current.y
769
- )
770
-
771
- card.style.transform = `perspective(1000px) rotateX(${cardTransform.rotateX}deg) rotateY(${cardTransform.rotateY}deg) scale3d(${cardTransform.scale}, ${cardTransform.scale}, ${cardTransform.scale})`
772
- card.style.boxShadow = '0 10px 35px rgba(0, 0, 0, 0.2)'
773
-
774
- image.style.transform = `perspective(1000px) rotateX(${imageTransform.rotateX}deg) rotateY(${imageTransform.rotateY}deg) scale3d(${imageTransform.scale}, ${imageTransform.scale}, ${imageTransform.scale})`
775
-
776
- animationFrameRef.current = requestAnimationFrame(animate)
777
- }
778
-
779
- const handleMouseMove = (e: MouseEvent) => {
780
- lastMousePosition.current = { x: e.clientX, y: e.clientY }
781
- }
782
-
783
- const handleMouseEnter = () => {
784
- card.style.transition = 'transform 0.2s ease, box-shadow 0.2s ease'
785
- image.style.transition = 'transform 0.2s ease'
786
- animate()
787
- }
788
-
789
- const handleMouseLeave = () => {
790
- if (animationFrameRef.current) {
791
- cancelAnimationFrame(animationFrameRef.current)
792
- }
793
-
794
- card.style.transform = 'perspective(1000px) rotateX(0) rotateY(0) scale3d(1, 1, 1)'
795
- card.style.boxShadow = 'none'
796
- card.style.transition = 'transform 0.5s ease, box-shadow 0.5s ease'
797
-
798
- image.style.transform = 'perspective(1000px) rotateX(0) rotateY(0) scale3d(1, 1, 1)'
799
- image.style.transition = 'transform 0.5s ease'
800
- }
801
-
802
- card.addEventListener('mouseenter', handleMouseEnter)
803
- card.addEventListener('mousemove', handleMouseMove)
804
- card.addEventListener('mouseleave', handleMouseLeave)
805
-
806
- return () => {
807
- if (animationFrameRef.current) {
808
- cancelAnimationFrame(animationFrameRef.current)
809
- }
810
- card.removeEventListener('mouseenter', handleMouseEnter)
811
- card.removeEventListener('mousemove', handleMouseMove)
812
- card.removeEventListener('mouseleave', handleMouseLeave)
813
- }
814
- }, [card])
815
-
816
- switch (card) {
817
- case '3d':
818
- return (
819
- <CardContent ref={cardRef} className={cn(cardContentVariants({ padding, spacing: 'loose' }), props.className)}>
820
- <img
821
- ref={imageRef}
822
- src={props.image}
823
- alt={props.imageAlt || 'Banner'}
824
- className='aspect-video w-full rounded-md object-cover'
825
- width={500}
826
- height={500}
827
- />
828
- {children}
829
- </CardContent>
830
- )
831
-
832
- case 'tweet':
833
- return (
834
- <CardContent className={cn(cardContentVariants({ padding, spacing: 'loose' }), 'text-sm', props.className)}>
835
- {props.image && (
836
- <img
837
- src={props.image}
838
- alt='Banner'
839
- className='aspect-video w-full rounded-md object-cover'
840
- />
841
- )}
842
- {children}
843
- </CardContent>
844
- )
845
-
846
- case 'closable':
847
- return (
848
- <CardContent className={cn(cardContentVariants({ padding, spacing }), 'flex flex-col gap-4 text-center', props.className)}>
849
- {children}
850
- {props.actionText && <Button>{props.actionText}</Button>}
851
- </CardContent>
852
- )
853
-
854
- case 'testimonial':
855
- return (
856
- <CardContent className={cn(cardContentVariants({ padding, spacing }), props.className)}>
857
- {children}
858
- </CardContent>
859
- )
860
-
861
- case 'overlay':
862
- return (
863
- <>
864
- <CardContent className='px-0' >
865
- <img
866
- src={props.image}
867
- alt='Banner'
868
- className='h-70 w-112 rounded-xl'
869
- />
870
- </CardContent>
871
- <CardContent className={cn(cardContentVariants({ padding, spacing }), 'text-primary-foreground/80 absolute', props.className)}>
872
- {children}
873
- </CardContent>
874
- </>
875
- )
876
-
877
- case 'horizontal':
878
- return (
879
- <div className='flex items-center'>
880
- <CardContent className={cn(cardContentVariants({ padding, spacing }), 'grow-1 px-0', props.className)} >
881
- {children}
882
- </CardContent>
883
- <div className='sm:min-w-54'>
884
- <CardHeader className='pt-6'>
885
- <CardTitle>{props.title}</CardTitle>
886
- <CardDescription>{props.description}</CardDescription>
887
- </CardHeader>
888
- {props.actionText && (
889
- <CardFooter className='gap-3 py-6'>
890
- <Button className='bg-transparent bg-gradient-to-br from-purple-500 to-pink-500 text-white focus-visible:ring-pink-600/20'>
891
- {props.actionText}
892
- </Button>
893
- </CardFooter>
894
- )}
895
- </div>
896
- </div>
897
- )
898
-
899
- case 'topImage':
900
- return (
901
- <CardContent className={cn(cardContentVariants({ padding, spacing }), 'px-0', props.className)} {...props} >
902
- <img
903
- src={props.image}
904
- alt='Banner'
905
- className='aspect-video h-70 rounded-t-xl object-cover'
906
- />
907
- </CardContent>
908
- )
909
-
910
- case 'bottomImage':
911
- return (
912
- <CardContent className={cn(cardContentVariants({ padding, spacing }), 'px-0', props.className)} {...props} >
913
- <img
914
- src={props.image}
915
- alt='Banner'
916
- className='aspect-video h-70 rounded-b-xl object-cover'
917
- />
918
- </CardContent>
919
- )
920
-
921
- case 'meeting':
922
- return (
923
- <CardContent className={cn(cardContentVariants({ padding, spacing }), 'text-sm', props.className)}>
924
- <p>{props.children}</p>
925
- {props.items && (
926
- <ol className='mt-4 flex list-decimal flex-col gap-2 pl-6'>
927
- {props.items.map((item: string, i: number) => (
928
- <li key={i}>{item}</li>
929
- ))}
930
- </ol>
931
- )}
932
- </CardContent>
933
- )
934
-
935
- case 'invite':
936
- return (
937
- <CardContent className={cn(cardContentVariants({ padding, spacing }), 'grid gap-4 sm:grid-cols-2', props.className)}>
938
- {props.showInvite && (
939
- <div className='flex items-center gap-4'>
940
- <CircleFadingPlusIcon />
941
- <span className='text-sm font-semibold'>Invite Member</span>
942
- </div>
943
- )}
944
- {props.members?.map((member: any, i: number) => (
945
- <div key={i} className='flex items-center gap-4'>
946
- <Avatar>
947
- <AvatarImage src={member.avatar} alt={member.name} />
948
- <AvatarFallback className='text-xs'>{member.fallback}</AvatarFallback>
949
- </Avatar>
950
- <div className='flex flex-col'>
951
- <span className='text-sm font-semibold'>{member.name}</span>
952
- <span className='text-muted-foreground text-sm'>{member.role}</span>
953
- </div>
954
- </div>
955
- ))}
956
- </CardContent>
957
- )
958
-
959
- default:
960
- return <CardContent className={cn(cardContentVariants({ padding, spacing }), props.className)} {...props} />
961
- }
962
- }
963
-
964
- // #endregion ===========================================================================
965
- // CARDX FOOTER - STRUCTURAL VARIANTS
966
- // #region ===========================================================================
967
- export function CardXFooter({ state = {
968
- liked: false,
969
- commented: false,
970
- retweeted: false,
971
- shared: false
972
- },
973
- setState,
974
- className,
975
- children,
976
- ...props
977
- }: any) {
978
- const { card, layout, justify, align, gap, } = useCardContext()
979
- /**const [state, setState] = useState({
980
- liked: false,
981
- commented: false,
982
- retweeted: false,
983
- shared: false
984
- })
985
-
986
- // Pass to CardXFooter
987
- <CardXFooter
988
- state={tweetState}
989
- setState={setTweetState}
990
- /> */
991
- switch (card) {
992
- case 'product':
993
- case 'productTop':
994
- case 'productBottom':
995
- case 'productLeft':
996
- case 'productRight':
997
- return (
998
- <CardFooter className={cn(cardFooterVariants({ layout, justify: justify || 'between', align, gap: gap || 'md' }), 'max-sm:flex-col max-sm:items-stretch', props.className)}>
999
- <div className='flex flex-col'>
1000
- <span className='text-sm font-medium uppercase'>{props.price1 || 'Price'}</span>
1001
- <span className='text-xl font-semibold'>{props.price2}</span>
1002
- </div>
1003
- {children}
1004
- {props.buttonLabel && <Button size='lg' onClick={props.onAddToCart}>{props.buttonLabel}</Button>}
1005
- </CardFooter>
1006
- )
1007
- case 'tweet':
1008
- return (
1009
- <CardFooter className={cn(cardFooterVariants({ layout, justify, align, gap: gap || 'sm' }), props.className)}>
1010
- <Button variant='ghost' size='sm' onClick={() => setState((prev) => ({
1011
- ...prev,
1012
- liked: !prev.liked
1013
- }))}>
1014
- <HeartIcon className={cn(props.state?.liked && 'fill-destructive stroke-destructive')} />
1015
- {state.likes || '0'}
1016
- </Button>
1017
- <Button variant='ghost' size='sm' onClick={() => setState((prev) => ({
1018
- ...prev,
1019
- commented: !prev.commented
1020
- }))}>
1021
- <MessageCircleIcon />
1022
- {state.comments || '0'}
1023
- </Button>
1024
- <Button variant='ghost' size='sm' onClick={() => setState((prev) => ({
1025
- ...prev,
1026
- retweeted: !prev.retweeted
1027
- }))}>
1028
- <RepeatIcon />
1029
- {state.retweets || '0'}
1030
- </Button>
1031
- <Button variant='ghost' size='sm' onClick={() => setState((prev) => ({
1032
- ...prev,
1033
- shared: !prev.shared
1034
- }))}>
1035
- <SendIcon />
1036
- {state.shares || '0'}
1037
- </Button>
1038
- </CardFooter>
1039
- )
1040
-
1041
- case 'testimonial':
1042
- return (
1043
- <CardFooter className={cn(cardFooterVariants({ layout, justify: justify || 'between', align, gap }), 'max-sm:flex-col max-sm:items-stretch', props.className)}>
1044
- <div className='flex items-center gap-3'>
1045
- <Avatar className='ring-ring ring-2'>
1046
- <AvatarImage src={props.avatar} alt={props.name} />
1047
- <AvatarFallback className='text-xs'>{props.name?.[0]}</AvatarFallback>
1048
- </Avatar>
1049
- <div className='flex flex-col gap-0.5'>
1050
- <CardTitle className='flex items-center gap-1 text-sm'>{props.name}</CardTitle>
1051
- <CardDescription>@{props.handle}</CardDescription>
1052
- </div>
1053
- </div>
1054
- <div className='flex items-center gap-1'>
1055
- {[...Array(5)].map((_, i) => (
1056
- <StarIcon
1057
- key={i}
1058
- className={cn(
1059
- 'size-5',
1060
- i < (props.rating || 5)
1061
- ? 'fill-amber-500 stroke-amber-500 dark:fill-amber-400 dark:stroke-amber-400'
1062
- : 'stroke-amber-500 dark:stroke-amber-400'
1063
- )}
1064
- />
1065
- ))}
1066
- </div>
1067
- </CardFooter>
1068
- )
1069
-
1070
- case 'topImage':
1071
- if (!props.showActions) return null
1072
- return (
1073
- <CardFooter className={cn(cardFooterVariants({ layout, justify, align, gap }), 'max-sm:flex-col max-sm:items-stretch', props.className)}>
1074
- <Button onClick={props.onClick}>Explore More</Button>
1075
- <Button onClick={props.onClick2} variant='outline'>Download Now</Button>
1076
- </CardFooter>
1077
- )
1078
-
1079
- case 'meeting':
1080
- if (!props.avatars) return null
1081
- return (
1082
- <CardFooter className={cn(cardFooterVariants({ layout, justify, align, gap }), props.className)}>
1083
- <div className='flex -space-x-2 hover:space-x-1'>
1084
- {props.avatars.map((avatar: any, index: number) => (
1085
- <Avatar key={index} className='ring-background ring-2 transition-all duration-300 ease-in-out'>
1086
- <AvatarImage src={avatar.src} alt={avatar.name} />
1087
- <AvatarFallback className='text-xs'>{avatar.fallback}</AvatarFallback>
1088
- </Avatar>
1089
- ))}
1090
- </div>
1091
- </CardFooter>
1092
- )
1093
- case 'product':
1094
- case 'productTop':
1095
- case 'productBottom':
1096
- case 'productLeft':
1097
- case 'productRight':
1098
- break;
1099
- default:
1100
- return <CardFooter className={cn(cardFooterVariants({ layout, justify, align, gap }), className)} {...props} />
1101
- }
1102
- }
1103
-
1104
- // #endregion ===========================================================================
1105
- // CARDX IMAGE - STRUCTURAL VARIANTS
1106
- // #region ===========================================================================
1107
- export function CardXImage({ ...props }: any) {
1108
- const { card, } = useCardContext()
1109
-
1110
- switch (card) {
1111
- default:
1112
- return <CardImage {...props} />
1113
- }
1114
- }
1115
-
1116
- // #endregion ===========================================================================
1117
- // CARDX HEART - STRUCTURAL VARIANTS
1118
- // #region ===========================================================================
1119
- export function CardXHeart({ filled, ...props }: any) {
1120
- const [liked, setLiked] = useState(filled || false)
1121
- const { card, } = useCardContext()
1122
-
1123
- switch (card) {
1124
- case 'product':
1125
- return (
1126
- <Button
1127
- size='icon'
1128
- onClick={() => setLiked(!liked)}
1129
- className='bg-primary/10 hover:bg-primary/20 absolute top-4 right-4 rounded-full'
1130
- >
1131
- <CardHeart filled={liked} className={cn('h-4 w-4', liked ? 'fill-destructive stroke-destructive' : 'stroke-white')} />
1132
- <span className='sr-only'>Like</span>
1133
- </Button>
1134
- )
1135
-
1136
- default:
1137
- return <CardHeart {...props} />
1138
- }
1139
- }
1140
-
1141
- // #endregion ===========================================================================
1142
- // CARDX PRODUCT - STRUCTURAL VARIANTS
1143
- // #region ===========================================================================
1144
- export function CardXProduct({ variant, filled, ...props }: any) {
1145
- const { card, } = useCardContext()
1146
- switch (card) {
1147
- case 'productTop':
1148
- return (
1149
- <div className='relative max-w-md rounded-xl bg-gradient-to-r from-neutral-600 to-violet-300 pt-0 shadow-lg'>
1150
- <div className='flex h-60 items-center justify-center'>
1151
- <img src={props.src} alt='product' className='w-75' />
1152
- </div>
1153
- <Button
1154
- size='icon'
1155
- onClick={() => props.setLiked(!props.liked)}
1156
- className='bg-primary/10 hover:bg-primary/20 absolute top-4 right-4 rounded-full'
1157
- >
1158
- <HeartIcon className={cn(props.liked ? 'fill-destructive stroke-destructive' : 'stroke-white')} />
1159
- <span className='sr-only'>Like</span>
1160
- </Button>
1161
- {props.children}
1162
- </div>
1163
- )
1164
- case 'productBottom':
1165
- return (
1166
- <div className='relative max-w-md rounded-xl bg-gradient-to-r from-neutral-600 to-violet-300 pt-0 shadow-lg'>
1167
- {props.children}
1168
- <div className='flex h-60 items-center justify-center'>
1169
- <img src={props.src} alt='product' className='w-75' />
1170
- </div>
1171
- <Button
1172
- size='icon'
1173
- onClick={() => props.setLiked(!props.liked)}
1174
- className='bg-primary/10 hover:bg-primary/20 absolute top-4 right-4 rounded-full'
1175
- >
1176
- <HeartIcon className={cn(props.liked ? 'fill-destructive stroke-destructive' : 'stroke-white')} />
1177
- <span className='sr-only'>Like</span>
1178
- </Button>
1179
- </div>
1180
- )
1181
- case 'productLeft':
1182
- return (
1183
- <div className='relative flex items-center max-w-md rounded-xl bg-gradient-to-r from-neutral-600 to-violet-300 pt-0 shadow-lg'>
1184
-
1185
- <div className='flex h-60 items-center justify-center'>
1186
- <img src={props.src} alt='product' className='w-75' />
1187
- </div>
1188
- <Button
1189
- size='icon'
1190
- onClick={() => props.setLiked(!props.liked)}
1191
- className='bg-primary/10 hover:bg-primary/20 absolute top-4 right-4 rounded-full'
1192
- >
1193
- <HeartIcon className={cn(props.liked ? 'fill-destructive stroke-destructive' : 'stroke-white')} />
1194
- <span className='sr-only'>Like</span>
1195
- </Button>
1196
- {props.children}
1197
- </div>
1198
- )
1199
- case 'productRight':
1200
- return (
1201
- <div className='relative flex items-center max-w-md rounded-xl bg-gradient-to-r from-neutral-600 to-violet-300 pt-0 shadow-lg'>
1202
- {props.children}
1203
- <div className='flex h-60 items-center justify-center'>
1204
- <img src={props.src} alt='product' className='w-75' />
1205
- </div>
1206
- <Button
1207
- size='icon'
1208
- onClick={() => props.setLiked(!props.liked)}
1209
- className='bg-primary/10 hover:bg-primary/20 absolute top-4 right-4 rounded-full'
1210
- >
1211
- <HeartIcon className={cn(props.liked ? 'fill-destructive stroke-destructive' : 'stroke-white')} />
1212
- <span className='sr-only'>Like</span>
1213
- </Button>
1214
- </div>
1215
- )
1216
- default:
1217
- return <CardHeart {...props} />
1218
- }
1219
- }
1220
-
1221
-
1222
- export function CardXGroup({ variant, className, children }: any) {
1223
- switch (variant) {
1224
- case 'vertical':
1225
- return (
1226
- <div className={cn('flex flex-col *:rounded-none *:shadow-none *:not-last:border-b-0 *:first:rounded-t-xl *:last:rounded-b-xl', className)}>
1227
- {children}
1228
- </div>
1229
- )
1230
- default:
1231
- return (
1232
- <div className={cn('flex *:rounded-none *:shadow-none max-xl:flex-col max-xl:*:not-last:border-b-0 max-xl:*:first:rounded-t-xl max-xl:*:last:rounded-b-xl xl:*:not-last:border-r-0 xl:*:first:rounded-l-xl xl:*:last:rounded-r-xl', className)}>
1233
- {children}
1234
- </div>
1235
- )
1236
- }
1237
- }
1238
-
1239
- // #endregion ===========================================================================
1240
- // DEMO COMPONENT
1241
- // #region ===========================================================================
1242
- export function CardXDemo() {
1243
- const [closableActive, setClosableActive] = useState(true)
1244
- const [tweetState, setTweetState] = useState({
1245
- liked: false,
1246
- commented: false,
1247
- retweeted: false,
1248
- shared: false
1249
- })
1250
- const [productLiked, setProductLiked] = useState(false)
1251
-
1252
- return (
1253
- <div className="space-y-12 p-6 max-w-5xl mx-auto">
1254
- {/* Default */}
1255
- <div>
1256
- <h3 className="text-lg font-semibold mb-4">Default</h3>
1257
- <CardX className="max-w-md">
1258
- <CardXHeader>
1259
- <CardXTitle>Card Title</CardXTitle>
1260
- <CardXDescription>Card description goes here</CardXDescription>
1261
- </CardXHeader>
1262
- <CardXContent>
1263
- This is the default card content. You can put any content here.
1264
- </CardXContent>
1265
- <CardXFooter>
1266
- <Button>Action</Button>
1267
- </CardXFooter>
1268
- </CardX>
1269
- </div>
1270
-
1271
- {/* Spotlight */}
1272
- <div>
1273
- <h3 className="text-lg font-semibold mb-4">Spotlight</h3>
1274
- <CardX card="spotlight">
1275
- <CardXHeader>
1276
- <CardXTitle>Spotlight Card</CardXTitle>
1277
- <CardXDescription>Hover to see the effect</CardXDescription>
1278
- </CardXHeader>
1279
- <CardXContent>
1280
- This card has a beautiful spotlight effect that follows your cursor.
1281
- </CardXContent>
1282
- </CardX>
1283
- </div>
1284
-
1285
- {/* 3D */}
1286
- <div>
1287
- <h3 className="text-lg font-semibold mb-4">3D Card</h3>
1288
- <div className="card-3d-wrapper">
1289
- <CardX card="3d" className="max-w-md">
1290
- <CardXHeader>
1291
- <CardXTitle>3D Interactive Card</CardXTitle>
1292
- <CardXDescription>Hover to see 3D effect</CardXDescription>
1293
- </CardXHeader>
1294
- <CardXContent image="https://images.unsplash.com/photo-1682687220742-aba13b6e50ba?w=500&h=300&fit=crop">
1295
- This card tilts in 3D when you hover over it.
1296
- </CardXContent>
1297
- </CardX>
1298
- </div>
1299
- </div>
1300
-
1301
- {/* Closable */}
1302
- <div>
1303
- <h3 className="text-lg font-semibold mb-4">Closable</h3>
1304
- {closableActive && (
1305
- <CardX card="closable" className="max-w-md">
1306
- <CardXHeader onClose={() => setClosableActive(false)}>
1307
- Important Notice
1308
- </CardXHeader>
1309
- <CardXContent actionText="Got it">
1310
- This is an important message that can be dismissed.
1311
- </CardXContent>
1312
- </CardX>
1313
- )}
1314
- </div>
1315
-
1316
- {/* Tweet */}
1317
- <div>
1318
- <h3 className="text-lg font-semibold mb-4">Tweet Card</h3>
1319
- <CardX card="tweet" className="max-w-md">
1320
- <CardXHeader
1321
- avatar="https://avatar.vercel.sh/john"
1322
- name="John Doe"
1323
- handle="johndoe"
1324
- verified={true}
1325
- />
1326
- <CardXContent image="https://images.unsplash.com/photo-1682687220742-aba13b6e50ba?w=500&h=300&fit=crop">
1327
- Just shipped a new feature! Check it out and let me know what you think. 🚀
1328
- </CardXContent>
1329
- <CardXFooter
1330
- state={tweetState}
1331
- setState={setTweetState}
1332
- likes="124"
1333
- comments="32"
1334
- retweets="18"
1335
- shares="7"
1336
- />
1337
- </CardX>
1338
- </div>
1339
-
1340
- {/* Product */}
1341
- <div>
1342
- <h3 className="text-lg font-semibold mb-4">Product Card</h3>
1343
- <CardX card="product" className="max-w-md border-none">
1344
- <CardXProduct src="https://images.unsplash.com/photo-1542291026-7eec264c27ff?w=300&fit=crop" liked={productLiked} setLiked={setProductLiked}>
1345
- <Card className="border-none">
1346
- <CardXHeader title="Nike Air Max" info1="EU42" info2="Black/White" />
1347
- <CardXContent>
1348
- Crossing hardwood comfort with off-court flair. '80s-Inspired construction, bold details and nothin'-but-net style.
1349
- </CardXContent>
1350
- <CardXFooter price1="Price" price2="$129.99" buttonLabel="Add to cart" onAddToCart={() => console.log('Added')} />
1351
- </Card>
1352
- </CardXProduct>
1353
- </CardX>
1354
- </div>
1355
-
1356
- {/* Product Top */}
1357
- <div>
1358
- <h3 className="text-lg font-semibold mb-4">Product Top</h3>
1359
- <CardX card="productTop" className="border-none">
1360
- <CardXProduct src="https://images.unsplash.com/photo-1542291026-7eec264c27ff?w=300&fit=crop" liked={productLiked} setLiked={setProductLiked}>
1361
- <Card className="border-none">
1362
- <CardXHeader title="Nike Air Max" info1="EU42" info2="Black/White" />
1363
- <CardXContent>
1364
- Premium materials and timeless design.
1365
- </CardXContent>
1366
- <CardXFooter price2="$129.99" buttonLabel="Buy Now" />
1367
- </Card>
1368
- </CardXProduct>
1369
- </CardX>
1370
- </div>
1371
-
1372
- {/* Product Bottom */}
1373
- <div>
1374
- <h3 className="text-lg font-semibold mb-4">Product Bottom</h3>
1375
- <CardX card="productBottom" className="border-none">
1376
- <CardXProduct src="https://images.unsplash.com/photo-1542291026-7eec264c27ff?w=300&fit=crop" liked={productLiked} setLiked={setProductLiked}>
1377
- <Card className="border-none">
1378
- <CardXHeader title="Nike Air Max" info1="EU42" info2="Black/White" />
1379
- <CardXContent>
1380
- Premium materials and timeless design.
1381
- </CardXContent>
1382
- <CardXFooter price2="$129.99" buttonLabel="Buy Now" />
1383
- </Card>
1384
- </CardXProduct>
1385
- </CardX>
1386
- </div>
1387
-
1388
- {/* Product Left */}
1389
- <div>
1390
- <h3 className="text-lg font-semibold mb-4">Product Left</h3>
1391
- <CardX card="productLeft" className="border-none">
1392
- <CardXProduct src="https://images.unsplash.com/photo-1542291026-7eec264c27ff?w=300&fit=crop" liked={productLiked} setLiked={setProductLiked}>
1393
- <Card className="border-none">
1394
- <CardXHeader title="Nike Air Max" info1="EU42" info2="Black/White" />
1395
- <CardXContent>
1396
- Premium materials and timeless design.
1397
- </CardXContent>
1398
- <CardXFooter price2="$129.99" buttonLabel="Buy Now" />
1399
- </Card>
1400
- </CardXProduct>
1401
- </CardX>
1402
- </div>
1403
-
1404
- {/* Product Right */}
1405
- <div>
1406
- <h3 className="text-lg font-semibold mb-4">Product Right</h3>
1407
- <CardX card="productRight" className="border-none">
1408
- <CardXProduct src="https://images.unsplash.com/photo-1542291026-7eec264c27ff?w=300&fit=crop" liked={productLiked} setLiked={setProductLiked}>
1409
- <Card className="border-none">
1410
- <CardXHeader title="Nike Air Max" info1="EU42" info2="Black/White" />
1411
- <CardXContent>
1412
- Premium materials and timeless design.
1413
- </CardXContent>
1414
- <CardXFooter price2="$129.99" buttonLabel="Buy Now" />
1415
- </Card>
1416
- </CardXProduct>
1417
- </CardX>
1418
- </div>
1419
-
1420
- {/* Testimonial */}
1421
- <div>
1422
- <h3 className="text-lg font-semibold mb-4">Testimonial</h3>
1423
- <CardX card="testimonial" className="max-w-md">
1424
- <CardXContent>
1425
- "This product has completely transformed how I work. The attention to detail is incredible!"
1426
- </CardXContent>
1427
- <CardXFooter
1428
- avatar="https://avatar.vercel.sh/sarah"
1429
- name="Sarah Johnson"
1430
- handle="sarahj"
1431
- rating={5}
1432
- />
1433
- </CardX>
1434
- </div>
1435
-
1436
- {/* Overlay */}
1437
- <div>
1438
- <h3 className="text-lg font-semibold mb-4">Overlay</h3>
1439
- <CardX card="overlay">
1440
- <CardXHeader>Stunning Destination</CardXHeader>
1441
- <CardXContent image="https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=500&h=300&fit=crop">
1442
- Discover the beauty of nature in this breathtaking location.
1443
- </CardXContent>
1444
- </CardX>
1445
- </div>
1446
-
1447
- {/* Horizontal */}
1448
- <div>
1449
- <h3 className="text-lg font-semibold mb-4">Horizontal</h3>
1450
- <CardX card="horizontal" className="max-w-2xl">
1451
- <CardXContent
1452
- title="Featured Article"
1453
- description="Learn about the latest trends"
1454
- actionText="Read More"
1455
- >
1456
- <img
1457
- src="https://images.unsplash.com/photo-1498050108023-c5249f4df085?w=300&h=200&fit=crop"
1458
- alt="Article"
1459
- className="h-full w-full rounded-l-xl object-cover"
1460
- />
1461
- </CardXContent>
1462
- </CardX>
1463
- </div>
1464
-
1465
- {/* Top Image */}
1466
- <div>
1467
- <h3 className="text-lg font-semibold mb-4">Top Image</h3>
1468
- <CardX card="topImage" className="max-w-md">
1469
- <CardXContent image="https://images.unsplash.com/photo-1682687220742-aba13b6e50ba?w=500&h=300&fit=crop" />
1470
- <CardXHeader>
1471
- <CardXTitle>Beautiful Landscape</CardXTitle>
1472
- <CardXDescription>Explore the wonders of nature</CardXDescription>
1473
- </CardXHeader>
1474
- <CardXFooter showActions onClick={() => console.log('explore')} onClick2={() => console.log('download')} />
1475
- </CardX>
1476
- </div>
1477
-
1478
- {/* Bottom Image */}
1479
- <div>
1480
- <h3 className="text-lg font-semibold mb-4">Bottom Image</h3>
1481
- <CardX card="bottomImage" className="max-w-md">
1482
- <CardXHeader>
1483
- <CardXTitle>Amazing View</CardXTitle>
1484
- <CardXDescription>Experience the beauty</CardXDescription>
1485
- </CardXHeader>
1486
- <CardXContent image="https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=500&h=300&fit=crop" />
1487
- </CardX>
1488
- </div>
1489
-
1490
- {/* Meeting */}
1491
- <div>
1492
- <h3 className="text-lg font-semibold mb-4">Meeting</h3>
1493
- <CardX card="meeting" className="max-w-md">
1494
- <CardXHeader>
1495
- <CardXTitle>Team Meeting</CardXTitle>
1496
- <CardXDescription>Wednesday, 2:00 PM</CardXDescription>
1497
- </CardXHeader>
1498
- <CardXContent
1499
- items={[
1500
- 'Review Q4 goals',
1501
- 'Discuss new project timeline',
1502
- 'Team feedback session'
1503
- ]}
1504
- >
1505
- Join us for our weekly sync to align on priorities.
1506
- </CardXContent>
1507
- <CardXFooter
1508
- avatars={[
1509
- { src: 'https://avatar.vercel.sh/john', name: 'John', fallback: 'JD' },
1510
- { src: 'https://avatar.vercel.sh/sarah', name: 'Sarah', fallback: 'SJ' },
1511
- { src: 'https://avatar.vercel.sh/mike', name: 'Mike', fallback: 'MW' }
1512
- ]}
1513
- />
1514
- </CardX>
1515
- </div>
1516
-
1517
- {/* Invite */}
1518
- <div>
1519
- <h3 className="text-lg font-semibold mb-4">Invite</h3>
1520
- <CardX card="invite" className="max-w-md">
1521
- <CardXHeader>
1522
- <CardXTitle>Team Members</CardXTitle>
1523
- <CardXDescription>Manage your team</CardXDescription>
1524
- </CardXHeader>
1525
- <CardXContent
1526
- showInvite
1527
- members={[
1528
- { avatar: 'https://avatar.vercel.sh/john', name: 'John Doe', role: 'Developer', fallback: 'JD' },
1529
- { avatar: 'https://avatar.vercel.sh/sarah', name: 'Sarah Smith', role: 'Designer', fallback: 'SS' },
1530
- { avatar: 'https://avatar.vercel.sh/mike', name: 'Mike Wilson', role: 'Manager', fallback: 'MW' }
1531
- ]}
1532
- />
1533
- </CardX>
1534
- </div>
1535
-
1536
- {/* Card Group Vertical */}
1537
- <div>
1538
- <h3 className="text-lg font-semibold mb-4">Card Group - Vertical</h3>
1539
- <CardXGroup variant="vertical" className="max-w-md">
1540
- <CardX>
1541
- <CardXHeader>
1542
- <CardXTitle>First Card</CardXTitle>
1543
- </CardXHeader>
1544
- <CardXContent>Content for first card</CardXContent>
1545
- </CardX>
1546
- <CardX>
1547
- <CardXHeader>
1548
- <CardXTitle>Second Card</CardXTitle>
1549
- </CardXHeader>
1550
- <CardXContent>Content for second card</CardXContent>
1551
- </CardX>
1552
- <CardX>
1553
- <CardXHeader>
1554
- <CardXTitle>Third Card</CardXTitle>
1555
- </CardXHeader>
1556
- <CardXContent>Content for third card</CardXContent>
1557
- </CardX>
1558
- </CardXGroup>
1559
- </div>
1560
-
1561
- {/* Card Group Horizontal */}
1562
- <div>
1563
- <h3 className="text-lg font-semibold mb-4">Card Group - Horizontal</h3>
1564
- <CardXGroup>
1565
- <CardX>
1566
- <CardXHeader>
1567
- <CardXTitle>Card 1</CardXTitle>
1568
- </CardXHeader>
1569
- <CardXContent>First card content</CardXContent>
1570
- </CardX>
1571
- <CardX>
1572
- <CardXHeader>
1573
- <CardXTitle>Card 2</CardXTitle>
1574
- </CardXHeader>
1575
- <CardXContent>Second card content</CardXContent>
1576
- </CardX>
1577
- <CardX>
1578
- <CardXHeader>
1579
- <CardXTitle>Card 3</CardXTitle>
1580
- </CardXHeader>
1581
- <CardXContent>Third card content</CardXContent>
1582
- </CardX>
1583
- </CardXGroup>
1584
- </div>
1585
- </div>
1586
- )
1587
- }
1588
- export function CardXDemo1() {
1589
- const [closableVisible, setClosableVisible] = useState(true)
1590
-
1591
- const avatars = [
1592
- { src: 'https://cdn.shadcnstudio.com/ss-assets/avatar/avatar-1.png', name: 'User 1', fallback: 'U1' },
1593
- { src: 'https://cdn.shadcnstudio.com/ss-assets/avatar/avatar-2.png', name: 'User 2', fallback: 'U2' },
1594
- { src: 'https://cdn.shadcnstudio.com/ss-assets/avatar/avatar-3.png', name: 'User 3', fallback: 'U3' },
1595
- ]
1596
-
1597
- const members = [
1598
- { name: 'Jimmy Anderson', role: 'UI Designer', avatar: 'https://cdn.shadcnstudio.com/ss-assets/avatar/avatar-5.png', fallback: 'JA' },
1599
- { name: 'Dean Ambrose', role: 'UX Designer', avatar: 'https://cdn.shadcnstudio.com/ss-assets/avatar/avatar-2.png', fallback: 'DA' },
1600
- { name: 'Anita John', role: 'Branding', avatar: 'https://cdn.shadcnstudio.com/ss-assets/avatar/avatar-3.png', fallback: 'AJ' },
1601
- ]
1602
-
1603
- const dropdownItems = [
1604
- { name: 'View Profile', onSelect: () => console.log('View Profile') },
1605
- { name: 'Mute', onSelect: () => console.log('Mute') },
1606
- { name: 'Block', onSelect: () => console.log('Block') },
1607
- { name: 'Report', onSelect: () => console.log('Report') },
1608
- ]
1609
-
1610
- return (
1611
- <div className='space-y-12 p-6 max-w-4xl mx-auto'>
1612
- <div>
1613
- <h3 className='text-lg font-semibold mb-4'>Default Card</h3>
1614
- <CardX className='max-w-md'>
1615
- <CardXHeader>
1616
- <CardXTitle>Default Card</CardXTitle>
1617
- <CardXDescription>This is the standard card layout</CardXDescription>
1618
- </CardXHeader>
1619
- <CardXContent>
1620
- Basic card content goes here with no special variants applied.
1621
- </CardXContent>
1622
- <CardXFooter>
1623
- <Button>Action</Button>
1624
- </CardXFooter>
1625
- </CardX>
1626
- </div>
1627
-
1628
- <div>
1629
- <h3 className='text-lg font-semibold mb-4'>Spotlight Card</h3>
1630
- <CardX card='spotlight'>
1631
- <CardXHeader>
1632
- <CardXTitle>Hover for the Glow-Up</CardXTitle>
1633
- </CardXHeader>
1634
- <CardXContent>
1635
- Glide your cursor here and watch magic unfold — an experience designed just for you.
1636
- </CardXContent>
1637
- </CardX>
1638
- </div>
1639
-
1640
- <div>
1641
- <h3 className='text-lg font-semibold mb-4'>3D Hover Card</h3>
1642
- <div className='card-3d-wrapper'>
1643
- <CardX card='3d' className='max-w-md'>
1644
- <CardXHeader>
1645
- <CardXTitle>Dynamic 3D Hover Card</CardXTitle>
1646
- </CardXHeader>
1647
- <CardXContent image='https://cdn.shadcnstudio.com/ss-assets/components/card/image-10.png?width=350&format=auto'>
1648
- Experience interactive depth and motion with this sleek 3D hover effect.
1649
- </CardXContent>
1650
- </CardX>
1651
- </div>
1652
- </div>
1653
-
1654
- {closableVisible && (
1655
- <div>
1656
- <h3 className='text-lg font-semibold mb-4'>Closable Card</h3>
1657
- <CardX card='closable' className='max-w-lg shadow-none'>
1658
- <CardXHeader onClose={() => setClosableVisible(false)}>
1659
- Have a project in mind
1660
- </CardXHeader>
1661
- <CardXContent actionText='Contact Our Team'>
1662
- Let's discuss! Our Assistant team is excited to hear about your projects, ideas and questions.
1663
- </CardXContent>
1664
- </CardX>
1665
- </div>
1666
- )}
1667
-
1668
- <div>
1669
- <h3 className='text-lg font-semibold mb-4'>Tweet Card</h3>
1670
- <CardX card='tweet' className='max-w-md'>
1671
- <CardXHeader
1672
- name='Philip George'
1673
- handle='philip20'
1674
- verified
1675
- showFollow
1676
- avatar='https://cdn.shadcnstudio.com/ss-assets/avatar/avatar-5.png'
1677
- />
1678
- <CardXContent image='https://cdn.shadcnstudio.com/ss-assets/components/card/image-6.png?width=350&format=auto'>
1679
- Lost in the colors of the night 🌌✨ Sometimes the blur reveals more than clarity. #AbstractVibes #Dreamscape
1680
- </CardXContent>
1681
- <CardXFooter likes='2.1K' comments='1.4K' retweets='669' shares='1.1K' />
1682
- </CardX>
1683
- </div>
1684
-
1685
- <div>
1686
- <h3 className='text-lg font-semibold mb-4'>Product Card</h3>
1687
- <CardX card='product' className='max-w-md border-none'>
1688
- <div className='relative rounded-xl bg-gradient-to-r from-neutral-600 to-violet-300 shadow-lg'>
1689
- <div className='flex h-60 items-center justify-center'>
1690
- <img
1691
- src='https://cdn.shadcnstudio.com/ss-assets/components/card/image-11.png?width=300&format=auto'
1692
- alt='Nike Jordan Air Rev'
1693
- className='w-75'
1694
- />
1695
- </div>
1696
- <CardXHeart />
1697
- <Card className='border-none'>
1698
- <CardXHeader>
1699
- <CardXTitle>Nike Jordan Air Rev</CardXTitle>
1700
- <CardXDescription className='flex items-center gap-2'>
1701
- <Badge variant='outline' className='rounded-sm'>EU38</Badge>
1702
- <Badge variant='outline' className='rounded-sm'>Black and White</Badge>
1703
- </CardXDescription>
1704
- </CardXHeader>
1705
- <CardXContent>
1706
- Crossing hardwood comfort with off-court flair. '80s-Inspired construction, bold details and nothin'-but-net style.
1707
- </CardXContent>
1708
- <CardXFooter className='justify-between gap-3 max-sm:flex-col max-sm:items-stretch'>
1709
- <div className='flex flex-col'>
1710
- <span className='text-sm font-medium uppercase'>Price</span>
1711
- <span className='text-xl font-semibold'>$69.99</span>
1712
- </div>
1713
- <Button size='lg'>Add to cart</Button>
1714
- </CardXFooter>
1715
- </Card>
1716
- </div>
1717
- </CardX>
1718
- </div>
1719
-
1720
- <div>
1721
- <h3 className='text-lg font-semibold mb-4'>Product Card - Top Image</h3>
1722
- <CardXProduct card='productTop' src='https://cdn.shadcnstudio.com/ss-assets/components/card/image-11.png?width=300&format=auto'>
1723
- <Card className='border-none'>
1724
- <CardXHeader>
1725
- <CardXTitle>Premium Sneakers</CardXTitle>
1726
- <CardXDescription>Limited Edition</CardXDescription>
1727
- </CardXHeader>
1728
- <CardXContent>
1729
- Top-quality materials and craftsmanship.
1730
- </CardXContent>
1731
- <CardXFooter className='justify-between'>
1732
- <span className='text-xl font-semibold'>$129.99</span>
1733
- <Button>Buy Now</Button>
1734
- </CardXFooter>
1735
- </Card>
1736
- </CardXProduct>
1737
- </div>
1738
-
1739
- <div>
1740
- <h3 className='text-lg font-semibold mb-4'>Product Card - Bottom Image</h3>
1741
- <CardXProduct card='productBottom' src='https://cdn.shadcnstudio.com/ss-assets/components/card/image-11.png?width=300&format=auto'>
1742
- <Card className='border-none'>
1743
- <CardXHeader>
1744
- <CardXTitle>Sport Edition</CardXTitle>
1745
- <CardXDescription>Performance Ready</CardXDescription>
1746
- </CardXHeader>
1747
- <CardXContent>
1748
- Designed for maximum comfort and style.
1749
- </CardXContent>
1750
- <CardXFooter className='justify-between'>
1751
- <span className='text-xl font-semibold'>$99.99</span>
1752
- <Button>Add to Cart</Button>
1753
- </CardXFooter>
1754
- </Card>
1755
- </CardXProduct>
1756
- </div>
1757
-
1758
- <div>
1759
- <h3 className='text-lg font-semibold mb-4'>Product Card - Left Image</h3>
1760
- <CardXProduct card='productLeft' src='https://cdn.shadcnstudio.com/ss-assets/components/card/image-11.png?width=300&format=auto'>
1761
- <Card className='border-none'>
1762
- <CardXHeader>
1763
- <CardXTitle>Classic Style</CardXTitle>
1764
- <CardXDescription>Timeless Design</CardXDescription>
1765
- </CardXHeader>
1766
- <CardXContent>
1767
- Perfect for everyday wear.
1768
- </CardXContent>
1769
- <CardXFooter className='justify-between'>
1770
- <span className='text-xl font-semibold'>$89.99</span>
1771
- <Button>Shop Now</Button>
1772
- </CardXFooter>
1773
- </Card>
1774
- </CardXProduct>
1775
- </div>
1776
-
1777
- <div>
1778
- <h3 className='text-lg font-semibold mb-4'>Product Card - Right Image</h3>
1779
- <CardXProduct card='productRight' src='https://cdn.shadcnstudio.com/ss-assets/components/card/image-11.png?width=300&format=auto'>
1780
- <Card className='border-none'>
1781
- <CardXHeader>
1782
- <CardXTitle>Modern Collection</CardXTitle>
1783
- <CardXDescription>Latest Release</CardXDescription>
1784
- </CardXHeader>
1785
- <CardXContent>
1786
- Contemporary design meets comfort.
1787
- </CardXContent>
1788
- <CardXFooter className='justify-between'>
1789
- <span className='text-xl font-semibold'>$119.99</span>
1790
- <Button>Purchase</Button>
1791
- </CardXFooter>
1792
- </Card>
1793
- </CardXProduct>
1794
- </div>
1795
-
1796
- <div>
1797
- <h3 className='text-lg font-semibold mb-4'>Testimonial Card</h3>
1798
- <CardX card='testimonial' className='max-w-md border-none'>
1799
- <CardXContent>
1800
- Incredible time-saver! shadcn/studio has made UI development a breeze. The pre build components are not only visually appealing but also highly customizable.
1801
- </CardXContent>
1802
- <CardXFooter
1803
- name='Sam Green'
1804
- handle='SamG11'
1805
- avatar='https://cdn.shadcnstudio.com/ss-assets/avatar/avatar-5.png'
1806
- rating={4}
1807
- />
1808
- </CardX>
1809
- </div>
1810
-
1811
- <div>
1812
- <h3 className='text-lg font-semibold mb-4'>Overlay Card</h3>
1813
- <CardX card='overlay'>
1814
- <CardXContent image='https://cdn.shadcnstudio.com/ss-assets/components/card/image-8.png?widht=448&height=280&format=auto'>
1815
- Step into a world where imagination takes the lead and every pixel tells a story.
1816
- </CardXContent>
1817
- <CardXHeader>Creative Catalyst</CardXHeader>
1818
- </CardX>
1819
- </div>
1820
-
1821
- <div>
1822
- <h3 className='text-lg font-semibold mb-4'>Horizontal Card</h3>
1823
- <CardX card='horizontal' className='max-w-lg py-0 sm:flex-row sm:gap-0'>
1824
- <CardXContent
1825
- title='Dreamy Colorwave Gradient'
1826
- description='A smooth blend of vibrant pinks, purples, and blues for a magical touch.'
1827
- image='https://cdn.shadcnstudio.com/ss-assets/components/card/image-3.png'
1828
- actionText='Explore More'
1829
- >
1830
- <img
1831
- src='https://cdn.shadcnstudio.com/ss-assets/components/card/image-3.png'
1832
- alt='Banner'
1833
- className='size-full rounded-l-xl'
1834
- />
1835
- </CardXContent>
1836
- </CardX>
1837
- </div>
1838
-
1839
- <div>
1840
- <h3 className='text-lg font-semibold mb-4'>Top Image Card</h3>
1841
- <CardX card='topImage' className='max-w-md pt-0'>
1842
- <CardXContent image='https://cdn.shadcnstudio.com/ss-assets/components/card/image-2.png?height=280&format=auto' />
1843
- <CardXHeader>
1844
- <CardXTitle>Ethereal Swirl Gradient</CardXTitle>
1845
- <CardXDescription>Smooth, flowing gradients blending rich reds and blues in an abstract swirl.</CardXDescription>
1846
- </CardXHeader>
1847
- <CardXFooter showActions />
1848
- </CardX>
1849
- </div>
1850
-
1851
- <div>
1852
- <h3 className='text-lg font-semibold mb-4'>Bottom Image Card</h3>
1853
- <CardX card='bottomImage' className='max-w-md pb-0'>
1854
- <CardXHeader>
1855
- <CardXTitle>Fluid Gradient Flow</CardXTitle>
1856
- <CardXDescription>A vibrant and abstract background with smooth gradient curves.</CardXDescription>
1857
- </CardXHeader>
1858
- <CardXContent image='https://cdn.shadcnstudio.com/ss-assets/components/card/image-1.png?height=280&format=auto' />
1859
- </CardX>
1860
- </div>
1861
-
1862
- <div>
1863
- <h3 className='text-lg font-semibold mb-4'>Meeting Notes Card</h3>
1864
- <CardX card='meeting' className='max-w-md'>
1865
- <CardXHeader>
1866
- <CardXTitle>Meeting Notes</CardXTitle>
1867
- <CardXDescription>Transcript from the meeting with the client.</CardXDescription>
1868
- </CardXHeader>
1869
- <CardXContent items={[
1870
- 'New analytics widgets for daily/weekly metrics',
1871
- 'Simplified navigation menu',
1872
- 'Dark mode support',
1873
- 'Timeline: 6 weeks',
1874
- 'Follow-up meeting scheduled for next Tuesday'
1875
- ]}>
1876
- Client requested dashboard redesign with focus on mobile responsiveness.
1877
- </CardXContent>
1878
- <CardXFooter avatars={avatars} />
1879
- </CardX>
1880
- </div>
1881
-
1882
- <div>
1883
- <h3 className='text-lg font-semibold mb-4'>Invite Card</h3>
1884
- <CardX card='invite' className='w-full max-w-lg'>
1885
- <CardXHeader>
1886
- <CardXTitle>Team Members</CardXTitle>
1887
- </CardXHeader>
1888
- <CardXContent showInvite members={members} />
1889
- </CardX>
1890
- </div>
1891
-
1892
- <div>
1893
- <h3 className='text-lg font-semibold mb-4'>Card Group - Horizontal (Default)</h3>
1894
- <CardXGroup>
1895
- <CardX card='topImage' className='overflow-hidden pt-0'>
1896
- <CardXContent image='https://cdn.shadcnstudio.com/ss-assets/components/card/image-7.png?width=368&format=auto' />
1897
- <CardXHeader>
1898
- <CardXTitle>Mystical Blue Swirl</CardXTitle>
1899
- <CardXDescription>
1900
- Dive into the depths of an enchanting swirl where vibrant blues and soft pinks merge seamlessly.
1901
- </CardXDescription>
1902
- </CardXHeader>
1903
- <CardXFooter showActions />
1904
- </CardX>
1905
- <CardX card='topImage' className='overflow-hidden pt-0'>
1906
- <CardXContent image='https://cdn.shadcnstudio.com/ss-assets/components/card/image-4.png?width=368&format=auto' />
1907
- <CardXHeader>
1908
- <CardXTitle>Fiery Sunset Gradient</CardXTitle>
1909
- <CardXDescription>
1910
- Experience the warmth of a radiant sunset with flowing gradients of red, orange, and yellow.
1911
- </CardXDescription>
1912
- </CardXHeader>
1913
- <CardXFooter showActions />
1914
- </CardX>
1915
- <CardX card='topImage' className='overflow-hidden pt-0'>
1916
- <CardXContent image='https://cdn.shadcnstudio.com/ss-assets/components/card/image-5.png?width=368&format=auto' />
1917
- <CardXHeader>
1918
- <CardXTitle>Cosmic Blue Waves</CardXTitle>
1919
- <CardXDescription>
1920
- Explore the mysteries of the cosmos with deep, swirling waves of blue and purple.
1921
- </CardXDescription>
1922
- </CardXHeader>
1923
- <CardXFooter showActions />
1924
- </CardX>
1925
- </CardXGroup>
1926
- </div>
1927
-
1928
- <div>
1929
- <h3 className='text-lg font-semibold mb-4'>Card Group - Vertical</h3>
1930
- <CardXGroup variant='vertical'>
1931
- <CardX className='max-w-md'>
1932
- <CardXHeader>
1933
- <CardXTitle>First Card</CardXTitle>
1934
- <CardXDescription>First item in vertical stack</CardXDescription>
1935
- </CardXHeader>
1936
- <CardXContent>Content for the first card</CardXContent>
1937
- </CardX>
1938
- <CardX className='max-w-md'>
1939
- <CardXHeader>
1940
- <CardXTitle>Second Card</CardXTitle>
1941
- <CardXDescription>Second item in vertical stack</CardXDescription>
1942
- </CardXHeader>
1943
- <CardXContent>Content for the second card</CardXContent>
1944
- </CardX>
1945
- <CardX className='max-w-md'>
1946
- <CardXHeader>
1947
- <CardXTitle>Third Card</CardXTitle>
1948
- <CardXDescription>Third item in vertical stack</CardXDescription>
1949
- </CardXHeader>
1950
- <CardXContent>Content for the third card</CardXContent>
1951
- </CardX>
1952
- </CardXGroup>
1953
- </div>
1954
- </div>
1955
- )
1956
- }
1957
-
1958
-
1959
-
1960
- const CardMeetingNotesDemo = () => {
1961
- return (
1962
- <Card className='max-w-md'>
1963
- <CardHeader>
1964
- <CardTitle>Meeting Notes</CardTitle>
1965
- <CardDescription>Transcript from the meeting with the client.</CardDescription>
1966
- </CardHeader>
1967
- <CardContent className='text-sm'>
1968
- <p>Client requested dashboard redesign with focus on mobile responsiveness.</p>
1969
- <ol className='mt-4 flex list-decimal flex-col gap-2 pl-6'>
1970
- <li>New analytics widgets for daily/weekly metrics</li>
1971
- <li>Simplified navigation menu</li>
1972
- <li>Dark mode support</li>
1973
- <li>Timeline: 6 weeks</li>
1974
- <li>Follow-up meeting scheduled for next Tuesday</li>
1975
- </ol>
1976
- </CardContent>
1977
- <CardFooter>
1978
- <div className='flex -space-x-2 hover:space-x-1'>
1979
- {avatars.map((avatar, index) => (
1980
- <Avatar key={index} className='ring-background ring-2 transition-all duration-300 ease-in-out'>
1981
- <AvatarImage src={avatar.src} alt={avatar.name} />
1982
- <AvatarFallback className='text-xs'>{avatar.fallback}</AvatarFallback>
1983
- </Avatar>
1984
- ))}
1985
- </div>
1986
- </CardFooter>
1987
- </Card>
1988
- )
1989
- }
1990
-
1991
- const CardInviteCardDemo = () => {
1992
- return (
1993
- <Card className='w-full max-w-lg'>
1994
- <CardHeader>
1995
- <CardTitle>Meeting Notes</CardTitle>
1996
- </CardHeader>
1997
- <CardContent className='grid gap-4 sm:grid-cols-2'>
1998
- <div className='flex items-center gap-4'>
1999
- <CircleFadingPlusIcon />
2000
- <span className='text-sm font-semibold'>Invite Member </span>
2001
- </div>
2002
- <div className='flex items-center gap-4'>
2003
- <Avatar>
2004
- <AvatarImage src='https://cdn.shadcnstudio.com/ss-assets/avatar/avatar-5.png' alt='Hallie Richards' />
2005
- <AvatarFallback className='text-xs'>JA</AvatarFallback>
2006
- </Avatar>
2007
- <div className='flex flex-col'>
2008
- <span className='text-sm font-semibold'>Jimmy Androson </span>
2009
- <span className='text-muted-foreground text-sm'>UI Designer</span>
2010
- </div>
2011
- </div>
2012
- <div className='flex items-center gap-4'>
2013
- <Avatar>
2014
- <AvatarImage src='https://cdn.shadcnstudio.com/ss-assets/avatar/avatar-2.png' alt='Hallie Richards' />
2015
- <AvatarFallback className='text-xs'>DA</AvatarFallback>
2016
- </Avatar>
2017
- <div className='flex flex-col'>
2018
- <span className='text-sm font-semibold'>Dean Ambrose </span>
2019
- <span className='text-muted-foreground text-sm'>UX Designer</span>
2020
- </div>
2021
- </div>
2022
- <div className='flex items-center gap-4'>
2023
- <Avatar>
2024
- <AvatarImage src='https://cdn.shadcnstudio.com/ss-assets/avatar/avatar-3.png' alt='Hallie Richards' />
2025
- <AvatarFallback className='text-xs'>HR</AvatarFallback>
2026
- </Avatar>
2027
- <div className='flex flex-col'>
2028
- <span className='text-sm font-semibold'>Anita John</span>
2029
- <span className='text-muted-foreground text-sm'>Branding</span>
2030
- </div>
2031
- </div>
2032
- <div></div>
2033
- <div></div>
2034
- </CardContent>
2035
- </Card>
2036
- )
2037
- }
2038
-
2039
- const CardBottomImageDemo = () => {
2040
- return (
2041
- <Card className='max-w-md pb-0'>
2042
- <CardHeader>
2043
- <CardTitle>Fluid Gradient Flow</CardTitle>
2044
- <CardDescription>A vibrant and abstract background with smooth gradient curves.</CardDescription>
2045
- </CardHeader>
2046
- <CardContent className='px-0'>
2047
- <img
2048
- src='https://cdn.shadcnstudio.com/ss-assets/components/card/image-1.png?height=280&format=auto'
2049
- alt='Banner'
2050
- className='aspect-video h-70 rounded-b-xl object-cover'
2051
- />
2052
- </CardContent>
2053
- </Card>
2054
- )
2055
- }
2056
-
2057
- const CardTopImageDemo = () => {
2058
- return (
2059
- <Card className='max-w-md pt-0'>
2060
- <CardContent className='px-0'>
2061
- <img
2062
- src='https://cdn.shadcnstudio.com/ss-assets/components/card/image-2.png?height=280&format=auto'
2063
- alt='Banner'
2064
- className='aspect-video h-70 rounded-t-xl object-cover'
2065
- />
2066
- </CardContent>
2067
- <CardHeader>
2068
- <CardTitle>Ethereal Swirl Gradient</CardTitle>
2069
- <CardDescription>Smooth, flowing gradients blending rich reds and blues in an abstract swirl.</CardDescription>
2070
- </CardHeader>
2071
- <CardFooter className='gap-3 max-sm:flex-col max-sm:items-stretch'>
2072
- <Button>Explore More</Button>
2073
- <Button variant={'outline'}>Download Now</Button>
2074
- </CardFooter>
2075
- </Card>
2076
- )
2077
- }
2078
-
2079
- const CardHorizontalDemo = () => {
2080
- return (
2081
- <Card className='max-w-lg py-0 sm:flex-row sm:gap-0'>
2082
- <CardContent className='grow-1 px-0'>
2083
- <img
2084
- src='https://cdn.shadcnstudio.com/ss-assets/components/card/image-3.png'
2085
- alt='Banner'
2086
- className='size-full rounded-l-xl'
2087
- />
2088
- </CardContent>
2089
- <div className='sm:min-w-54'>
2090
- <CardHeader className='pt-6'>
2091
- <CardTitle>Dreamy Colorwave Gradient</CardTitle>
2092
- <CardDescription>A smooth blend of vibrant pinks, purples, and blues for a magical touch.</CardDescription>
2093
- </CardHeader>
2094
- <CardFooter className='gap-3 py-6'>
2095
- <Button className='bg-transparent bg-gradient-to-br from-purple-500 to-pink-500 text-white focus-visible:ring-pink-600/20'>
2096
- Explore More
2097
- </Button>
2098
- </CardFooter>
2099
- </div>
2100
- </Card>
2101
- )
2102
- }
2103
-
2104
- const CardOverlayDemo = () => {
2105
- return (
2106
- <Card className='before:bg-primary/70 relative max-w-md py-0 before:absolute before:size-full before:rounded-xl'>
2107
- <CardContent className='px-0'>
2108
- <img
2109
- src='https://cdn.shadcnstudio.com/ss-assets/components/card/image-8.png?widht=448&height=280&format=auto'
2110
- alt='Banner'
2111
- className='h-70 w-112 rounded-xl'
2112
- />
2113
- </CardContent>
2114
- <div className='absolute'>
2115
- <CardHeader className='text-primary-foreground w-full pt-6'>
2116
- <CardTitle>Creative Catalyst</CardTitle>
2117
- </CardHeader>
2118
- <CardContent className='text-primary-foreground/80'>
2119
- Step into a world where imagination takes the lead and every pixel tells a story. This is a space designed to
2120
- unleash your creative potential without boundaries or time constraints. Explore bold ideas, experiment with
2121
- vibrant concepts, and craft visuals that inspire and captivate.
2122
- </CardContent>
2123
- </div>
2124
- </Card>
2125
- )
2126
- }
2127
-
2128
- const CardSoftDemo = () => {
2129
- return (
2130
- <Card className='bg-primary/20 max-w-md gap-0'>
2131
- <CardHeader>
2132
- <CardTitle>Design Throwdown</CardTitle>
2133
- </CardHeader>
2134
- <CardContent>
2135
- Where passion, pressure, and pixels collide—push your creativity to the edge and show what you are made of.
2136
- </CardContent>
2137
- </Card>
2138
- )
2139
- }
2140
-
2141
- const CardOutlineDemo = () => {
2142
- return (
2143
- <Card className='border-primary max-w-md gap-0 bg-transparent shadow-none'>
2144
- <CardHeader>
2145
- <CardTitle>Creative Clash</CardTitle>
2146
- </CardHeader>
2147
- <CardContent>
2148
- Step into a space where design skills are tested, ideas come alive, and only the boldest concepts win the
2149
- spotlight.
2150
- </CardContent>
2151
- </Card>
2152
- )
2153
- }
2154
-
2155
- const CardWithTabsDemo = () => {
2156
- return (
2157
- <Card className='w-max'>
2158
- <CardContent>
2159
- <Tabs defaultValue={tabs[0].value} className='w-full max-w-sm'>
2160
- <TabsList className='bg-background w-full justify-start rounded-none border-b p-0'>
2161
- {tabs.map(tab => (
2162
- <TabsTrigger
2163
- key={tab.value}
2164
- value={tab.value}
2165
- className='bg-background data-[state=active]:border-b-primary h-full rounded-none border-b-2 border-transparent data-[state=active]:shadow-none'
2166
- >
2167
- {tab.name}
2168
- </TabsTrigger>
2169
- ))}
2170
- </TabsList>
2171
- {tabs.map(tab => (
2172
- <TabsContent key={tab.value} value={tab.value}>
2173
- <p className='text-muted-foreground p-4 text-sm'>{tab.content}</p>
2174
- </TabsContent>
2175
- ))}
2176
- </Tabs>
2177
- </CardContent>
2178
- </Card>
2179
- )
2180
- }
2181
-
2182
- const CardTweetDemo = () => {
2183
- const [liked, setLiked] = useState<boolean>(true)
2184
-
2185
- return (
2186
- <Card className='max-w-md'>
2187
- <CardHeader className='flex items-center justify-between gap-3'>
2188
- <div className='flex items-center gap-3'>
2189
- <Avatar className='ring-ring ring-2'>
2190
- <AvatarImage src='https://cdn.shadcnstudio.com/ss-assets/avatar/avatar-5.png' alt='Hallie Richards' />
2191
- <AvatarFallback className='text-xs'>PG</AvatarFallback>
2192
- </Avatar>
2193
- <div className='flex flex-col gap-0.5'>
2194
- <CardTitle className='flex items-center gap-1 text-sm'>
2195
- Philip George <BadgeCheckIcon className='size-4 fill-sky-600 stroke-white dark:fill-sky-400' />
2196
- </CardTitle>
2197
- <CardDescription>@philip20</CardDescription>
2198
- </div>
2199
- </div>
2200
- <div className='flex items-center gap-2'>
2201
- <Button variant='outline' size='sm'>
2202
- <UserPlusIcon />
2203
- Follow
2204
- </Button>
2205
- <Button variant='ghost' size='icon' aria-label='Toggle menu'>
2206
- <EllipsisIcon />
2207
- </Button>
2208
- </div>
2209
- </CardHeader>
2210
- <CardContent className='space-y-6 text-sm'>
2211
- <img
2212
- src='https://cdn.shadcnstudio.com/ss-assets/components/card/image-6.png?width=350&format=auto'
2213
- alt='Banner'
2214
- className='aspect-video w-full rounded-md object-cover'
2215
- />
2216
- <p>
2217
- Lost in the colors of the night 🌌✨ Sometimes the blur reveals more than clarity.{' '}
2218
- <a href='#' className='text-sky-600 dark:text-sky-400'>
2219
- #AbstractVibes
2220
- </a>{' '}
2221
- <a href='#' className='text-sky-600 dark:text-sky-400'>
2222
- #Dreamscape
2223
- </a>{' '}
2224
- <a href='#' className='text-sky-600 dark:text-sky-400'>
2225
- #VisualPoetry
2226
- </a>
2227
- </p>
2228
- </CardContent>
2229
- <CardFooter className='flex items-center gap-1'>
2230
- <Button variant='ghost' size='sm' onClick={() => setLiked(!liked)}>
2231
- <HeartIcon className={cn(liked && 'fill-destructive stroke-destructive')} />
2232
- 2.1K
2233
- </Button>
2234
- <Button variant='ghost' size='sm'>
2235
- <MessageCircleIcon />
2236
- 1.4K
2237
- </Button>
2238
- <Button variant='ghost' size='sm'>
2239
- <RepeatIcon />
2240
- 669
2241
- </Button>
2242
- <Button variant='ghost' size='sm'>
2243
- <SendIcon />
2244
- 1.1K
2245
- </Button>
2246
- </CardFooter>
2247
- </Card>
2248
- )
2249
- }
2250
-
2251
- const CardProductDemo = () => {
2252
- const [liked, setLiked] = useState<boolean>(false)
2253
-
2254
- return (
2255
- <div className='relative max-w-md rounded-xl bg-gradient-to-r from-neutral-600 to-violet-300 pt-0 shadow-lg'>
2256
- <div className='flex h-60 items-center justify-center'>
2257
- <img
2258
- src='https://cdn.shadcnstudio.com/ss-assets/components/card/image-11.png?width=300&format=auto'
2259
- alt='Shoes'
2260
- className='w-75'
2261
- />
2262
- </div>
2263
- <Button
2264
- size='icon'
2265
- onClick={() => setLiked(!liked)}
2266
- className='bg-primary/10 hover:bg-primary/20 absolute top-4 right-4 rounded-full'
2267
- >
2268
- <HeartIcon className={cn(liked ? 'fill-destructive stroke-destructive' : 'stroke-white')} />
2269
- <span className='sr-only'>Like</span>
2270
- </Button>
2271
- <Card className='border-none'>
2272
- <CardHeader>
2273
- <CardTitle>Nike Jordan Air Rev</CardTitle>
2274
- <CardDescription className='flex items-center gap-2'>
2275
- <Badge variant='outline' className='rounded-sm'>
2276
- EU38
2277
- </Badge>
2278
- <Badge variant='outline' className='rounded-sm'>
2279
- Black and White
2280
- </Badge>
2281
- </CardDescription>
2282
- </CardHeader>
2283
- <CardContent>
2284
- <p>
2285
- Crossing hardwood comfort with off-court flair. &apos;80s-Inspired construction, bold details and
2286
- nothin&apos;-but-net style.
2287
- </p>
2288
- </CardContent>
2289
- <CardFooter className='justify-between gap-3 max-sm:flex-col max-sm:items-stretch'>
2290
- <div className='flex flex-col'>
2291
- <span className='text-sm font-medium uppercase'>Price</span>
2292
- <span className='text-xl font-semibold'>$69.99</span>
2293
- </div>
2294
- <Button size='lg'>Add to cart</Button>
2295
- </CardFooter>
2296
- </Card>
2297
- </div>
2298
- )
2299
- }
2300
-
2301
- const CardTestimonialDemo = () => {
2302
- return (
2303
- <Card className='max-w-md border-none'>
2304
- <CardContent>
2305
- <p>
2306
- Incredible time-saver! shadcn/studio has made UI development a breeze. The pre build components are not only{' '}
2307
- <span className='bg-primary/10'>visually appealing but also highly customizable</span>, fitting seamlessly
2308
- into my projects. With a wide array of options to choose from, I can easily match.
2309
- </p>
2310
- </CardContent>
2311
- <CardFooter className='justify-between gap-3 max-sm:flex-col max-sm:items-stretch'>
2312
- <div className='flex items-center gap-3'>
2313
- <Avatar className='ring-ring ring-2'>
2314
- <AvatarImage src='https://cdn.shadcnstudio.com/ss-assets/avatar/avatar-5.png' alt='Hallie Richards' />
2315
- <AvatarFallback className='text-xs'>SG</AvatarFallback>
2316
- </Avatar>
2317
- <div className='flex flex-col gap-0.5'>
2318
- <CardTitle className='flex items-center gap-1 text-sm'>Sam Green</CardTitle>
2319
- <CardDescription>@SamG11</CardDescription>
2320
- </div>
2321
- </div>
2322
- <div className='flex items-center gap-1'>
2323
- <StarIcon className='size-5 fill-amber-500 stroke-amber-500 dark:fill-amber-400 dark:stroke-amber-400'></StarIcon>
2324
- <StarIcon className='size-5 fill-amber-500 stroke-amber-500 dark:fill-amber-400 dark:stroke-amber-400'></StarIcon>
2325
- <StarIcon className='size-5 fill-amber-500 stroke-amber-500 dark:fill-amber-400 dark:stroke-amber-400'></StarIcon>
2326
- <StarIcon className='size-5 fill-amber-500 stroke-amber-500 dark:fill-amber-400 dark:stroke-amber-400'></StarIcon>
2327
- <StarIcon className='size-5 stroke-amber-500 dark:stroke-amber-400'></StarIcon>
2328
- </div>
2329
- </CardFooter>
2330
- </Card>
2331
- )
2332
- }
2333
-
2334
- const CardActionDemo = () => {
2335
- const [isActive, setIsActive] = useState(true)
2336
-
2337
- if (!isActive) return null
2338
-
2339
- return (
2340
- <Card className='relative max-w-lg shadow-none'>
2341
- <Button
2342
- variant='ghost'
2343
- size='icon'
2344
- onClick={() => setIsActive(false)}
2345
- className='absolute top-2 right-2 rounded-full'
2346
- >
2347
- <XIcon />
2348
- <span className='sr-only'>Close</span>
2349
- </Button>
2350
- <CardHeader>
2351
- <CardTitle className='text-center'>Have a project in mind</CardTitle>
2352
- </CardHeader>
2353
- <CardContent className='flex flex-col gap-4 text-center'>
2354
- <p>Let&apos;s discuss! Our Assistant team is excited to hear about your projects, ideas and questions. </p>
2355
- <Button>Contact Our Team</Button>
2356
- </CardContent>
2357
- </Card>
2358
- )
2359
- }
2360
-
2361
- const CardGroupDemo = () => {
2362
- return (
2363
- <div className='flex *:rounded-none *:shadow-none max-xl:flex-col max-xl:*:not-last:border-b-0 max-xl:*:first:rounded-t-xl max-xl:*:last:rounded-b-xl xl:*:not-last:border-r-0 xl:*:first:rounded-l-xl xl:*:last:rounded-r-xl'>
2364
- <Card className='overflow-hidden pt-0'>
2365
- <CardContent className='px-0'>
2366
- <img
2367
- src='https://cdn.shadcnstudio.com/ss-assets/components/card/image-7.png?width=368&format=auto'
2368
- alt='Banner'
2369
- className='aspect-video w-92 object-cover'
2370
- />
2371
- </CardContent>
2372
- <CardHeader>
2373
- <CardTitle>Mystical Blue Swirl</CardTitle>
2374
- <CardDescription>
2375
- Dive into the depths of an enchanting swirl where vibrant blues and soft pinks merge seamlessly, creating a
2376
- mesmerizing flow of colors.
2377
- </CardDescription>
2378
- </CardHeader>
2379
- <CardFooter className='gap-3 max-sm:flex-col max-sm:items-stretch'>
2380
- <Button>Explore More</Button>
2381
- <Button variant={'outline'}>Download Now</Button>
2382
- </CardFooter>
2383
- </Card>
2384
- <Card className='overflow-hidden pt-0'>
2385
- <CardContent className='px-0'>
2386
- <img
2387
- src='https://cdn.shadcnstudio.com/ss-assets/components/card/image-4.png?width=368&format=auto'
2388
- alt='Banner'
2389
- className='aspect-video w-92 object-cover'
2390
- />
2391
- </CardContent>
2392
- <CardHeader>
2393
- <CardTitle>Fiery Sunset Gradient</CardTitle>
2394
- <CardDescription>
2395
- Experience the warmth of a radiant sunset with flowing gradients of red, orange, and yellow blending
2396
- effortlessly in an abstract glow.
2397
- </CardDescription>
2398
- </CardHeader>
2399
- <CardFooter className='gap-3 max-sm:flex-col max-sm:items-stretch'>
2400
- <Button>Explore More</Button>
2401
- <Button variant={'outline'}>Download Now</Button>
2402
- </CardFooter>
2403
- </Card>
2404
- <Card className='overflow-hidden pt-0'>
2405
- <CardContent className='px-0'>
2406
- <img
2407
- src='https://cdn.shadcnstudio.com/ss-assets/components/card/image-5.png?width=368&format=auto'
2408
- alt='Banner'
2409
- className='aspect-video w-92 object-cover'
2410
- />
2411
- </CardContent>
2412
- <CardHeader>
2413
- <CardTitle>Cosmic Blue Waves</CardTitle>
2414
- <CardDescription>
2415
- Explore the mysteries of the cosmos with deep, swirling waves of blue and purple, evoking a sense of depth
2416
- and infinite space.
2417
- </CardDescription>
2418
- </CardHeader>
2419
- <CardFooter className='gap-3 max-sm:flex-col max-sm:items-stretch'>
2420
- <Button>Explore More</Button>
2421
- <Button variant={'outline'}>Download Now</Button>
2422
- </CardFooter>
2423
- </Card>
2424
- </div>
2425
- )
2426
- }
2427
-
2428
- const CardSpotlightDemo = () => {
2429
- useEffect(() => {
2430
- const all = document.querySelectorAll('.spotlight-card')
2431
-
2432
- const handleMouseMove = (ev: MouseEvent) => {
2433
- all.forEach(e => {
2434
- const blob = e.querySelector('.blob') as HTMLElement
2435
- const fblob = e.querySelector('.fake-blob') as HTMLElement
2436
-
2437
- if (!blob || !fblob) return
2438
-
2439
- const rec = fblob.getBoundingClientRect()
2440
-
2441
- blob.style.opacity = '1'
2442
-
2443
- blob.animate(
2444
- [
2445
- {
2446
- transform: `translate(${ev.clientX - rec.left - rec.width / 2
2447
- }px, ${ev.clientY - rec.top - rec.height / 2}px)`
2448
- }
2449
- ],
2450
- {
2451
- duration: 300,
2452
- fill: 'forwards'
2453
- }
2454
- )
2455
- })
2456
- }
2457
-
2458
- window.addEventListener('mousemove', handleMouseMove)
2459
-
2460
- return () => {
2461
- window.removeEventListener('mousemove', handleMouseMove)
2462
- }
2463
- }, [])
2464
-
2465
- return (
2466
- <div className='h-max w-max'>
2467
- <div className='spotlight-card group bg-border relative overflow-hidden rounded-xl p-px transition-all duration-300 ease-in-out'>
2468
- <Card className='group-hover:bg-card/90 max-w-80 border-none transition-all duration-300 ease-in-out group-hover:backdrop-blur-[20px]'>
2469
- <CardHeader>
2470
- <CardTitle>Hover for the Glow-Up</CardTitle>
2471
- </CardHeader>
2472
- <CardContent>
2473
- Glide your cursor here and watch magic unfold — an experience designed just for you.
2474
- </CardContent>
2475
- </Card>
2476
- <div className='blob absolute top-0 left-0 size-20 rounded-full bg-sky-600/60 opacity-0 blur-2xl transition-all duration-300 ease-in-out dark:bg-sky-400/60' />
2477
- <div className='fake-blob absolute top-0 left-0 size-20 rounded-full' />
2478
- </div>
2479
- </div>
2480
- )
2481
- }
2482
-
2483
- const Card3dDemo = () => {
2484
- const cardRef = useRef<HTMLDivElement>(null)
2485
- const imageRef = useRef<HTMLImageElement>(null)
2486
- const animationFrameRef = useRef<number | undefined>(undefined)
2487
- const lastMousePosition = useRef({ x: 0, y: 0 })
2488
-
2489
- useEffect(() => {
2490
- const card = cardRef.current
2491
- const image = imageRef.current
2492
-
2493
- if (!card || !image) return
2494
-
2495
- let rect: DOMRect
2496
- let centerX: number
2497
- let centerY: number
2498
-
2499
- const updateCardTransform = (mouseX: number, mouseY: number) => {
2500
- if (!rect) {
2501
- rect = card.getBoundingClientRect()
2502
- centerX = rect.left + rect.width / 2
2503
- centerY = rect.top + rect.height / 2
2504
- }
2505
-
2506
- const relativeX = mouseX - centerX
2507
- const relativeY = mouseY - centerY
2508
-
2509
- const cardTransform: CardTransform = {
2510
- rotateX: -relativeY * 0.035,
2511
- rotateY: relativeX * 0.035,
2512
- scale: 1.025
2513
- }
2514
-
2515
- const imageTransform: CardTransform = {
2516
- rotateX: -relativeY * 0.025,
2517
- rotateY: relativeX * 0.025,
2518
- scale: 1.05
2519
- }
2520
-
2521
- return { cardTransform, imageTransform }
2522
- }
2523
-
2524
- const animate = () => {
2525
- const { cardTransform, imageTransform } = updateCardTransform(
2526
- lastMousePosition.current.x,
2527
- lastMousePosition.current.y
2528
- )
2529
-
2530
- card.style.transform = `perspective(1000px) rotateX(${cardTransform.rotateX}deg) rotateY(${cardTransform.rotateY}deg) scale3d(${cardTransform.scale}, ${cardTransform.scale}, ${cardTransform.scale})`
2531
- card.style.boxShadow = '0 10px 35px rgba(0, 0, 0, 0.2)'
2532
-
2533
- image.style.transform = `perspective(1000px) rotateX(${imageTransform.rotateX}deg) rotateY(${imageTransform.rotateY}deg) scale3d(${imageTransform.scale}, ${imageTransform.scale}, ${imageTransform.scale})`
2534
-
2535
- animationFrameRef.current = requestAnimationFrame(animate)
2536
- }
2537
-
2538
- const handleMouseMove = (e: MouseEvent) => {
2539
- lastMousePosition.current = { x: e.clientX, y: e.clientY }
2540
- }
2541
-
2542
- const handleMouseEnter = () => {
2543
- card.style.transition = 'transform 0.2s ease, box-shadow 0.2s ease'
2544
- image.style.transition = 'transform 0.2s ease'
2545
- animate()
2546
- }
2547
-
2548
- const handleMouseLeave = () => {
2549
- if (animationFrameRef.current) {
2550
- cancelAnimationFrame(animationFrameRef.current)
2551
- }
2552
-
2553
- card.style.transform = 'perspective(1000px) rotateX(0) rotateY(0) scale3d(1, 1, 1)'
2554
- card.style.boxShadow = 'none'
2555
- card.style.transition = 'transform 0.5s ease, box-shadow 0.5s ease'
2556
-
2557
- image.style.transform = 'perspective(1000px) rotateX(0) rotateY(0) scale3d(1, 1, 1)'
2558
- image.style.transition = 'transform 0.5s ease'
2559
- }
2560
-
2561
- card.addEventListener('mouseenter', handleMouseEnter)
2562
- card.addEventListener('mousemove', handleMouseMove)
2563
- card.addEventListener('mouseleave', handleMouseLeave)
2564
-
2565
- return () => {
2566
- if (animationFrameRef.current) {
2567
- cancelAnimationFrame(animationFrameRef.current)
2568
- }
2569
-
2570
- card.removeEventListener('mouseenter', handleMouseEnter)
2571
- card.removeEventListener('mousemove', handleMouseMove)
2572
- card.removeEventListener('mouseleave', handleMouseLeave)
2573
- }
2574
- }, [])
2575
-
2576
- return (
2577
- <Card ref={cardRef} className='max-w-md'>
2578
- <CardHeader>
2579
- <CardTitle>Dynamic 3D Hover Card</CardTitle>
2580
- </CardHeader>
2581
- <CardContent className='space-y-6 text-sm'>
2582
- <img
2583
- ref={imageRef}
2584
- src='https://cdn.shadcnstudio.com/ss-assets/components/card/image-10.png?width=350&format=auto'
2585
- alt='Banner'
2586
- className='aspect-video w-full rounded-md object-cover'
2587
- width={500}
2588
- height={500}
2589
- />
2590
- <p>
2591
- Experience interactive depth and motion with this sleek 3D hover effect. Move your cursor to see it come
2592
- alive!
2593
- </p>
2594
- </CardContent>
2595
- </Card>
2596
- )
2597
- }