gladvn 0.2.35 → 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 +2 -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
@@ -24,24 +24,18 @@ import {
24
24
  DocsP,
25
25
  DocsUl,
26
26
  ExampleGrid,
27
- ExampleSection,
27
+ ShowcaseExample,
28
28
  Showcase,
29
29
  ShowcaseDocs
30
30
  } from "../../dev/components/showcase";
31
31
  import { type Size } from "../../lib/types";
32
32
 
33
- // ──────────────────────────────────────────────────────────
34
- // SECTION 1: Macro Content (không export)
35
- // ──────────────────────────────────────────────────────────
36
33
  function AlertMacroShowcase({ globalSize }: { globalSize: Size }) {
37
34
  const [controlledOpen, setControlledOpen] = useState(true);
38
35
 
39
36
  return (
40
- <div className="space-y-10 mt-6">
41
- <ExampleSection
42
- label="Controlled vs Uncontrolled"
43
- fullWidth
44
- codeString={`<div className="space-y-4 px-2 py-4">
37
+ <div className="space-y-10">
38
+ <ShowcaseExample title="Controlled vs Uncontrolled" code={`<div className="space-y-4 px-2 py-4">
45
39
  <DocsUl>
46
40
  <DocsLi>
47
41
  <b>Uncontrolled (Mặc định):</b> Nếu truyền{" "}
@@ -56,75 +50,66 @@ function AlertMacroShowcase({ globalSize }: { globalSize: Size }) {
56
50
  soát thì hãy render nó có điều kiện bên ngoài.
57
51
  </DocsLi>
58
52
  </DocsUl>
59
- </div>`}
60
- >
61
- <div className="space-y-4 px-2 py-4">
62
- <DocsUl>
63
- <DocsLi>
64
- <b>Uncontrolled (Mặc định):</b> Nếu truyền{" "}
65
- <DocsCode>dismissible=true</DocsCode>, component tự quản lý state
66
- để tắt (ẩn) Alert khi click vào nút X.
67
- </DocsLi>
68
- <DocsLi>
69
- <b>Controlled:</b> Có thể kiểm soát state đóng/mở thông qua React
70
- state và truyền hàm vào <DocsCode>onDismiss</DocsCode>. Tuy nhiên
71
- thông thường Alert chỉ bị huỷ (unmount), nên nếu bạn kiểm soát thì
72
- hãy render nó có điều kiện bên ngoài.
73
- </DocsLi>
74
- </DocsUl>
75
- </div>
76
- </ExampleSection>
53
+ </div>`} preview={
54
+ <>
55
+ <div className="space-y-4 px-2 py-4">
56
+ <DocsUl>
57
+ <DocsLi>
58
+ <b>Uncontrolled (Mặc định):</b> Nếu truyền{" "}
59
+ <DocsCode>dismissible=true</DocsCode>, component tự quản lý state
60
+ để tắt (ẩn) Alert khi click vào nút X.
61
+ </DocsLi>
62
+ <DocsLi>
63
+ <b>Controlled:</b> Có thể kiểm soát state đóng/mở thông qua React
64
+ state và truyền hàm vào <DocsCode>onDismiss</DocsCode>. Tuy nhiên
65
+ thông thường Alert chỉ bị huỷ (unmount), nên nếu bạn kiểm soát thì
66
+ hãy render nó có điều kiện bên ngoài.
67
+ </DocsLi>
68
+ </DocsUl>
69
+ </div>
70
+ </>
71
+ } />
77
72
 
78
73
  <ExampleGrid>
79
- <ExampleSection
80
- label="Tiêu chuẩn (Standard)"
81
- description="Truyền props trực tiếp thay vì lồng children."
82
- fullWidth
83
- codeString={`<AlertPreset
74
+ <ShowcaseExample title="Tiêu chuẩn (Standard)" description="Truyền props trực tiếp thay vì lồng children." code={`<AlertPreset
84
75
  color="info"
85
76
  title="Có bản cập nhật mới"
86
77
  description="Phiên bản 2.0.4 đã sẵn sàng để tải xuống."
87
78
  icon={<InfoIcon />}
88
- />`}
89
- >
90
- <AlertPreset
91
- color="info"
92
- size={globalSize}
93
- title="Có bản cập nhật mới"
94
- description="Phiên bản 2.0.4 đã sẵn sàng để tải xuống."
95
- icon={<InfoIcon />}
96
- />
97
- </ExampleSection>
98
-
99
- <ExampleSection
100
- label="Tự Đóng (Dismissible)"
101
- description="Thêm dismissible=true để hiển thị nút [X]. Thử bấm vào nút X bên dưới."
102
- fullWidth
103
- codeString={`<AlertPreset
79
+ />`} preview={
80
+ <>
81
+ <AlertPreset
82
+ color="info"
83
+ size={globalSize}
84
+ title="Có bản cập nhật mới"
85
+ description="Phiên bản 2.0.4 đã sẵn sàng để tải xuống."
86
+ icon={<InfoIcon />}
87
+ />
88
+ </>
89
+ } />
90
+
91
+ <ShowcaseExample title="Tự Đóng (Dismissible)" description="Thêm dismissible=true để hiển thị nút [X]. Thử bấm vào nút X bên dưới." code={`<AlertPreset
104
92
  color="warning"
105
93
  title="Phiên bản sắp hết hạn"
106
94
  description="Phiên đăng nhập của bạn sẽ hết hạn trong 5 phút."
107
95
  icon={<TriangleAlertIcon />}
108
96
  dismissible
109
- />`}
110
- >
111
- <AlertPreset
112
- color="warning"
113
- size={globalSize}
114
- title="Phiên bản sắp hết hạn"
115
- description="Phiên đăng nhập của bạn sẽ hết hạn trong 5 phút."
116
- icon={<TriangleAlertIcon />}
117
- dismissible
118
- />
119
- </ExampleSection>
97
+ />`} preview={
98
+ <>
99
+ <AlertPreset
100
+ color="warning"
101
+ size={globalSize}
102
+ title="Phiên bản sắp hết hạn"
103
+ description="Phiên đăng nhập của bạn sẽ hết hạn trong 5 phút."
104
+ icon={<TriangleAlertIcon />}
105
+ dismissible
106
+ />
107
+ </>
108
+ } />
120
109
  </ExampleGrid>
121
110
 
122
111
  <ExampleGrid>
123
- <ExampleSection
124
- label="Controlled"
125
- description="Quản lý trạng thái đóng mở thông qua state bên ngoài bằng React (Conditional Rendering)."
126
- fullWidth
127
- codeString={`const [controlledOpen, setControlledOpen] = useState(true);
112
+ <ShowcaseExample title="Controlled" description="Quản lý trạng thái đóng mở thông qua state bên ngoài bằng React (Conditional Rendering)." code={`const [controlledOpen, setControlledOpen] = useState(true);
128
113
  return (
129
114
  <>
130
115
  <div className="mb-4">
@@ -144,44 +129,42 @@ return (
144
129
  />
145
130
  )}
146
131
  </>
147
- );`}
148
- >
149
- <div className="flex w-full flex-col gap-3">
150
- <div className="flex items-center justify-between">
151
- <p className="text-xs text-muted-foreground">
152
- State:{" "}
153
- <code className="rounded bg-muted px-1.5 py-0.5 text-xs font-mono">
154
- {controlledOpen ? "true" : "false"}
155
- </code>
156
- </p>
157
- <Button
158
- size="sm"
159
- variant="outline"
160
- className="h-7 text-xs"
161
- onClick={() => setControlledOpen(true)}
162
- disabled={controlledOpen}
163
- >
164
- Mở lại Alert
165
- </Button>
166
- </div>
167
- {controlledOpen && (
168
- <AlertPreset
169
- color="destructive"
170
- size={globalSize}
171
- title="Bảo trì hệ thống"
172
- description="Hệ thống sẽ tạm ngừng hoạt động để bảo trì vào lúc nửa đêm."
173
- icon={<TriangleAlertIcon />}
174
- dismissible
175
- onDismiss={() => setControlledOpen(false)}
176
- />
177
- )}
178
- </div>
179
- </ExampleSection>
180
-
181
- <ExampleSection
182
- label="Nội Dung Phức Tạp (Complex Content)"
183
- description="Có thể truyền ReactNode hoặc thay thế toàn bộ bằng thẻ children."
184
- codeString={`<div className="flex w-full flex-col gap-4 max-w-xl">
132
+ );`} preview={
133
+ <>
134
+ <div className="flex w-full flex-col gap-3">
135
+ <div className="flex items-center justify-between">
136
+ <p className="text-xs text-muted-foreground">
137
+ State:{" "}
138
+ <code className="rounded bg-muted px-1.5 py-0.5 text-xs font-mono">
139
+ {controlledOpen ? "true" : "false"}
140
+ </code>
141
+ </p>
142
+ <Button
143
+ size="sm"
144
+ variant="outline"
145
+ className="h-7 text-xs"
146
+ onClick={() => setControlledOpen(true)}
147
+ disabled={controlledOpen}
148
+ >
149
+ Mở lại Alert
150
+ </Button>
151
+ </div>
152
+ {controlledOpen && (
153
+ <AlertPreset
154
+ color="destructive"
155
+ size={globalSize}
156
+ title="Bảo trì hệ thống"
157
+ description="Hệ thống sẽ tạm ngừng hoạt động để bảo trì vào lúc nửa đêm."
158
+ icon={<TriangleAlertIcon />}
159
+ dismissible
160
+ onDismiss={() => setControlledOpen(false)}
161
+ />
162
+ )}
163
+ </div>
164
+ </>
165
+ } />
166
+
167
+ <ShowcaseExample title="Nội Dung Phức Tạp (Complex Content)" description="Có thể truyền ReactNode hoặc thay thế toàn bộ bằng thẻ children." code={`<div className="flex w-full flex-col gap-4 max-w-xl">
185
168
  <AlertPreset
186
169
  color="success"
187
170
  title="Thanh toán thành công"
@@ -201,31 +184,32 @@ return (
201
184
  Hoá đơn #1234 của bạn đã được thanh toán hoàn tất.
202
185
  </p>
203
186
  </AlertPreset>
204
- </div>`}
205
- >
206
- <div className="flex w-full flex-col gap-4 max-w-xl">
207
- <AlertPreset
208
- color="success"
209
- size={globalSize}
210
- title="Thanh toán thành công"
211
- icon={<CheckCircle2Icon />}
212
- dismissible
213
- action={
214
- <Button
215
- size="sm"
216
- variant="outline"
217
- className="h-7 px-2 text-xs"
218
- >
219
- Xem biên lai
220
- </Button>
221
- }
222
- >
223
- <p className="text-sm mt-1 text-success/90">
224
- Hoá đơn #1234 của bạn đã được thanh toán hoàn tất.
225
- </p>
226
- </AlertPreset>
227
- </div>
228
- </ExampleSection>
187
+ </div>`} preview={
188
+ <>
189
+ <div className="flex w-full flex-col gap-4 max-w-xl">
190
+ <AlertPreset
191
+ color="success"
192
+ size={globalSize}
193
+ title="Thanh toán thành công"
194
+ icon={<CheckCircle2Icon />}
195
+ dismissible
196
+ action={
197
+ <Button
198
+ size="sm"
199
+ variant="outline"
200
+ className="h-7 px-2 text-xs"
201
+ >
202
+ Xem biên lai
203
+ </Button>
204
+ }
205
+ >
206
+ <p className="text-sm mt-1 text-success/90">
207
+ Hoá đơn #1234 của bạn đã được thanh toán hoàn tất.
208
+ </p>
209
+ </AlertPreset>
210
+ </div>
211
+ </>
212
+ } />
229
213
  </ExampleGrid>
230
214
  </div>
231
215
  );
@@ -236,13 +220,9 @@ return (
236
220
  // ──────────────────────────────────────────────────────────
237
221
  function AlertMicroShowcase({ globalSize }: { globalSize: Size }) {
238
222
  return (
239
- <div className="space-y-10 mt-6">
223
+ <div className="space-y-10">
240
224
  {/* ── Semantic Colors ──────────────────────── */}
241
- <ExampleSection
242
- label="Màu Sắc Ngữ Nghĩa (Semantic Colors)"
243
- description="Mỗi màu sắc truyền đạt một mức độ khẩn cấp hoặc ý nghĩa khác nhau."
244
- fullWidth
245
- codeString={`<Alert color="info" className="flex items-start">
225
+ <ShowcaseExample title="Màu Sắc Ngữ Nghĩa (Semantic Colors)" description="Mỗi màu sắc truyền đạt một mức độ khẩn cấp hoặc ý nghĩa khác nhau." code={`<Alert color="info" className="flex items-start">
246
226
  <AlertIcon
247
227
  render={<InfoIcon />}
248
228
  className="mt-0.5 shrink-0"
@@ -295,69 +275,60 @@ function AlertMicroShowcase({ globalSize }: { globalSize: Size }) {
295
275
  tra lại đường truyền mạng.
296
276
  </AlertDescription>
297
277
  </div>
298
- </Alert>`}
299
- >
300
- <Alert color="info" size={globalSize} className="flex items-start">
301
- <AlertIcon render={<InfoIcon />} className="mt-0.5 shrink-0" />
302
- <div className="flex-1 space-y-0.5">
303
- <AlertTitle>Có bản cập nhật mới</AlertTitle>
304
- <AlertDescription>
305
- Phiên bản 2.0.4 đã sẵn sàng để tải xuống. Hãy cập nhật để trải
306
- nghiệm tính năng mới.
307
- </AlertDescription>
308
- </div>
309
- </Alert>
310
-
311
- <Alert color="success" size={globalSize} className="flex items-start">
312
- <AlertIcon
313
- render={<CheckCircle2Icon />}
314
- className="mt-0.5 shrink-0"
315
- />
316
- <div className="flex-1 space-y-0.5">
317
- <AlertTitle>Đã lưu thành công</AlertTitle>
318
- <AlertDescription>
319
- Các thay đổi của bạn đã được đồng bộ lên đám mây.
320
- </AlertDescription>
321
- </div>
322
- </Alert>
323
-
324
- <Alert color="warning" size={globalSize} className="flex items-start">
325
- <AlertIcon
326
- render={<TriangleAlertIcon />}
327
- className="mt-0.5 shrink-0"
328
- />
329
- <div className="flex-1 space-y-0.5">
330
- <AlertTitle>Phiên bản sắp hết hạn</AlertTitle>
331
- <AlertDescription>
332
- Phiên đăng nhập của bạn sẽ hết hạn trong 5 phút nữa. Vui lòng lưu
333
- lại công việc.
334
- </AlertDescription>
335
- </div>
336
- </Alert>
337
-
338
- <Alert
339
- color="destructive"
340
- size={globalSize}
341
- className="flex items-start"
342
- >
343
- <AlertIcon render={<XCircleIcon />} className="mt-0.5 shrink-0" />
344
- <div className="flex-1 space-y-0.5">
345
- <AlertTitle>Kết nối thất bại</AlertTitle>
346
- <AlertDescription>
347
- Không thể kết nối đến cơ sở dữ liệu. Vui lòng kiểm tra lại đường
348
- truyền mạng.
349
- </AlertDescription>
350
- </div>
351
- </Alert>
352
- </ExampleSection>
278
+ </Alert>`} preview={
279
+ <>
280
+ <Alert color="info" size={globalSize} className="flex items-start">
281
+ <AlertIcon render={<InfoIcon />} className="mt-0.5 shrink-0" />
282
+ <div className="flex-1 space-y-0.5">
283
+ <AlertTitle>Có bản cập nhật mới</AlertTitle>
284
+ <AlertDescription>
285
+ Phiên bản 2.0.4 đã sẵn sàng để tải xuống. Hãy cập nhật để trải
286
+ nghiệm tính năng mới.
287
+ </AlertDescription>
288
+ </div>
289
+ </Alert><Alert color="success" size={globalSize} className="flex items-start">
290
+ <AlertIcon
291
+ render={<CheckCircle2Icon />}
292
+ className="mt-0.5 shrink-0"
293
+ />
294
+ <div className="flex-1 space-y-0.5">
295
+ <AlertTitle>Đã lưu thành công</AlertTitle>
296
+ <AlertDescription>
297
+ Các thay đổi của bạn đã được đồng bộ lên đám mây.
298
+ </AlertDescription>
299
+ </div>
300
+ </Alert><Alert color="warning" size={globalSize} className="flex items-start">
301
+ <AlertIcon
302
+ render={<TriangleAlertIcon />}
303
+ className="mt-0.5 shrink-0"
304
+ />
305
+ <div className="flex-1 space-y-0.5">
306
+ <AlertTitle>Phiên bản sắp hết hạn</AlertTitle>
307
+ <AlertDescription>
308
+ Phiên đăng nhập của bạn sẽ hết hạn trong 5 phút nữa. Vui lòng lưu
309
+ lại công việc.
310
+ </AlertDescription>
311
+ </div>
312
+ </Alert><Alert
313
+ color="destructive"
314
+ size={globalSize}
315
+ className="flex items-start"
316
+ >
317
+ <AlertIcon render={<XCircleIcon />} className="mt-0.5 shrink-0" />
318
+ <div className="flex-1 space-y-0.5">
319
+ <AlertTitle>Kết nối thất bại</AlertTitle>
320
+ <AlertDescription>
321
+ Không thể kết nối đến cơ sở dữ liệu. Vui lòng kiểm tra lại đường
322
+ truyền mạng.
323
+ </AlertDescription>
324
+ </div>
325
+ </Alert>
326
+ </>
327
+ } />
353
328
 
354
329
  <ExampleGrid>
355
330
  {/* ── Default (no color) ───────────────────── */}
356
- <ExampleSection
357
- label="Cơ bản (Basic)"
358
- description="Hiển thị Alert với màu sắc mặc định (info)."
359
- fullWidth
360
- codeString={`<Alert className="flex items-start">
331
+ <ShowcaseExample title="Cơ bản (Basic)" description="Hiển thị Alert với màu sắc mặc định (info)." code={`<Alert className="flex items-start">
361
332
  <AlertIcon
362
333
  render={<InfoIcon />}
363
334
  className="mt-0.5 shrink-0"
@@ -369,25 +340,22 @@ function AlertMicroShowcase({ globalSize }: { globalSize: Size }) {
369
340
  dụng CLI.
370
341
  </AlertDescription>
371
342
  </div>
372
- </Alert>`}
373
- >
374
- <Alert size={globalSize} className="flex items-start">
375
- <AlertIcon render={<InfoIcon />} className="mt-0.5 shrink-0" />
376
- <div className="flex-1 space-y-0.5">
377
- <AlertTitle>Chú ý!</AlertTitle>
378
- <AlertDescription>
379
- Bạn có thể thêm các component vào dự án bằng cách sử dụng CLI.
380
- </AlertDescription>
381
- </div>
382
- </Alert>
383
- </ExampleSection>
343
+ </Alert>`} preview={
344
+ <>
345
+ <Alert size={globalSize} className="flex items-start">
346
+ <AlertIcon render={<InfoIcon />} className="mt-0.5 shrink-0" />
347
+ <div className="flex-1 space-y-0.5">
348
+ <AlertTitle>Chú ý!</AlertTitle>
349
+ <AlertDescription>
350
+ Bạn có thể thêm các component vào dự án bằng cách sử dụng CLI.
351
+ </AlertDescription>
352
+ </div>
353
+ </Alert>
354
+ </>
355
+ } />
384
356
 
385
357
  {/* ── With Action ───────────────────── */}
386
- <ExampleSection
387
- label="Có Nút Hành Động (With Action)"
388
- description="Alert kèm theo một nút tắt (dismiss) được đặt ở góc trên bên phải."
389
- fullWidth
390
- codeString={`<Alert color="info" className="flex items-start relative">
358
+ <ShowcaseExample title="Có Nút Hành Động (With Action)" description="Alert kèm theo một nút tắt (dismiss) được đặt ở góc trên bên phải." code={`<Alert color="info" className="flex items-start relative">
391
359
  <AlertIcon
392
360
  render={<InfoIcon />}
393
361
  className="mt-0.5 shrink-0"
@@ -408,41 +376,38 @@ function AlertMicroShowcase({ globalSize }: { globalSize: Size }) {
408
376
  <XIcon className="size-3.5 group-data-[size=sm]/alert:size-3 group-data-[size=lg]/alert:size-4" />
409
377
  </Button>
410
378
  </AlertAction>
411
- </Alert>`}
412
- >
413
- <Alert
414
- color="info"
415
- size={globalSize}
416
- className="flex items-start relative"
417
- >
418
- <AlertIcon render={<InfoIcon />} className="mt-0.5 shrink-0" />
419
- <div className="flex-1 space-y-0.5 pr-8">
420
- <AlertTitle>Tính năng mới</AlertTitle>
421
- <AlertDescription>
422
- Hãy khám phá trang thống kê dashboard hoàn toàn mới của chúng
423
- tôi.
424
- </AlertDescription>
425
- </div>
426
- <AlertAction className="absolute right-1 top-1">
427
- <Button
428
- variant="ghost"
429
- size="sm"
430
- className="size-6 p-0 group-data-[size=sm]/alert:size-5 group-data-[size=lg]/alert:size-7"
431
- iconOnly
432
- >
433
- <XIcon className="size-3.5 group-data-[size=sm]/alert:size-3 group-data-[size=lg]/alert:size-4" />
434
- </Button>
435
- </AlertAction>
436
- </Alert>
437
- </ExampleSection>
379
+ </Alert>`} preview={
380
+ <>
381
+ <Alert
382
+ color="info"
383
+ size={globalSize}
384
+ className="flex items-start relative"
385
+ >
386
+ <AlertIcon render={<InfoIcon />} className="mt-0.5 shrink-0" />
387
+ <div className="flex-1 space-y-0.5 pr-8">
388
+ <AlertTitle>Tính năng mới</AlertTitle>
389
+ <AlertDescription>
390
+ Hãy khám phá trang thống kê dashboard hoàn toàn mới của chúng
391
+ tôi.
392
+ </AlertDescription>
393
+ </div>
394
+ <AlertAction className="absolute right-1 top-1">
395
+ <Button
396
+ variant="ghost"
397
+ size="sm"
398
+ className="size-6 p-0 group-data-[size=sm]/alert:size-5 group-data-[size=lg]/alert:size-7"
399
+ iconOnly
400
+ >
401
+ <XIcon className="size-3.5 group-data-[size=sm]/alert:size-3 group-data-[size=lg]/alert:size-4" />
402
+ </Button>
403
+ </AlertAction>
404
+ </Alert>
405
+ </>
406
+ } />
438
407
  </ExampleGrid>
439
408
 
440
409
  {/* ── Minimal (no title) ───────────────────── */}
441
- <ExampleSection
442
- label="Tối Giản (Minimal)"
443
- description="Alert chỉ có nội dung mô tả, không có tiêu đề."
444
- fullWidth
445
- codeString={`<Alert color="info" className="flex items-start">
410
+ <ShowcaseExample title="Tối Giản (Minimal)" description="Alert chỉ có nội dung mô tả, không có tiêu đề." code={`<Alert color="info" className="flex items-start">
446
411
  <AlertIcon
447
412
  render={<InfoIcon />}
448
413
  className="mt-0.5 shrink-0"
@@ -460,31 +425,27 @@ function AlertMicroShowcase({ globalSize }: { globalSize: Size }) {
460
425
  <AlertDescription className="flex-1">
461
426
  Bản dùng thử của bạn sẽ hết hạn trong 3 ngày nữa.
462
427
  </AlertDescription>
463
- </Alert>`}
464
- >
465
- <Alert color="info" size={globalSize} className="flex items-start">
466
- <AlertIcon render={<InfoIcon />} className="mt-0.5 shrink-0" />
467
- <AlertDescription className="flex-1">
468
- Bạn có thể thêm các component vào dự án bằng cách sử dụng CLI.
469
- </AlertDescription>
470
- </Alert>
471
- <Alert color="warning" size={globalSize} className="flex items-start">
472
- <AlertIcon
473
- render={<TriangleAlertIcon />}
474
- className="mt-0.5 shrink-0"
475
- />
476
- <AlertDescription className="flex-1">
477
- Bản dùng thử của bạn sẽ hết hạn trong 3 ngày nữa.
478
- </AlertDescription>
479
- </Alert>
480
- </ExampleSection>
428
+ </Alert>`} preview={
429
+ <>
430
+ <Alert color="info" size={globalSize} className="flex items-start">
431
+ <AlertIcon render={<InfoIcon />} className="mt-0.5 shrink-0" />
432
+ <AlertDescription className="flex-1">
433
+ Bạn có thể thêm các component vào dự án bằng cách sử dụng CLI.
434
+ </AlertDescription>
435
+ </Alert><Alert color="warning" size={globalSize} className="flex items-start">
436
+ <AlertIcon
437
+ render={<TriangleAlertIcon />}
438
+ className="mt-0.5 shrink-0"
439
+ />
440
+ <AlertDescription className="flex-1">
441
+ Bản dùng thử của bạn sẽ hết hạn trong 3 ngày nữa.
442
+ </AlertDescription>
443
+ </Alert>
444
+ </>
445
+ } />
481
446
 
482
447
  {/* ── Text Only (no icon) ───────────────────── */}
483
- <ExampleSection
484
- label="Chỉ Có Chữ (Text Only)"
485
- description="Alert đơn giản không có icon — layout tự nhiên."
486
- fullWidth
487
- codeString={`<Alert color="success" className="flex flex-col gap-0.5">
448
+ <ShowcaseExample title="Chỉ Có Chữ (Text Only)" description="Alert đơn giản không có icon — layout tự nhiên." code={`<Alert color="success" className="flex flex-col gap-0.5">
488
449
  <AlertTitle>Thanh toán thành công</AlertTitle>
489
450
  <AlertDescription>
490
451
  Hoá đơn #1234 của bạn đã được thanh toán hoàn tất.
@@ -499,37 +460,32 @@ function AlertMicroShowcase({ globalSize }: { globalSize: Size }) {
499
460
  Vui lòng liên hệ với bộ phận hỗ trợ để mở khoá tài
500
461
  khoản.
501
462
  </AlertDescription>
502
- </Alert>`}
503
- >
504
- <Alert
505
- color="success"
506
- size={globalSize}
507
- className="flex flex-col gap-0.5"
508
- >
509
- <AlertTitle>Thanh toán thành công</AlertTitle>
510
- <AlertDescription>
511
- Hoá đơn #1234 của bạn đã được thanh toán hoàn tất.
512
- </AlertDescription>
513
- </Alert>
514
- <Alert
515
- color="destructive"
516
- size={globalSize}
517
- className="flex flex-col gap-0.5"
518
- >
519
- <AlertTitle>Tài khoản bị khoá</AlertTitle>
520
- <AlertDescription>
521
- Vui lòng liên hệ với bộ phận hỗ trợ để mở khoá tài khoản.
522
- </AlertDescription>
523
- </Alert>
524
- </ExampleSection>
463
+ </Alert>`} preview={
464
+ <>
465
+ <Alert
466
+ color="success"
467
+ size={globalSize}
468
+ className="flex flex-col gap-0.5"
469
+ >
470
+ <AlertTitle>Thanh toán thành công</AlertTitle>
471
+ <AlertDescription>
472
+ Hoá đơn #1234 của bạn đã được thanh toán hoàn tất.
473
+ </AlertDescription>
474
+ </Alert><Alert
475
+ color="destructive"
476
+ size={globalSize}
477
+ className="flex flex-col gap-0.5"
478
+ >
479
+ <AlertTitle>Tài khoản bị khoá</AlertTitle>
480
+ <AlertDescription>
481
+ Vui lòng liên hệ với bộ phận hỗ trợ để mở khoá tài khoản.
482
+ </AlertDescription>
483
+ </Alert>
484
+ </>
485
+ } />
525
486
 
526
487
  {/* ── Use Case Comparison ─────────────────────── */}
527
- <ExampleSection
528
- label="🧭 Use Case Comparison"
529
- description="Các kịch bản thực tế giúp bạn quyết định nên dùng Micro hay Macro."
530
- fullWidth
531
- codeString={`<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
532
- {/* ── Story 1: Macro wins ── */}
488
+ <ShowcaseExample title="🧭 So sánh Use Case" description="Các kịch bản thực tế giúp bạn quyết định nên dùng Micro hay Macro." code={`<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
533
489
  <div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
534
490
  <div className="flex items-start gap-3">
535
491
  <span className="mt-0.5 shrink-0 rounded-full bg-green-500/10 p-1.5 text-green-600">
@@ -577,7 +533,6 @@ function AlertMicroShowcase({ globalSize }: { globalSize: Size }) {
577
533
  </div>
578
534
  </div>
579
535
 
580
- {/* ── Story 2: Micro wins ── */}
581
536
  <div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
582
537
  <div className="flex items-start gap-3">
583
538
  <span className="mt-0.5 shrink-0 rounded-full bg-blue-500/10 p-1.5 text-blue-600">
@@ -633,104 +588,105 @@ function AlertMicroShowcase({ globalSize }: { globalSize: Size }) {
633
588
  </p>
634
589
  </div>
635
590
  </div>
636
- </div>`}
637
- >
638
- <div className="grid grid-cols-1 gap-6 md:grid-cols-2">
639
- {/* ── Story 1: Macro wins ── */}
640
- <div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
641
- <div className="flex items-start gap-3">
642
- <span className="mt-0.5 shrink-0 rounded-full bg-green-500/10 p-1.5 text-green-600">
643
- <CheckCircle2Icon className="size-4" aria-hidden="true" />
644
- </span>
645
- <div>
646
- <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
647
- Story 1 · Dùng Macro
648
- </p>
649
- <h3 className="mt-0.5 text-sm font-semibold text-foreground">
650
- Thông báo chuẩn, cho phép tự đóng
651
- </h3>
652
- </div>
653
- </div>
654
-
655
- <p className="text-xs text-muted-foreground leading-relaxed">
656
- Phần lớn các cảnh báo trong ứng dụng đều đi kèm Icon, Tiêu đề, Nội
657
- dung, và nút X để tự tắt (Dismiss). Dùng Macro sẽ tiết kiệm cực kỳ
658
- nhiều code.
659
- </p>
660
-
661
- <div className="rounded-lg bg-muted/50 p-3">
662
- <AlertPreset
663
- color="info"
664
- size="sm"
665
- title="Có bản cập nhật mới"
666
- description="Phiên bản 2.0.4 đã sẵn sàng để tải xuống."
667
- icon={<InfoIcon />}
668
- dismissible
669
- />
670
- </div>
671
-
672
- <div className="rounded-md border border-border border-green-500/20 bg-green-500/5 px-3 py-2">
673
- <p className="text-xs font-medium text-green-700 dark:text-green-400">
674
- ✅ Dùng <code className="font-mono">AlertPreset</code> — Prop{" "}
675
- <code className="font-mono">dismissible</code> tự động xử lý
676
- state tắt Alert.
677
- </p>
678
- </div>
679
- </div>
680
-
681
- {/* ── Story 2: Micro wins ── */}
682
- <div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
683
- <div className="flex items-start gap-3">
684
- <span className="mt-0.5 shrink-0 rounded-full bg-blue-500/10 p-1.5 text-blue-600">
685
- <CheckCircle2Icon className="size-4" aria-hidden="true" />
686
- </span>
687
- <div>
688
- <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
689
- Story 2 · Dùng Micro
690
- </p>
691
- <h3 className="mt-0.5 text-sm font-semibold text-foreground">
692
- Giao diện Alert không theo chuẩn
693
- </h3>
694
- </div>
695
- </div>
696
-
697
- <p className="text-xs text-muted-foreground leading-relaxed">
698
- Khi bạn cần tạo một Alert với layout đặc biệt, ví dụ như không có
699
- icon, hoặc muốn chèn form vào giữa. Macro sẽ bị hạn chế vì đã chốt
700
- sẵn layout Flexbox ngang.
701
- </p>
702
-
703
- <div className="rounded-lg bg-muted/50 p-3">
704
- <Alert
705
- color="warning"
706
- size="sm"
707
- className="flex flex-col gap-0.5"
708
- >
709
- <AlertTitle>Bản dùng thử hết hạn</AlertTitle>
710
- <AlertDescription>
711
- Chỉ còn 3 ngày nữa. Vui lòng thanh toán!
712
- </AlertDescription>
713
- <Button
714
- variant="soft"
715
- color="warning"
716
- size="sm"
717
- className="mt-2 w-fit"
718
- >
719
- Nâng Cấp Ngay
720
- </Button>
721
- </Alert>
722
- </div>
723
-
724
- <div className="rounded-md border border-border border-blue-500/20 bg-blue-500/5 px-3 py-2">
725
- <p className="text-xs font-medium text-blue-700 dark:text-blue-400">
726
- ✅ Dùng <code className="font-mono">Alert</code> (Micro) — Bạn
727
- tự viết class <code className="font-mono">flex-col</code>, tự
728
- chèn nội dung thoải mái.
729
- </p>
730
- </div>
731
- </div>
732
- </div>
733
- </ExampleSection>
591
+ </div>`} preview={
592
+ <>
593
+ <div className="grid grid-cols-1 gap-6 md:grid-cols-2">
594
+ {/* ── Story 1: Macro wins ── */}
595
+ <div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
596
+ <div className="flex items-start gap-3">
597
+ <span className="mt-0.5 shrink-0 rounded-full bg-green-500/10 p-1.5 text-green-600">
598
+ <CheckCircle2Icon className="size-4" aria-hidden="true" />
599
+ </span>
600
+ <div>
601
+ <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
602
+ Story 1 · Dùng Macro
603
+ </p>
604
+ <h3 className="mt-0.5 text-sm font-semibold text-foreground">
605
+ Thông báo chuẩn, cho phép tự đóng
606
+ </h3>
607
+ </div>
608
+ </div>
609
+
610
+ <p className="text-xs text-muted-foreground leading-relaxed">
611
+ Phần lớn các cảnh báo trong ứng dụng đều đi kèm Icon, Tiêu đề, Nội
612
+ dung, và nút X để tự tắt (Dismiss). Dùng Macro sẽ tiết kiệm cực kỳ
613
+ nhiều code.
614
+ </p>
615
+
616
+ <div className="rounded-lg bg-muted/50 p-3">
617
+ <AlertPreset
618
+ color="info"
619
+ size="sm"
620
+ title="Có bản cập nhật mới"
621
+ description="Phiên bản 2.0.4 đã sẵn sàng để tải xuống."
622
+ icon={<InfoIcon />}
623
+ dismissible
624
+ />
625
+ </div>
626
+
627
+ <div className="rounded-md border border-border border-green-500/20 bg-green-500/5 px-3 py-2">
628
+ <p className="text-xs font-medium text-green-700 dark:text-green-400">
629
+ ✅ Dùng <code className="font-mono">AlertPreset</code> — Prop{" "}
630
+ <code className="font-mono">dismissible</code> tự động xử lý
631
+ state tắt Alert.
632
+ </p>
633
+ </div>
634
+ </div>
635
+
636
+ {/* ── Story 2: Micro wins ── */}
637
+ <div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
638
+ <div className="flex items-start gap-3">
639
+ <span className="mt-0.5 shrink-0 rounded-full bg-blue-500/10 p-1.5 text-blue-600">
640
+ <CheckCircle2Icon className="size-4" aria-hidden="true" />
641
+ </span>
642
+ <div>
643
+ <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
644
+ Story 2 · Dùng Micro
645
+ </p>
646
+ <h3 className="mt-0.5 text-sm font-semibold text-foreground">
647
+ Giao diện Alert không theo chuẩn
648
+ </h3>
649
+ </div>
650
+ </div>
651
+
652
+ <p className="text-xs text-muted-foreground leading-relaxed">
653
+ Khi bạn cần tạo một Alert với layout đặc biệt, ví dụ như không có
654
+ icon, hoặc muốn chèn form vào giữa. Macro sẽ bị hạn chế vì đã chốt
655
+ sẵn layout Flexbox ngang.
656
+ </p>
657
+
658
+ <div className="rounded-lg bg-muted/50 p-3">
659
+ <Alert
660
+ color="warning"
661
+ size="sm"
662
+ className="flex flex-col gap-0.5"
663
+ >
664
+ <AlertTitle>Bản dùng thử hết hạn</AlertTitle>
665
+ <AlertDescription>
666
+ Chỉ còn 3 ngày nữa. Vui lòng thanh toán!
667
+ </AlertDescription>
668
+ <Button
669
+ variant="soft"
670
+ color="warning"
671
+ size="sm"
672
+ className="mt-2 w-fit"
673
+ >
674
+ Nâng Cấp Ngay
675
+ </Button>
676
+ </Alert>
677
+ </div>
678
+
679
+ <div className="rounded-md border border-border border-blue-500/20 bg-blue-500/5 px-3 py-2">
680
+ <p className="text-xs font-medium text-blue-700 dark:text-blue-400">
681
+ ✅ Dùng <code className="font-mono">Alert</code> (Micro) — Bạn
682
+ tự viết class <code className="font-mono">flex-col</code>, tự
683
+ chèn nội dung thoải mái.
684
+ </p>
685
+ </div>
686
+ </div>
687
+ </div>
688
+ </>
689
+ } />
734
690
  </div>
735
691
  );
736
692
  }
@@ -744,7 +700,7 @@ export default function AlertShowcase() {
744
700
  <Showcase
745
701
  title="Alert"
746
702
  description="Hiển thị một thông báo nổi bật để thu hút sự chú ý của người dùng."
747
- generalConcept={
703
+ guideline={
748
704
  <ShowcaseDocs>
749
705
  <DocsP>
750
706
  Dùng để hiển thị một thông báo quan trọng thu hút sự chú ý của người
@@ -754,14 +710,8 @@ export default function AlertShowcase() {
754
710
  </DocsP>
755
711
  </ShowcaseDocs>
756
712
  }
757
- tabs={[
758
- {
759
- label: "Micro (Primitive)",
760
- content: <AlertMicroShowcase globalSize={globalSize} /> },
761
- {
762
- label: "Macro (Preset)",
763
- content: <AlertMacroShowcase globalSize={globalSize} /> },
764
- ]}
713
+ micro={{ content: <AlertMicroShowcase globalSize={globalSize} /> }}
714
+ macro={{ content: <AlertMacroShowcase globalSize={globalSize} /> }}
765
715
  />
766
716
  );
767
717
  }