gladvn 0.2.36 → 0.2.37

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 (134) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/scripts/strip-comments.ts +79 -0
  4. package/src/blocks/auth-form.tsx +34 -30
  5. package/src/blocks/auth-recovery.tsx +9 -13
  6. package/src/blocks/auth-split.tsx +46 -36
  7. package/src/blocks/settings.tsx +84 -117
  8. package/src/components/macro/alert-preset.tsx +3 -1
  9. package/src/components/macro/carousel-preset.tsx +0 -1
  10. package/src/components/macro/checkbox-preset.test.tsx +2 -2
  11. package/src/components/macro/checkbox-preset.tsx +1 -2
  12. package/src/components/macro/command-preset.tsx +1 -1
  13. package/src/components/macro/date-picker.tsx +5 -18
  14. package/src/components/macro/dialog-preset.tsx +5 -3
  15. package/src/components/macro/input-preset.tsx +0 -1
  16. package/src/components/macro/select-preset.tsx +1 -1
  17. package/src/components/macro/switch-preset.test.tsx +1 -1
  18. package/src/components/micro/accordion.test.tsx +6 -12
  19. package/src/components/micro/alert-dialog.tsx +0 -2
  20. package/src/components/micro/alert.test.tsx +5 -8
  21. package/src/components/micro/alert.tsx +0 -2
  22. package/src/components/micro/badge.test.tsx +5 -7
  23. package/src/components/micro/badge.tsx +1 -3
  24. package/src/components/micro/button.test.tsx +19 -26
  25. package/src/components/micro/button.tsx +3 -11
  26. package/src/components/micro/calendar.tsx +12 -13
  27. package/src/components/micro/card.test.tsx +3 -5
  28. package/src/components/micro/carousel.tsx +0 -1
  29. package/src/components/micro/chart.tsx +3 -2
  30. package/src/components/micro/checkbox.test.tsx +9 -18
  31. package/src/components/micro/combobox.tsx +1 -3
  32. package/src/components/micro/command.tsx +23 -11
  33. package/src/components/micro/context-menu.tsx +0 -2
  34. package/src/components/micro/dialog.test.tsx +6 -14
  35. package/src/components/micro/dialog.tsx +0 -2
  36. package/src/components/micro/drawer.tsx +0 -3
  37. package/src/components/micro/dropdown-menu.test.tsx +8 -14
  38. package/src/components/micro/dropdown-menu.tsx +0 -2
  39. package/src/components/micro/field.tsx +3 -3
  40. package/src/components/micro/hover-card.tsx +0 -2
  41. package/src/components/micro/input-group.tsx +9 -42
  42. package/src/components/micro/input.test.tsx +15 -24
  43. package/src/components/micro/navigation-menu.tsx +0 -2
  44. package/src/components/micro/popover.test.tsx +5 -9
  45. package/src/components/micro/progress.tsx +5 -1
  46. package/src/components/micro/select.test.tsx +5 -18
  47. package/src/components/micro/select.tsx +3 -5
  48. package/src/components/micro/separator.tsx +1 -1
  49. package/src/components/micro/sheet.test.tsx +6 -14
  50. package/src/components/micro/sheet.tsx +0 -2
  51. package/src/components/micro/sidebar.tsx +5 -6
  52. package/src/components/micro/sonner.tsx +0 -1
  53. package/src/components/micro/switch.test.tsx +9 -18
  54. package/src/components/micro/switch.tsx +1 -1
  55. package/src/components/micro/tabs.test.tsx +5 -11
  56. package/src/components/micro/theme-provider.tsx +0 -12
  57. package/src/components/micro/toggle-group.tsx +1 -12
  58. package/src/components/micro/tooltip.test.tsx +7 -12
  59. package/src/dev/App.tsx +6 -6
  60. package/src/dev/components/BlockViewer.tsx +15 -4
  61. package/src/dev/components/Container.tsx +20 -0
  62. package/src/dev/components/GladvnLogo.tsx +3 -9
  63. package/src/dev/components/code-highlighter.tsx +5 -3
  64. package/src/dev/components/showcase.tsx +116 -168
  65. package/src/dev/sections/buttons.tsx +4 -9
  66. package/src/dev/sections/display.tsx +68 -72
  67. package/src/dev/sections/feedback.tsx +304 -314
  68. package/src/dev/sections/forms.tsx +10 -14
  69. package/src/dev/sections/interactive.tsx +32 -32
  70. package/src/dev/sections/overview.tsx +2 -10
  71. package/src/dev/showcase/accordion.tsx +512 -554
  72. package/src/dev/showcase/alert-dialog.tsx +525 -565
  73. package/src/dev/showcase/alert.tsx +352 -402
  74. package/src/dev/showcase/aspect-ratio.tsx +167 -193
  75. package/src/dev/showcase/avatar.tsx +231 -269
  76. package/src/dev/showcase/badge.tsx +92 -140
  77. package/src/dev/showcase/breadcrumb.tsx +113 -135
  78. package/src/dev/showcase/button.tsx +140 -173
  79. package/src/dev/showcase/calendar.tsx +187 -237
  80. package/src/dev/showcase/card.tsx +229 -261
  81. package/src/dev/showcase/carousel.tsx +288 -315
  82. package/src/dev/showcase/chart.tsx +44 -50
  83. package/src/dev/showcase/checkbox.tsx +286 -330
  84. package/src/dev/showcase/collapsible.tsx +143 -160
  85. package/src/dev/showcase/combobox.tsx +327 -369
  86. package/src/dev/showcase/command.tsx +106 -120
  87. package/src/dev/showcase/context-menu.tsx +93 -107
  88. package/src/dev/showcase/dialog.tsx +585 -630
  89. package/src/dev/showcase/drawer.tsx +176 -196
  90. package/src/dev/showcase/dropdown-menu.tsx +183 -201
  91. package/src/dev/showcase/empty.tsx +232 -274
  92. package/src/dev/showcase/hover-card.tsx +153 -180
  93. package/src/dev/showcase/input-group.tsx +221 -253
  94. package/src/dev/showcase/input-otp.tsx +204 -250
  95. package/src/dev/showcase/input.tsx +246 -325
  96. package/src/dev/showcase/item.tsx +134 -152
  97. package/src/dev/showcase/kbd.tsx +149 -172
  98. package/src/dev/showcase/label.tsx +50 -68
  99. package/src/dev/showcase/menubar.tsx +194 -213
  100. package/src/dev/showcase/navigation-menu.tsx +119 -133
  101. package/src/dev/showcase/overview-components/ArchitectureSection.tsx +126 -0
  102. package/src/dev/showcase/overview-components/CodeBlock.tsx +50 -0
  103. package/src/dev/showcase/overview-components/ColorPaletteSection.tsx +44 -0
  104. package/src/dev/showcase/overview-components/DashboardPreview.tsx +159 -0
  105. package/src/dev/showcase/overview-components/FeatureGridSection.tsx +535 -0
  106. package/src/dev/showcase/overview-components/FooterCTA.tsx +137 -0
  107. package/src/dev/showcase/overview-components/HeroSection.tsx +65 -0
  108. package/src/dev/showcase/overview-components/PrinciplesSection.tsx +128 -0
  109. package/src/dev/showcase/overview.tsx +21 -1163
  110. package/src/dev/showcase/pagination.tsx +144 -190
  111. package/src/dev/showcase/popover.tsx +181 -196
  112. package/src/dev/showcase/progress.tsx +141 -189
  113. package/src/dev/showcase/radio-group.tsx +272 -332
  114. package/src/dev/showcase/resizable.tsx +119 -141
  115. package/src/dev/showcase/scroll-area.tsx +21 -36
  116. package/src/dev/showcase/select.tsx +262 -322
  117. package/src/dev/showcase/separator.tsx +75 -73
  118. package/src/dev/showcase/sheet.tsx +333 -361
  119. package/src/dev/showcase/sidebar.tsx +53 -59
  120. package/src/dev/showcase/skeleton.tsx +93 -112
  121. package/src/dev/showcase/slider.tsx +244 -296
  122. package/src/dev/showcase/sonner.tsx +251 -258
  123. package/src/dev/showcase/spinner.tsx +46 -67
  124. package/src/dev/showcase/switch.tsx +298 -362
  125. package/src/dev/showcase/table.tsx +76 -80
  126. package/src/dev/showcase/tabs.tsx +302 -355
  127. package/src/dev/showcase/textarea.tsx +240 -293
  128. package/src/dev/showcase/toast.tsx +48 -54
  129. package/src/dev/showcase/toggle-group.tsx +104 -129
  130. package/src/dev/showcase/toggle.tsx +82 -102
  131. package/src/dev/showcase/tooltip.tsx +173 -192
  132. package/src/dev/showcase/why.tsx +6 -12
  133. package/src/hooks/use-mobile.test.ts +3 -2
  134. package/src/lib/utils.test.ts +5 -4
@@ -13,7 +13,7 @@ import {
13
13
  import {
14
14
  DocsP,
15
15
  ExampleGrid,
16
- ExampleSection,
16
+ ShowcaseExample,
17
17
  Showcase,
18
18
  ShowcaseDocs
19
19
  } from "../../dev/components/showcase";
@@ -22,27 +22,27 @@ import { cn } from "../../lib/utils";
22
22
  const SLIDES = [
23
23
  {
24
24
  id: 1,
25
- title: "Modern Aesthetics",
25
+ title: "Giao diện Hiện đại",
26
26
  desc: "Crafting beautiful interfaces with tailwind.",
27
27
  bg: "bg-gradient-to-tr from-violet-500 to-purple-500" },
28
28
  {
29
29
  id: 2,
30
- title: "Smooth Interactions",
30
+ title: "Tương tác Mượt mà",
31
31
  desc: "Fluid animations and micro-interactions.",
32
32
  bg: "bg-gradient-to-tr from-pink-500 to-rose-500" },
33
33
  {
34
34
  id: 3,
35
- title: "Highly Customizable",
35
+ title: "Dễ tuỳ chỉnh",
36
36
  desc: "Easily adapt to your brand.",
37
37
  bg: "bg-gradient-to-tr from-blue-500 to-cyan-500" },
38
38
  {
39
39
  id: 4,
40
- title: "Accessible by Default",
40
+ title: "Mặc định Accessible",
41
41
  desc: "Keyboard navigation out of the box.",
42
42
  bg: "bg-gradient-to-tr from-emerald-500 to-teal-500" },
43
43
  {
44
44
  id: 5,
45
- title: "Dark Mode Ready",
45
+ title: "Hỗ trợ Dark Mode",
46
46
  desc: "Looks stunning on dark and light mode.",
47
47
  bg: "bg-gradient-to-tr from-amber-500 to-orange-500" },
48
48
  ];
@@ -109,17 +109,11 @@ function ControlledCarouselDemo() {
109
109
  );
110
110
  }
111
111
 
112
- // ──────────────────────────────────────────────────────────
113
- // SECTION 1: Macro Content
114
- // ──────────────────────────────────────────────────────────
115
112
  function CarouselMacroShowcase() {
116
113
  return (
117
- <div className="space-y-10 mt-6">
114
+ <div className="space-y-10">
118
115
  <ExampleGrid>
119
- <ExampleSection
120
- label="Tiêu chuẩn (Standard)"
121
- description="Băng chuyền cơ bản nhất với cầu trượt."
122
- codeString={`<CarouselPreset
116
+ <ShowcaseExample title="Tiêu chuẩn (Standard)" description="Băng chuyền cơ bản nhất với cầu trượt." code={`<CarouselPreset
123
117
  items={[
124
118
  {
125
119
  id: "std-1",
@@ -155,47 +149,45 @@ function CarouselMacroShowcase() {
155
149
  </div>
156
150
  ) },
157
151
  ]}
158
- />`}
159
- >
160
- <div className="w-full max-w-sm px-12">
161
- <CarouselPreset
162
- items={[
163
- {
164
- id: "std-1",
165
- content: (
166
- <div className="p-1 border border-border rounded-xl">
167
- <div className="flex aspect-square items-center justify-center p-6 bg-muted/20 rounded-lg">
168
- <span className="text-4xl font-semibold">1</span>
169
- </div>
170
- </div>
171
- ) },
172
- {
173
- id: "std-2",
174
- content: (
175
- <div className="p-1 border border-border rounded-xl">
176
- <div className="flex aspect-square items-center justify-center p-6 bg-muted/20 rounded-lg">
177
- <span className="text-4xl font-semibold">2</span>
178
- </div>
179
- </div>
180
- ) },
181
- {
182
- id: "std-3",
183
- content: (
184
- <div className="p-1 border border-border rounded-xl">
185
- <div className="flex aspect-square items-center justify-center p-6 bg-muted/20 rounded-lg">
186
- <span className="text-4xl font-semibold">3</span>
187
- </div>
188
- </div>
189
- ) },
190
- ]}
191
- />
192
- </div>
193
- </ExampleSection>
152
+ />`} preview={
153
+ <>
154
+ <div className="w-full max-w-sm px-12">
155
+ <CarouselPreset
156
+ items={[
157
+ {
158
+ id: "std-1",
159
+ content: (
160
+ <div className="p-1 border border-border rounded-xl">
161
+ <div className="flex aspect-square items-center justify-center p-6 bg-muted/20 rounded-lg">
162
+ <span className="text-4xl font-semibold">1</span>
163
+ </div>
164
+ </div>
165
+ ) },
166
+ {
167
+ id: "std-2",
168
+ content: (
169
+ <div className="p-1 border border-border rounded-xl">
170
+ <div className="flex aspect-square items-center justify-center p-6 bg-muted/20 rounded-lg">
171
+ <span className="text-4xl font-semibold">2</span>
172
+ </div>
173
+ </div>
174
+ ) },
175
+ {
176
+ id: "std-3",
177
+ content: (
178
+ <div className="p-1 border border-border rounded-xl">
179
+ <div className="flex aspect-square items-center justify-center p-6 bg-muted/20 rounded-lg">
180
+ <span className="text-4xl font-semibold">3</span>
181
+ </div>
182
+ </div>
183
+ ) },
184
+ ]}
185
+ />
186
+ </div>
187
+ </>
188
+ } />
194
189
 
195
- <ExampleSection
196
- label="Thư viện ảnh (Image Gallery)"
197
- description="Sử dụng hình ảnh thực làm nội dung slide."
198
- codeString={`<CarouselPreset
190
+ <ShowcaseExample title="Thư viện ảnh (Image Gallery)" description="Sử dụng hình ảnh thực làm nội dung slide." code={`<CarouselPreset
199
191
  items={[
200
192
  {
201
193
  id: "img-1",
@@ -225,49 +217,47 @@ function CarouselMacroShowcase() {
225
217
  />
226
218
  ) },
227
219
  ]}
228
- />`}
229
- >
230
- <div className="w-full max-w-sm px-12">
231
- <CarouselPreset
232
- items={[
233
- {
234
- id: "img-1",
235
- content: (
236
- <img
237
- src="https://images.unsplash.com/photo-1707343843437-caacff5cfa74?q=80&w=600&h=400&auto=format&fit=crop"
238
- alt="Slide 1"
239
- className="rounded-xl object-cover"
240
- />
241
- ) },
242
- {
243
- id: "img-2",
244
- content: (
245
- <img
246
- src="https://images.unsplash.com/photo-1682687220742-aba13b6e50ba?q=80&w=600&h=400&auto=format&fit=crop"
247
- alt="Slide 2"
248
- className="rounded-xl object-cover"
249
- />
250
- ) },
251
- {
252
- id: "img-3",
253
- content: (
254
- <img
255
- src="https://images.unsplash.com/photo-1707343843437-caacff5cfa74?q=80&w=600&h=400&auto=format&fit=crop"
256
- alt="Slide 3"
257
- className="rounded-xl object-cover"
258
- />
259
- ) },
260
- ]}
261
- />
262
- </div>
263
- </ExampleSection>
220
+ />`} preview={
221
+ <>
222
+ <div className="w-full max-w-sm px-12">
223
+ <CarouselPreset
224
+ items={[
225
+ {
226
+ id: "img-1",
227
+ content: (
228
+ <img
229
+ src="https://images.unsplash.com/photo-1707343843437-caacff5cfa74?q=80&w=600&h=400&auto=format&fit=crop"
230
+ alt="Slide 1"
231
+ className="rounded-xl object-cover"
232
+ />
233
+ ) },
234
+ {
235
+ id: "img-2",
236
+ content: (
237
+ <img
238
+ src="https://images.unsplash.com/photo-1682687220742-aba13b6e50ba?q=80&w=600&h=400&auto=format&fit=crop"
239
+ alt="Slide 2"
240
+ className="rounded-xl object-cover"
241
+ />
242
+ ) },
243
+ {
244
+ id: "img-3",
245
+ content: (
246
+ <img
247
+ src="https://images.unsplash.com/photo-1707343843437-caacff5cfa74?q=80&w=600&h=400&auto=format&fit=crop"
248
+ alt="Slide 3"
249
+ className="rounded-xl object-cover"
250
+ />
251
+ ) },
252
+ ]}
253
+ />
254
+ </div>
255
+ </>
256
+ } />
264
257
  </ExampleGrid>
265
258
 
266
259
  <ExampleGrid>
267
- <ExampleSection
268
- label="Vòng lặp vô hạn (Loop Enabled)"
269
- description="Chỉ hiển thị dấu chấm (ẩn mũi tên)."
270
- codeString={`<CarouselPreset
260
+ <ShowcaseExample title="Vòng lặp vô hạn (Loop Enabled)" description="Chỉ hiển thị dấu chấm (ẩn mũi tên)." code={`<CarouselPreset
271
261
  opts={{ loop: true }}
272
262
  showArrows={false}
273
263
  items={[
@@ -305,49 +295,47 @@ function CarouselMacroShowcase() {
305
295
  </div>
306
296
  ) },
307
297
  ]}
308
- />`}
309
- >
310
- <div className="w-full max-w-sm">
311
- <CarouselPreset
312
- opts={{ loop: true }}
313
- showArrows={false}
314
- items={[
315
- {
316
- id: "loop-1",
317
- content: (
318
- <div className="p-1 border border-border rounded-xl">
319
- <div className="flex aspect-square items-center justify-center p-6 bg-gradient-to-tr from-violet-500 to-purple-500 rounded-lg text-white">
320
- <span className="text-4xl font-semibold">1</span>
321
- </div>
322
- </div>
323
- ) },
324
- {
325
- id: "loop-2",
326
- content: (
327
- <div className="p-1 border border-border rounded-xl">
328
- <div className="flex aspect-square items-center justify-center p-6 bg-gradient-to-tr from-pink-500 to-rose-500 rounded-lg text-white">
329
- <span className="text-4xl font-semibold">2</span>
330
- </div>
331
- </div>
332
- ) },
333
- {
334
- id: "loop-3",
335
- content: (
336
- <div className="p-1 border border-border rounded-xl">
337
- <div className="flex aspect-square items-center justify-center p-6 bg-gradient-to-tr from-blue-500 to-cyan-500 rounded-lg text-white">
338
- <span className="text-4xl font-semibold">3</span>
339
- </div>
340
- </div>
341
- ) },
342
- ]}
343
- />
344
- </div>
345
- </ExampleSection>
298
+ />`} preview={
299
+ <>
300
+ <div className="w-full max-w-sm">
301
+ <CarouselPreset
302
+ opts={{ loop: true }}
303
+ showArrows={false}
304
+ items={[
305
+ {
306
+ id: "loop-1",
307
+ content: (
308
+ <div className="p-1 border border-border rounded-xl">
309
+ <div className="flex aspect-square items-center justify-center p-6 bg-gradient-to-tr from-violet-500 to-purple-500 rounded-lg text-white">
310
+ <span className="text-4xl font-semibold">1</span>
311
+ </div>
312
+ </div>
313
+ ) },
314
+ {
315
+ id: "loop-2",
316
+ content: (
317
+ <div className="p-1 border border-border rounded-xl">
318
+ <div className="flex aspect-square items-center justify-center p-6 bg-gradient-to-tr from-pink-500 to-rose-500 rounded-lg text-white">
319
+ <span className="text-4xl font-semibold">2</span>
320
+ </div>
321
+ </div>
322
+ ) },
323
+ {
324
+ id: "loop-3",
325
+ content: (
326
+ <div className="p-1 border border-border rounded-xl">
327
+ <div className="flex aspect-square items-center justify-center p-6 bg-gradient-to-tr from-blue-500 to-cyan-500 rounded-lg text-white">
328
+ <span className="text-4xl font-semibold">3</span>
329
+ </div>
330
+ </div>
331
+ ) },
332
+ ]}
333
+ />
334
+ </div>
335
+ </>
336
+ } />
346
337
 
347
- <ExampleSection
348
- label="Chỉ mũi tên (Arrows Only)"
349
- description="Mũi tên điều hướng không có dấu chấm."
350
- codeString={`<CarouselPreset
338
+ <ShowcaseExample title="Chỉ mũi tên (Arrows Only)" description="Mũi tên điều hướng không có dấu chấm." code={`<CarouselPreset
351
339
  showDots={false}
352
340
  items={[
353
341
  {
@@ -384,50 +372,48 @@ function CarouselMacroShowcase() {
384
372
  </div>
385
373
  ) },
386
374
  ]}
387
- />`}
388
- >
389
- <div className="w-full max-w-sm px-12">
390
- <CarouselPreset
391
- showDots={false}
392
- items={[
393
- {
394
- id: "arr-1",
395
- content: (
396
- <div className="p-1 border border-border rounded-xl">
397
- <div className="flex aspect-square items-center justify-center p-6 bg-muted/20 rounded-lg">
398
- <span className="text-4xl font-semibold">A</span>
399
- </div>
400
- </div>
401
- ) },
402
- {
403
- id: "arr-2",
404
- content: (
405
- <div className="p-1 border border-border rounded-xl">
406
- <div className="flex aspect-square items-center justify-center p-6 bg-muted/20 rounded-lg">
407
- <span className="text-4xl font-semibold">B</span>
408
- </div>
409
- </div>
410
- ) },
411
- {
412
- id: "arr-3",
413
- content: (
414
- <div className="p-1 border border-border rounded-xl">
415
- <div className="flex aspect-square items-center justify-center p-6 bg-muted/20 rounded-lg">
416
- <span className="text-4xl font-semibold">C</span>
417
- </div>
418
- </div>
419
- ) },
420
- ]}
421
- />
422
- </div>
423
- </ExampleSection>
375
+ />`} preview={
376
+ <>
377
+ <div className="w-full max-w-sm px-12">
378
+ <CarouselPreset
379
+ showDots={false}
380
+ items={[
381
+ {
382
+ id: "arr-1",
383
+ content: (
384
+ <div className="p-1 border border-border rounded-xl">
385
+ <div className="flex aspect-square items-center justify-center p-6 bg-muted/20 rounded-lg">
386
+ <span className="text-4xl font-semibold">A</span>
387
+ </div>
388
+ </div>
389
+ ) },
390
+ {
391
+ id: "arr-2",
392
+ content: (
393
+ <div className="p-1 border border-border rounded-xl">
394
+ <div className="flex aspect-square items-center justify-center p-6 bg-muted/20 rounded-lg">
395
+ <span className="text-4xl font-semibold">B</span>
396
+ </div>
397
+ </div>
398
+ ) },
399
+ {
400
+ id: "arr-3",
401
+ content: (
402
+ <div className="p-1 border border-border rounded-xl">
403
+ <div className="flex aspect-square items-center justify-center p-6 bg-muted/20 rounded-lg">
404
+ <span className="text-4xl font-semibold">C</span>
405
+ </div>
406
+ </div>
407
+ ) },
408
+ ]}
409
+ />
410
+ </div>
411
+ </>
412
+ } />
424
413
  </ExampleGrid>
425
414
 
426
415
  <ExampleGrid>
427
- <ExampleSection
428
- label="Điều khiển từ bên ngoài (Controlled Mode)"
429
- description="Sử dụng biến state React để điều khiển slide."
430
- codeString={`const [index, setIndex] = useState(0);
416
+ <ShowcaseExample title="Điều khiển từ bên ngoài (Controlled Mode)" description="Sử dụng biến state React để điều khiển slide." code={`const [index, setIndex] = useState(0);
431
417
 
432
418
  return (
433
419
  <CarouselPreset
@@ -435,15 +421,13 @@ return (
435
421
  onIndexChange={setIndex}
436
422
  items={[...]}
437
423
  />
438
- );`}
439
- >
440
- <ControlledCarouselDemo />
441
- </ExampleSection>
424
+ );`} preview={
425
+ <>
426
+ <ControlledCarouselDemo />
427
+ </>
428
+ } />
442
429
 
443
- <ExampleSection
444
- label="Theo chiều dọc (Vertical Orientation)"
445
- description="Băng chuyền macro cuộn theo chiều dọc."
446
- codeString={`<CarouselPreset
430
+ <ShowcaseExample title="Theo chiều dọc (Vertical Orientation)" description="Băng chuyền macro cuộn theo chiều dọc." code={`<CarouselPreset
447
431
  className="w-full"
448
432
  orientation="vertical"
449
433
  contentClassName="h-[300px]"
@@ -471,55 +455,50 @@ return (
471
455
  </div>
472
456
  ) },
473
457
  ]}
474
- />`}
475
- >
476
- <div className="w-full max-w-sm px-12 py-12 flex justify-center">
477
- <CarouselPreset
478
- className="w-full"
479
- orientation="vertical"
480
- contentClassName="h-[300px]"
481
- itemClassName="basis-[250px]"
482
- items={[
483
- {
484
- id: "v1",
485
- content: (
486
- <div className="h-full w-full border border-border rounded-xl flex items-center justify-center bg-muted/20 text-4xl font-semibold">
487
- A
488
- </div>
489
- ) },
490
- {
491
- id: "v2",
492
- content: (
493
- <div className="h-full w-full border border-border rounded-xl flex items-center justify-center bg-muted/20 text-4xl font-semibold">
494
- B
495
- </div>
496
- ) },
497
- {
498
- id: "v3",
499
- content: (
500
- <div className="h-full w-full border border-border rounded-xl flex items-center justify-center bg-muted/20 text-4xl font-semibold">
501
- C
502
- </div>
503
- ) },
504
- ]}
505
- />
506
- </div>
507
- </ExampleSection>
458
+ />`} preview={
459
+ <>
460
+ <div className="w-full max-w-sm px-12 py-12 flex justify-center">
461
+ <CarouselPreset
462
+ className="w-full"
463
+ orientation="vertical"
464
+ contentClassName="h-[300px]"
465
+ itemClassName="basis-[250px]"
466
+ items={[
467
+ {
468
+ id: "v1",
469
+ content: (
470
+ <div className="h-full w-full border border-border rounded-xl flex items-center justify-center bg-muted/20 text-4xl font-semibold">
471
+ A
472
+ </div>
473
+ ) },
474
+ {
475
+ id: "v2",
476
+ content: (
477
+ <div className="h-full w-full border border-border rounded-xl flex items-center justify-center bg-muted/20 text-4xl font-semibold">
478
+ B
479
+ </div>
480
+ ) },
481
+ {
482
+ id: "v3",
483
+ content: (
484
+ <div className="h-full w-full border border-border rounded-xl flex items-center justify-center bg-muted/20 text-4xl font-semibold">
485
+ C
486
+ </div>
487
+ ) },
488
+ ]}
489
+ />
490
+ </div>
491
+ </>
492
+ } />
508
493
  </ExampleGrid>
509
494
  </div>
510
495
  );
511
496
  }
512
497
 
513
- // ──────────────────────────────────────────────────────────
514
- // SECTION 2: Micro Content
515
- // ──────────────────────────────────────────────────────────
516
498
  function CarouselMicroShowcase() {
517
499
  return (
518
- <div className="space-y-10 mt-6">
519
- <ExampleSection
520
- label="Hero Banner (Overlay Navigation)"
521
- description="Mũi tên kính mờ nằm đè trên Banner, chỉ hiện khi hover. Dấu chấm nằm sát mép dưới."
522
- codeString={`<Carousel
500
+ <div className="space-y-10">
501
+ <ShowcaseExample title="Hero Banner (Overlay Navigation)" description="Mũi tên kính mờ nằm đè trên Banner, chỉ hiện khi hover. Dấu chấm nằm sát mép dưới." code={`<Carousel
523
502
  opts={{ loop: true }}
524
503
  className="group relative w-full overflow-hidden rounded-2xl shadow-xl"
525
504
  >
@@ -533,49 +512,47 @@ function CarouselMicroShowcase() {
533
512
  <div className="absolute bottom-4 left-0 right-0 z-10">
534
513
  <CarouselDots className="[&>[data-slot=carousel-dot][data-active]]:bg-white [&>[data-slot=carousel-dot]]:bg-white/40" />
535
514
  </div>
536
- </Carousel>`}
537
- >
538
- <div className="mx-auto w-full max-w-4xl">
539
- <Carousel
540
- opts={{ loop: true }}
541
- className="group relative w-full overflow-hidden rounded-2xl shadow-xl border border-border/50"
542
- >
543
- <CarouselContent className="-ml-4">
544
- {SLIDES.map((slide) => (
545
- <CarouselItem key={slide.id} className="pl-4">
546
- <div
547
- className={cn(
548
- "flex aspect-[21/9] flex-col items-center justify-center p-6 text-center text-white",
549
- slide.bg,
550
- )}
551
- >
552
- <h3 className="mb-2 text-3xl font-bold tracking-tight sm:text-5xl">
553
- {slide.title}
554
- </h3>
555
- <p className="max-w-md text-sm text-white/80 sm:text-lg">
556
- {slide.desc}
557
- </p>
558
- </div>
559
- </CarouselItem>
560
- ))}
561
- </CarouselContent>
515
+ </Carousel>`} preview={
516
+ <>
517
+ <div className="mx-auto w-full max-w-4xl">
518
+ <Carousel
519
+ opts={{ loop: true }}
520
+ className="group relative w-full overflow-hidden rounded-2xl shadow-xl border border-border/50"
521
+ >
522
+ <CarouselContent className="-ml-4">
523
+ {SLIDES.map((slide) => (
524
+ <CarouselItem key={slide.id} className="pl-4">
525
+ <div
526
+ className={cn(
527
+ "flex aspect-[21/9] flex-col items-center justify-center p-6 text-center text-white",
528
+ slide.bg,
529
+ )}
530
+ >
531
+ <h3 className="mb-2 text-3xl font-bold tracking-tight sm:text-5xl">
532
+ {slide.title}
533
+ </h3>
534
+ <p className="max-w-md text-sm text-white/80 sm:text-lg">
535
+ {slide.desc}
536
+ </p>
537
+ </div>
538
+ </CarouselItem>
539
+ ))}
540
+ </CarouselContent>
562
541
 
563
- <div className="pointer-events-none absolute inset-0 z-10 flex items-center justify-between p-4 transition-opacity duration-300 sm:p-6 opacity-0 group-hover:opacity-100">
564
- <CarouselPrevious className="pointer-events-auto backdrop-blur-md bg-background/30 hover:bg-background/50 border-white/20 text-white" />
565
- <CarouselNext className="pointer-events-auto backdrop-blur-md bg-background/30 hover:bg-background/50 border-white/20 text-white" />
566
- </div>
542
+ <div className="pointer-events-none absolute inset-0 z-10 flex items-center justify-between p-4 transition-opacity duration-300 sm:p-6 opacity-0 group-hover:opacity-100">
543
+ <CarouselPrevious className="pointer-events-auto backdrop-blur-md bg-background/30 hover:bg-background/50 border-white/20 text-white" />
544
+ <CarouselNext className="pointer-events-auto backdrop-blur-md bg-background/30 hover:bg-background/50 border-white/20 text-white" />
545
+ </div>
567
546
 
568
- <div className="absolute bottom-4 left-0 right-0 z-10">
569
- <CarouselDots className="[&>[data-slot=carousel-dot][data-active]]:bg-white [&>[data-slot=carousel-dot]]:bg-white/40 hover:[&>[data-slot=carousel-dot]]:bg-white/60" />
570
- </div>
571
- </Carousel>
572
- </div>
573
- </ExampleSection>
547
+ <div className="absolute bottom-4 left-0 right-0 z-10">
548
+ <CarouselDots className="[&>[data-slot=carousel-dot][data-active]]:bg-white [&>[data-slot=carousel-dot]]:bg-white/40 hover:[&>[data-slot=carousel-dot]]:bg-white/60" />
549
+ </div>
550
+ </Carousel>
551
+ </div>
552
+ </>
553
+ } />
574
554
 
575
- <ExampleSection
576
- label="Nhiều phần tử trên 1 slide (Product Gallery)"
577
- description="Hiển thị nhiều Card (vd: basis-1/2, lg:basis-1/3) trên cùng một Slide của Băng chuyền."
578
- codeString={`<div className="mx-auto w-full max-w-5xl px-12">
555
+ <ShowcaseExample title="Nhiều phần tử trên 1 slide (Product Gallery)" description="Hiển thị nhiều Card (vd: basis-1/2, lg:basis-1/3) trên cùng một Slide của Băng chuyền." code={`<div className="mx-auto w-full max-w-5xl px-12">
579
556
  <Carousel
580
557
  opts={{ align: "start" }}
581
558
  className="w-full relative"
@@ -615,60 +592,58 @@ function CarouselMicroShowcase() {
615
592
  <CarouselPrevious className="absolute -left-12 top-1/2 -translate-y-1/2 border-border shadow-sm hover:bg-accent" />
616
593
  <CarouselNext className="absolute -right-12 top-1/2 -translate-y-1/2 border-border shadow-sm hover:bg-accent" />
617
594
  </Carousel>
618
- </div>`}
619
- >
620
- <div className="mx-auto w-full max-w-5xl px-12">
621
- <Carousel opts={{ align: "start" }} className="w-full relative">
622
- <CarouselContent className="-ml-4">
623
- {Array.from({ length: 10 }).map((_, index) => (
624
- <CarouselItem
625
- key={index}
626
- className="pl-4 md:basis-1/2 lg:basis-1/3"
627
- >
628
- <div className="p-1">
629
- <Card className="overflow-hidden transition-all duration-300 hover:shadow-lg hover:-translate-y-1">
630
- <div className="aspect-4/3 bg-muted flex items-center justify-center relative group">
631
- <span className="text-4xl font-black text-muted-foreground/30 transition-transform duration-500 group-hover:scale-110">
632
- 0{index + 1}
633
- </span>
634
- <div className="absolute inset-0 bg-linear-to-t from-black/60 to-transparent opacity-0 transition-opacity duration-300 group-hover:opacity-100 flex items-end p-4">
635
- <span className="text-white font-medium">
636
- View Item {index + 1}
637
- </span>
638
- </div>
639
- </div>
640
- <CardContent className="p-4">
641
- <div className="text-sm font-medium text-muted-foreground mb-1">
642
- Category
643
- </div>
644
- <h4 className="font-semibold text-lg leading-none">
645
- Featured Item {index + 1}
646
- </h4>
647
- </CardContent>
648
- </Card>
649
- </div>
650
- </CarouselItem>
651
- ))}
652
- </CarouselContent>
595
+ </div>`} preview={
596
+ <>
597
+ <div className="mx-auto w-full max-w-5xl px-12">
598
+ <Carousel opts={{ align: "start" }} className="w-full relative">
599
+ <CarouselContent className="-ml-4">
600
+ {Array.from({ length: 10 }).map((_, index) => (
601
+ <CarouselItem
602
+ key={index}
603
+ className="pl-4 md:basis-1/2 lg:basis-1/3"
604
+ >
605
+ <div className="p-1">
606
+ <Card className="overflow-hidden transition-all duration-300 hover:shadow-lg hover:-translate-y-1">
607
+ <div className="aspect-4/3 bg-muted flex items-center justify-center relative group">
608
+ <span className="text-4xl font-black text-muted-foreground/30 transition-transform duration-500 group-hover:scale-110">
609
+ 0{index + 1}
610
+ </span>
611
+ <div className="absolute inset-0 bg-linear-to-t from-black/60 to-transparent opacity-0 transition-opacity duration-300 group-hover:opacity-100 flex items-end p-4">
612
+ <span className="text-white font-medium">
613
+ View Item {index + 1}
614
+ </span>
615
+ </div>
616
+ </div>
617
+ <CardContent className="p-4">
618
+ <div className="text-sm font-medium text-muted-foreground mb-1">
619
+ Category
620
+ </div>
621
+ <h4 className="font-semibold text-lg leading-none">
622
+ Featured Item {index + 1}
623
+ </h4>
624
+ </CardContent>
625
+ </Card>
626
+ </div>
627
+ </CarouselItem>
628
+ ))}
629
+ </CarouselContent>
653
630
 
654
- <CarouselPrevious className="absolute -left-12 top-1/2 -translate-y-1/2 border-border shadow-sm hover:bg-accent" />
655
- <CarouselNext className="absolute -right-12 top-1/2 -translate-y-1/2 border-border shadow-sm hover:bg-accent" />
656
- </Carousel>
657
- </div>
658
- </ExampleSection>
631
+ <CarouselPrevious className="absolute -left-12 top-1/2 -translate-y-1/2 border-border shadow-sm hover:bg-accent" />
632
+ <CarouselNext className="absolute -right-12 top-1/2 -translate-y-1/2 border-border shadow-sm hover:bg-accent" />
633
+ </Carousel>
634
+ </div>
635
+ </>
636
+ } />
659
637
  </div>
660
638
  );
661
639
  }
662
640
 
663
- // ──────────────────────────────────────────────────────────
664
- // SECTION 3: Entry point
665
- // ──────────────────────────────────────────────────────────
666
641
  export default function CarouselShowcase() {
667
642
  return (
668
643
  <Showcase
669
644
  title="Carousel"
670
645
  description="Băng chuyền vuốt chuyển động cao cấp được xây dựng bằng Embla."
671
- generalConcept={
646
+ guideline={
672
647
  <ShowcaseDocs>
673
648
  <DocsP>
674
649
  Dùng để duyệt qua một tập hợp các nội dung (như hình ảnh, thẻ bài,
@@ -677,10 +652,8 @@ export default function CarouselShowcase() {
677
652
  </DocsP>
678
653
  </ShowcaseDocs>
679
654
  }
680
- tabs={[
681
- { label: "Micro (Primitive)", content: <CarouselMicroShowcase /> },
682
- { label: "Macro (Preset)", content: <CarouselMacroShowcase /> },
683
- ]}
655
+ micro={{ content: <CarouselMicroShowcase /> }}
656
+ macro={{ content: <CarouselMacroShowcase /> }}
684
657
  />
685
658
  );
686
659
  }