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
@@ -23,26 +23,20 @@ import {
23
23
  DocsH3,
24
24
  DocsP,
25
25
  ExampleGrid,
26
- ExampleSection,
26
+ ShowcaseExample,
27
27
  Showcase,
28
28
  ShowcaseDocs
29
29
  } from "../../dev/components/showcase";
30
30
  import { type Size } from "../../lib/types";
31
31
  import { cn } from "../../lib/utils";
32
32
 
33
- // ──────────────────────────────────────────────────────────
34
- // Macro Showcase
35
- // ──────────────────────────────────────────────────────────
36
33
  function DialogMacroShowcase({ globalSize }: { globalSize: Size }) {
37
34
  const [controlledOpen, setControlledOpen] = useState(false);
38
35
 
39
36
  return (
40
37
  <div className="space-y-10">
41
38
  <ExampleGrid>
42
- <ExampleSection
43
- label="Basic Usage"
44
- description="DialogPreset với title, description và footer đơn giản."
45
- codeString={`<DialogPreset
39
+ <ShowcaseExample title="Basic Usage" description="DialogPreset với title, description và footer đơn giản." code={`<DialogPreset
46
40
  title="Update Subscription"
47
41
  description="Are you sure you want to upgrade your plan to Pro? This will charge your card immediately."
48
42
  trigger={
@@ -50,44 +44,42 @@ function DialogMacroShowcase({ globalSize }: { globalSize: Size }) {
50
44
  }
51
45
  footer={
52
46
  <>
53
- <Button variant="ghost">Cancel</Button>
47
+ <Button variant="ghost">Huỷ</Button>
54
48
  <Button color="primary">Confirm</Button>
55
49
  </>
56
50
  }
57
- />`}
58
- >
59
- <DialogPreset
60
- size={globalSize}
61
- title="Update Subscription"
62
- description="Are you sure you want to upgrade your plan to Pro? This will charge your card immediately."
63
- trigger={
64
- <Button variant="outline" size={globalSize}>
65
- Upgrade Plan
66
- </Button>
67
- }
68
- footer={
69
- <>
70
- <Button variant="ghost" size={globalSize}>
71
- Cancel
72
- </Button>
73
- <Button color="primary" size={globalSize}>
74
- Confirm
75
- </Button>
76
- </>
77
- }
78
- />
79
- </ExampleSection>
51
+ />`} preview={
52
+ <>
53
+ <DialogPreset
54
+ size={globalSize}
55
+ title="Update Subscription"
56
+ description="Are you sure you want to upgrade your plan to Pro? This will charge your card immediately."
57
+ trigger={
58
+ <Button variant="outline" size={globalSize}>
59
+ Upgrade Plan
60
+ </Button>
61
+ }
62
+ footer={
63
+ <>
64
+ <Button variant="ghost" size={globalSize}>
65
+ Cancel
66
+ </Button>
67
+ <Button color="primary" size={globalSize}>
68
+ Confirm
69
+ </Button>
70
+ </>
71
+ }
72
+ />
73
+ </>
74
+ } />
80
75
 
81
- <ExampleSection
82
- label="Forms & Custom Content"
83
- description="Sử dụng children để render form hoặc nội dung phức tạp."
84
- codeString={`<DialogPreset
85
- title="Edit profile"
86
- description="Make changes to your profile here. Click save when you're done."
76
+ <ShowcaseExample title="Forms & Custom Content" description="Sử dụng children để render form hoặc nội dung phức tạp." code={`<DialogPreset
77
+ title="Chỉnh sửa hồ "
78
+ description="Thay đổi thông tin hồ của bạn tại đây. Bấm lưu khi hoàn tất."
87
79
  trigger={
88
- <Button variant="outline">Edit Profile</Button>
80
+ <Button variant="outline">Chỉnh sửa hồ sơ</Button>
89
81
  }
90
- footer={<Button type="submit">Save changes</Button>}
82
+ footer={<Button type="submit">Lưu thay đổi</Button>}
91
83
  >
92
84
  <div className="grid gap-4 py-4">
93
85
  <div className="grid grid-cols-4 items-center gap-4">
@@ -111,57 +103,55 @@ function DialogMacroShowcase({ globalSize }: { globalSize: Size }) {
111
103
  />
112
104
  </div>
113
105
  </div>
114
- </DialogPreset>`}
115
- >
116
- <DialogPreset
117
- size={globalSize}
118
- title="Edit profile"
119
- description="Make changes to your profile here. Click save when you're done."
120
- trigger={
121
- <Button variant="outline" size={globalSize}>
122
- Edit Profile
123
- </Button>
124
- }
125
- footer={
126
- <Button type="submit" size={globalSize}>
127
- Save changes
128
- </Button>
129
- }
130
- >
131
- <div className="grid gap-4 py-4">
132
- <div className="grid grid-cols-4 items-center gap-4">
133
- <Label htmlFor="name" className="text-right">
134
- Name
135
- </Label>
136
- <Input
137
- id="name"
138
- defaultValue="Pedro Duarte"
139
- className="col-span-3"
140
- />
141
- </div>
142
- <div className="grid grid-cols-4 items-center gap-4">
143
- <Label htmlFor="username" className="text-right">
144
- Username
145
- </Label>
146
- <Input
147
- id="username"
148
- defaultValue="@peduarte"
149
- className="col-span-3"
150
- />
151
- </div>
152
- </div>
153
- </DialogPreset>
154
- </ExampleSection>
106
+ </DialogPreset>`} preview={
107
+ <>
108
+ <DialogPreset
109
+ size={globalSize}
110
+ title="Chỉnh sửa hồ sơ"
111
+ description="Thay đổi thông tin hồ sơ của bạn tại đây. Bấm lưu khi hoàn tất."
112
+ trigger={
113
+ <Button variant="outline" size={globalSize}>
114
+ Chỉnh sửa hồ sơ
115
+ </Button>
116
+ }
117
+ footer={
118
+ <Button type="submit" size={globalSize}>
119
+ Lưu thay đổi
120
+ </Button>
121
+ }
122
+ >
123
+ <div className="grid gap-4 py-4">
124
+ <div className="grid grid-cols-4 items-center gap-4">
125
+ <Label htmlFor="name" className="text-right">
126
+ Name
127
+ </Label>
128
+ <Input
129
+ id="name"
130
+ defaultValue="Pedro Duarte"
131
+ className="col-span-3"
132
+ />
133
+ </div>
134
+ <div className="grid grid-cols-4 items-center gap-4">
135
+ <Label htmlFor="username" className="text-right">
136
+ Username
137
+ </Label>
138
+ <Input
139
+ id="username"
140
+ defaultValue="@peduarte"
141
+ className="col-span-3"
142
+ />
143
+ </div>
144
+ </div>
145
+ </DialogPreset>
146
+ </>
147
+ } />
155
148
  </ExampleGrid>
156
149
 
157
150
  <ExampleGrid>
158
- <ExampleSection
159
- label="No Close Button"
160
- description="Ẩn nút X ở góc trên bằng showCloseButton={false}."
161
- codeString={`<DialogPreset
151
+ <ShowcaseExample title="No Close Button" description="Ẩn nút X ở góc trên bằng showCloseButton={false}." code={`<DialogPreset
162
152
  showCloseButton={false}
163
- title="Terms of Service"
164
- description="You must accept the new terms to continue using the application."
153
+ title="Điều khoản Dịch vụ"
154
+ description="Bạn phải chấp nhận điều khoản mới để tiếp tục sử dụng ứng dụng."
165
155
  trigger={<Button variant="outline">View Terms</Button>}
166
156
  footer={
167
157
  <>
@@ -171,43 +161,41 @@ function DialogMacroShowcase({ globalSize }: { globalSize: Size }) {
171
161
  }
172
162
  >
173
163
  <p className="text-sm text-muted-foreground">
174
- By clicking accept, you agree to our updated Terms of
175
- Service and Privacy Policy.
164
+ Bằng cách chọn chấp nhận, bạn đồng ý với Điều khoản của
165
+ Dịch vụ Chính sách bảo mật.
176
166
  </p>
177
- </DialogPreset>`}
178
- >
179
- <DialogPreset
180
- size={globalSize}
181
- showCloseButton={false}
182
- title="Terms of Service"
183
- description="You must accept the new terms to continue using the application."
184
- trigger={
185
- <Button variant="outline" size={globalSize}>
186
- View Terms
187
- </Button>
188
- }
189
- footer={
190
- <>
191
- <Button variant="outline" size={globalSize}>
192
- Decline
193
- </Button>
194
- <Button size={globalSize}>Accept</Button>
195
- </>
196
- }
197
- >
198
- <p className="text-sm text-muted-foreground">
199
- By clicking accept, you agree to our updated Terms of Service and
200
- Privacy Policy.
201
- </p>
202
- </DialogPreset>
203
- </ExampleSection>
167
+ </DialogPreset>`} preview={
168
+ <>
169
+ <DialogPreset
170
+ size={globalSize}
171
+ showCloseButton={false}
172
+ title="Điều khoản Dịch vụ"
173
+ description="Bạn phải chấp nhận điều khoản mới để tiếp tục sử dụng ứng dụng."
174
+ trigger={
175
+ <Button variant="outline" size={globalSize}>
176
+ View Terms
177
+ </Button>
178
+ }
179
+ footer={
180
+ <>
181
+ <Button variant="outline" size={globalSize}>
182
+ Decline
183
+ </Button>
184
+ <Button size={globalSize}>Accept</Button>
185
+ </>
186
+ }
187
+ >
188
+ <p className="text-sm text-muted-foreground">
189
+ Bằng cách chọn chấp nhận, bạn đồng ý với Điều khoản của Service and
190
+ Privacy Policy.
191
+ </p>
192
+ </DialogPreset>
193
+ </>
194
+ } />
204
195
 
205
- <ExampleSection
206
- label="Large Content Sizing"
207
- description="Sử dụng size='lg' cho nội dung lớn hơn."
208
- codeString={`<DialogPreset
209
- title="Detailed Report"
210
- description="Monthly analytics and performance overview."
196
+ <ShowcaseExample title="Large Content Sizing" description="Sử dụng size='lg' cho nội dung lớn hơn." code={`<DialogPreset
197
+ title="Báo cáo chi tiết"
198
+ description="Phân tích hàng tháng tổng quan hiệu suất."
211
199
  trigger={<Button variant="outline">View Report</Button>}
212
200
  footer={<Button>Download PDF</Button>}
213
201
  >
@@ -216,33 +204,31 @@ function DialogMacroShowcase({ globalSize }: { globalSize: Size }) {
216
204
  Large Content Area
217
205
  </span>
218
206
  </div>
219
- </DialogPreset>`}
220
- >
221
- <DialogPreset
222
- size={globalSize}
223
- title="Detailed Report"
224
- description="Monthly analytics and performance overview."
225
- trigger={
226
- <Button variant="outline" size={globalSize}>
227
- View Report
228
- </Button>
229
- }
230
- footer={<Button size={globalSize}>Download PDF</Button>}
231
- >
232
- <div className="h-[200px] flex items-center justify-center rounded-md border border-border border-dashed bg-muted/20">
233
- <span className="text-muted-foreground text-sm">
234
- Large Content Area
235
- </span>
236
- </div>
237
- </DialogPreset>
238
- </ExampleSection>
207
+ </DialogPreset>`} preview={
208
+ <>
209
+ <DialogPreset
210
+ size={globalSize}
211
+ title="Báo cáo chi tiết"
212
+ description="Phân tích hàng tháng và tổng quan hiệu suất."
213
+ trigger={
214
+ <Button variant="outline" size={globalSize}>
215
+ View Report
216
+ </Button>
217
+ }
218
+ footer={<Button size={globalSize}>Download PDF</Button>}
219
+ >
220
+ <div className="h-[200px] flex items-center justify-center rounded-md border border-border border-dashed bg-muted/20">
221
+ <span className="text-muted-foreground text-sm">
222
+ Large Content Area
223
+ </span>
224
+ </div>
225
+ </DialogPreset>
226
+ </>
227
+ } />
239
228
  </ExampleGrid>
240
229
 
241
230
  <ExampleGrid>
242
- <ExampleSection
243
- label="Controlled State"
244
- description="Sử dụng open và onOpenChange để quản lý trạng thái đóng mở bằng React state."
245
- codeString={`<div className="w-full flex flex-col gap-4 items-center justify-center">
231
+ <ShowcaseExample title="Controlled State" description="Sử dụng open và onOpenChange để quản lý trạng thái đóng mở bằng React state." code={`<div className="w-full flex flex-col gap-4 items-center justify-center">
246
232
  <div className="flex gap-4 items-center">
247
233
  <Button
248
234
  onClick={() => setControlledOpen(true)}
@@ -273,60 +259,58 @@ function DialogMacroShowcase({ globalSize }: { globalSize: Size }) {
273
259
  Bạn có thể đóng bằng nút bên dưới hoặc dấu X.
274
260
  </p>
275
261
  </DialogPreset>
276
- </div>`}
277
- >
278
- <div className="w-full flex flex-col gap-4 items-center justify-center">
279
- <div className="flex gap-4 items-center">
280
- <Button
281
- onClick={() => setControlledOpen(true)}
282
- variant="outline"
283
- size={globalSize}
284
- >
285
- Open Controlled Dialog
286
- </Button>
287
- <span className="text-sm text-muted-foreground font-mono">
288
- State: {controlledOpen ? "true" : "false"}
289
- </span>
290
- </div>
262
+ </div>`} preview={
263
+ <>
264
+ <div className="w-full flex flex-col gap-4 items-center justify-center">
265
+ <div className="flex gap-4 items-center">
266
+ <Button
267
+ onClick={() => setControlledOpen(true)}
268
+ variant="outline"
269
+ size={globalSize}
270
+ >
271
+ Open Controlled Dialog
272
+ </Button>
273
+ <span className="text-sm text-muted-foreground font-mono">
274
+ State: {controlledOpen ? "true" : "false"}
275
+ </span>
276
+ </div>
291
277
 
292
- <DialogPreset
293
- open={controlledOpen}
294
- onOpenChange={setControlledOpen}
295
- size={globalSize}
296
- title="Controlled Dialog"
297
- description="Trạng thái của dialog này được quản lý hoàn toàn bởi React state bên ngoài."
298
- footer={
299
- <Button
300
- color="primary"
301
- onClick={() => setControlledOpen(false)}
302
- size={globalSize}
303
- >
304
- Close Manually
305
- </Button>
306
- }
307
- >
308
- <p className="text-sm text-foreground">
309
- Bạn có thể đóng bằng nút bên dưới hoặc dấu X.
310
- </p>
311
- </DialogPreset>
312
- </div>
313
- </ExampleSection>
278
+ <DialogPreset
279
+ open={controlledOpen}
280
+ onOpenChange={setControlledOpen}
281
+ size={globalSize}
282
+ title="Controlled Dialog"
283
+ description="Trạng thái của dialog này được quản lý hoàn toàn bởi React state bên ngoài."
284
+ footer={
285
+ <Button
286
+ color="primary"
287
+ onClick={() => setControlledOpen(false)}
288
+ size={globalSize}
289
+ >
290
+ Close Manually
291
+ </Button>
292
+ }
293
+ >
294
+ <p className="text-sm text-foreground">
295
+ Bạn có thể đóng bằng nút bên dưới hoặc dấu X.
296
+ </p>
297
+ </DialogPreset>
298
+ </div>
299
+ </>
300
+ } />
314
301
 
315
- <ExampleSection
316
- label="Sticky Footer (Long Content)"
317
- description="Layout in-flow giúp footer luôn dính ở dưới cùng khi có thanh cuộn."
318
- codeString={`<DialogPreset
302
+ <ShowcaseExample title="Sticky Footer (Long Content)" description="Layout in-flow giúp footer luôn dính ở dưới cùng khi có thanh cuộn." code={`<DialogPreset
319
303
  trigger={
320
304
  <Button variant="outline">View Long Content</Button>
321
305
  }
322
- title="Terms & Conditions"
306
+ title="Điều khoản & Điều kiện"
323
307
  description="Cuộn xuống dưới cùng để có thể đồng ý với điều khoản."
324
308
  footer={
325
309
  <div className="flex w-full sm:justify-end gap-2">
326
310
  <DialogClose render={<Button variant="ghost" />}>
327
311
  Cancel
328
312
  </DialogClose>
329
- <Button>I Agree</Button>
313
+ <Button>Tôi đồng ý</Button>
330
314
  </div>
331
315
  }
332
316
  >
@@ -344,52 +328,50 @@ function DialogMacroShowcase({ globalSize }: { globalSize: Size }) {
344
328
  END OF CONTENT
345
329
  </span>
346
330
  </div>
347
- </DialogPreset>`}
348
- >
349
- <DialogPreset
350
- trigger={
351
- <Button variant="outline" size={globalSize}>
352
- View Long Content
353
- </Button>
354
- }
355
- size={globalSize}
356
- title="Terms & Conditions"
357
- description="Cuộn xuống dưới cùng để có thể đồng ý với điều khoản."
358
- footer={
359
- <div className="flex w-full sm:justify-end gap-2">
360
- <DialogClose
361
- render={<Button variant="ghost" size={globalSize} />}
362
- >
363
- Cancel
364
- </DialogClose>
365
- <Button size={globalSize}>I Agree</Button>
366
- </div>
367
- }
368
- >
369
- <div className="flex h-[800px] flex-col items-center justify-between rounded-md border border-border border-dashed bg-muted/20 py-8">
370
- <span className="text-sm font-medium text-muted-foreground">
371
- START OF CONTENT
372
- </span>
373
- <div className="flex flex-col items-center gap-2">
374
- <span className="text-4xl">👇</span>
375
- <span className="text-sm text-muted-foreground">
376
- Keep scrolling
377
- </span>
378
- </div>
379
- <span className="text-sm font-medium text-muted-foreground">
380
- END OF CONTENT
381
- </span>
382
- </div>
383
- </DialogPreset>
384
- </ExampleSection>
331
+ </DialogPreset>`} preview={
332
+ <>
333
+ <DialogPreset
334
+ trigger={
335
+ <Button variant="outline" size={globalSize}>
336
+ View Long Content
337
+ </Button>
338
+ }
339
+ size={globalSize}
340
+ title="Điều khoản & Điều kiện"
341
+ description="Cuộn xuống dưới cùng để có thể đồng ý với điều khoản."
342
+ footer={
343
+ <div className="flex w-full sm:justify-end gap-2">
344
+ <DialogClose
345
+ render={<Button variant="ghost" size={globalSize} />}
346
+ >
347
+ Cancel
348
+ </DialogClose>
349
+ <Button size={globalSize}>Tôi đồng ý</Button>
350
+ </div>
351
+ }
352
+ >
353
+ <div className="flex h-[800px] flex-col items-center justify-between rounded-md border border-border border-dashed bg-muted/20 py-8">
354
+ <span className="text-sm font-medium text-muted-foreground">
355
+ START OF CONTENT
356
+ </span>
357
+ <div className="flex flex-col items-center gap-2">
358
+ <span className="text-4xl">👇</span>
359
+ <span className="text-sm text-muted-foreground">
360
+ Keep scrolling
361
+ </span>
362
+ </div>
363
+ <span className="text-sm font-medium text-muted-foreground">
364
+ END OF CONTENT
365
+ </span>
366
+ </div>
367
+ </DialogPreset>
368
+ </>
369
+ } />
385
370
  </ExampleGrid>
386
371
  </div>
387
372
  );
388
373
  }
389
374
 
390
- // ──────────────────────────────────────────────────────────
391
- // Micro Showcase
392
- // ──────────────────────────────────────────────────────────
393
375
  function DialogMicroShowcase({ globalSize }: { globalSize: Size }) {
394
376
  const [controlledOpen, setControlledOpen] = useState(false);
395
377
  const contentClass =
@@ -402,10 +384,7 @@ function DialogMicroShowcase({ globalSize }: { globalSize: Size }) {
402
384
  return (
403
385
  <div className="space-y-10">
404
386
  <ExampleGrid>
405
- <ExampleSection
406
- label="Basic Usage"
407
- description="Sử dụng các thành phần rời rạc để tạo dialog cơ bản."
408
- codeString={`<Dialog>
387
+ <ShowcaseExample title="Basic Usage" description="Sử dụng các thành phần rời rạc để tạo dialog cơ bản." code={`<Dialog>
409
388
  <DialogTrigger
410
389
  render={
411
390
  <Button variant="outline">Upgrade Plan</Button>
@@ -441,66 +420,64 @@ function DialogMicroShowcase({ globalSize }: { globalSize: Size }) {
441
420
  </DialogClose>
442
421
  </DialogContent>
443
422
 
444
- </Dialog>`}
445
- >
446
- <Dialog>
447
- <DialogTrigger
448
- render={
449
- <Button variant="outline" size={globalSize}>
450
- Upgrade Plan
451
- </Button>
452
- }
453
- />
423
+ </Dialog>`} preview={
424
+ <>
425
+ <Dialog>
426
+ <DialogTrigger
427
+ render={
428
+ <Button variant="outline" size={globalSize}>
429
+ Upgrade Plan
430
+ </Button>
431
+ }
432
+ />
454
433
 
455
- <DialogContent className={contentClass}>
456
- <DialogHeader>
457
- <DialogTitle>Update Subscription</DialogTitle>
458
- <DialogDescription>
459
- Are you sure you want to upgrade your plan to Pro? This will
460
- charge your card immediately.
461
- </DialogDescription>
462
- </DialogHeader>
463
- <DialogFooter className="-mx-4 -mb-4 mt-4 rounded-b-xl border-t border-t-border bg-muted/50 p-4">
464
- <DialogClose
465
- render={<Button variant="ghost" size={globalSize} />}
466
- >
467
- Cancel
468
- </DialogClose>
469
- <Button color="primary" size={globalSize}>
470
- Confirm
471
- </Button>
472
- </DialogFooter>
473
- <DialogClose
474
- render={
475
- <Button
476
- variant="ghost"
477
- className="absolute top-2 right-2"
478
- size="sm"
479
- iconOnly
480
- />
481
- }
482
- >
483
- <XIcon />
484
- <span className="sr-only">Close</span>
485
- </DialogClose>
486
- </DialogContent>
487
-
488
- </Dialog>
489
- </ExampleSection>
434
+ <DialogContent className={contentClass}>
435
+ <DialogHeader>
436
+ <DialogTitle>Update Subscription</DialogTitle>
437
+ <DialogDescription>
438
+ Are you sure you want to upgrade your plan to Pro? This will
439
+ charge your card immediately.
440
+ </DialogDescription>
441
+ </DialogHeader>
442
+ <DialogFooter className="-mx-4 -mb-4 mt-4 rounded-b-xl border-t border-t-border bg-muted/50 p-4">
443
+ <DialogClose
444
+ render={<Button variant="ghost" size={globalSize} />}
445
+ >
446
+ Cancel
447
+ </DialogClose>
448
+ <Button color="primary" size={globalSize}>
449
+ Confirm
450
+ </Button>
451
+ </DialogFooter>
452
+ <DialogClose
453
+ render={
454
+ <Button
455
+ variant="ghost"
456
+ className="absolute top-2 right-2"
457
+ size="sm"
458
+ iconOnly
459
+ />
460
+ }
461
+ >
462
+ <XIcon />
463
+ <span className="sr-only">Close</span>
464
+ </DialogClose>
465
+ </DialogContent>
466
+
467
+ </Dialog>
468
+ </>
469
+ } />
490
470
 
491
- <ExampleSection
492
- label="Forms & Custom Content"
493
- description="Sử dụng form bên trong DialogContent."
494
- codeString={`<Dialog>
471
+ <ShowcaseExample title="Forms & Custom Content" description="Sử dụng form bên trong DialogContent." code={`<Dialog>
495
472
  <DialogTrigger
496
473
  render={
497
- <Button variant="outline">Edit Profile</Button>
474
+ <Button variant="outline">Chỉnh sửa hồ sơ</Button>
498
475
  }
499
476
  />
500
477
 
501
478
  <DialogContent className={contentClass}>
502
479
  <DialogHeader>
503
- <DialogTitle>Edit profile</DialogTitle>
480
+ <DialogTitle>Chỉnh sửa hồ sơ</DialogTitle>
504
481
  <DialogDescription>
505
482
  Make changes to your profile here. Click save
506
483
  when you're done.
@@ -532,7 +509,7 @@ function DialogMicroShowcase({ globalSize }: { globalSize: Size }) {
532
509
  </div>
533
510
  </div>
534
511
  <DialogFooter className="-mx-4 -mb-4 mt-4 rounded-b-xl border-t border-t-border bg-muted/50 p-4">
535
- <Button type="submit">Save changes</Button>
512
+ <Button type="submit">Lưu thay đổi</Button>
536
513
  </DialogFooter>
537
514
  <DialogClose
538
515
  render={
@@ -549,91 +526,89 @@ function DialogMicroShowcase({ globalSize }: { globalSize: Size }) {
549
526
  </DialogClose>
550
527
  </DialogContent>
551
528
 
552
- </Dialog>`}
553
- >
554
- <Dialog>
555
- <DialogTrigger
556
- render={
557
- <Button variant="outline" size={globalSize}>
558
- Edit Profile
559
- </Button>
560
- }
561
- />
529
+ </Dialog>`} preview={
530
+ <>
531
+ <Dialog>
532
+ <DialogTrigger
533
+ render={
534
+ <Button variant="outline" size={globalSize}>
535
+ Chỉnh sửa hồ sơ
536
+ </Button>
537
+ }
538
+ />
562
539
 
563
- <DialogContent className={contentClass}>
564
- <DialogHeader>
565
- <DialogTitle>Edit profile</DialogTitle>
566
- <DialogDescription>
567
- Make changes to your profile here. Click save when you're
568
- done.
569
- </DialogDescription>
570
- </DialogHeader>
571
- <div className="grid gap-4 py-4">
572
- <div className="grid grid-cols-4 items-center gap-4">
573
- <Label htmlFor="name" className="text-right">
574
- Name
575
- </Label>
576
- <Input
577
- id="name"
578
- defaultValue="Pedro Duarte"
579
- className="col-span-3"
580
- />
581
- </div>
582
- <div className="grid grid-cols-4 items-center gap-4">
583
- <Label htmlFor="username" className="text-right">
584
- Username
585
- </Label>
586
- <Input
587
- id="username"
588
- defaultValue="@peduarte"
589
- className="col-span-3"
590
- />
591
- </div>
592
- </div>
593
- <DialogFooter className="-mx-4 -mb-4 mt-4 rounded-b-xl border-t border-t-border bg-muted/50 p-4">
594
- <Button type="submit" size={globalSize}>
595
- Save changes
596
- </Button>
597
- </DialogFooter>
598
- <DialogClose
599
- render={
600
- <Button
601
- variant="ghost"
602
- className="absolute top-2 right-2"
603
- size="sm"
604
- iconOnly
605
- />
606
- }
607
- >
608
- <XIcon />
609
- <span className="sr-only">Close</span>
610
- </DialogClose>
611
- </DialogContent>
612
-
613
- </Dialog>
614
- </ExampleSection>
540
+ <DialogContent className={contentClass}>
541
+ <DialogHeader>
542
+ <DialogTitle>Chỉnh sửa hồ sơ</DialogTitle>
543
+ <DialogDescription>
544
+ Make changes to your profile here. Click save when you're
545
+ done.
546
+ </DialogDescription>
547
+ </DialogHeader>
548
+ <div className="grid gap-4 py-4">
549
+ <div className="grid grid-cols-4 items-center gap-4">
550
+ <Label htmlFor="name" className="text-right">
551
+ Name
552
+ </Label>
553
+ <Input
554
+ id="name"
555
+ defaultValue="Pedro Duarte"
556
+ className="col-span-3"
557
+ />
558
+ </div>
559
+ <div className="grid grid-cols-4 items-center gap-4">
560
+ <Label htmlFor="username" className="text-right">
561
+ Username
562
+ </Label>
563
+ <Input
564
+ id="username"
565
+ defaultValue="@peduarte"
566
+ className="col-span-3"
567
+ />
568
+ </div>
569
+ </div>
570
+ <DialogFooter className="-mx-4 -mb-4 mt-4 rounded-b-xl border-t border-t-border bg-muted/50 p-4">
571
+ <Button type="submit" size={globalSize}>
572
+ Lưu thay đổi
573
+ </Button>
574
+ </DialogFooter>
575
+ <DialogClose
576
+ render={
577
+ <Button
578
+ variant="ghost"
579
+ className="absolute top-2 right-2"
580
+ size="sm"
581
+ iconOnly
582
+ />
583
+ }
584
+ >
585
+ <XIcon />
586
+ <span className="sr-only">Close</span>
587
+ </DialogClose>
588
+ </DialogContent>
589
+
590
+ </Dialog>
591
+ </>
592
+ } />
615
593
  </ExampleGrid>
616
594
 
617
595
  <ExampleGrid>
618
- <ExampleSection
619
- label="No Close Button"
620
- description="Không render nút XIcon thủ công."
621
- codeString={`<Dialog>
596
+ <ShowcaseExample title="No Close Button" description="Không render nút XIcon thủ công." code={`<Dialog>
622
597
  <DialogTrigger
623
598
  render={<Button variant="outline">View Terms</Button>}
624
599
  />
625
600
 
626
601
  <DialogContent className={contentClass}>
627
602
  <DialogHeader>
628
- <DialogTitle>Terms of Service</DialogTitle>
603
+ <DialogTitle>Điều khoản Dịch vụ</DialogTitle>
629
604
  <DialogDescription>
630
605
  You must accept the new terms to continue using
631
606
  the application.
632
607
  </DialogDescription>
633
608
  </DialogHeader>
634
609
  <p className="text-sm text-muted-foreground">
635
- By clicking accept, you agree to our updated Terms
636
- of Service and Privacy Policy.
610
+ Bằng cách chọn chấp nhận, bạn đồng ý với Điều khoản
611
+ of Dịch vụ Chính sách bảo mật.
637
612
  </p>
638
613
  <DialogFooter className="-mx-4 -mb-4 mt-4 rounded-b-xl border-t border-t-border bg-muted/50 p-4">
639
614
  <DialogClose
@@ -645,46 +620,44 @@ function DialogMicroShowcase({ globalSize }: { globalSize: Size }) {
645
620
  </DialogFooter>
646
621
  </DialogContent>
647
622
 
648
- </Dialog>`}
649
- >
650
- <Dialog>
651
- <DialogTrigger
652
- render={
653
- <Button variant="outline" size={globalSize}>
654
- View Terms
655
- </Button>
656
- }
657
- />
623
+ </Dialog>`} preview={
624
+ <>
625
+ <Dialog>
626
+ <DialogTrigger
627
+ render={
628
+ <Button variant="outline" size={globalSize}>
629
+ View Terms
630
+ </Button>
631
+ }
632
+ />
658
633
 
659
- <DialogContent className={contentClass}>
660
- <DialogHeader>
661
- <DialogTitle>Terms of Service</DialogTitle>
662
- <DialogDescription>
663
- You must accept the new terms to continue using the
664
- application.
665
- </DialogDescription>
666
- </DialogHeader>
667
- <p className="text-sm text-muted-foreground">
668
- By clicking accept, you agree to our updated Terms of Service
669
- and Privacy Policy.
670
- </p>
671
- <DialogFooter className="-mx-4 -mb-4 mt-4 rounded-b-xl border-t border-t-border bg-muted/50 p-4">
672
- <DialogClose
673
- render={<Button variant="outline" size={globalSize} />}
674
- >
675
- Decline
676
- </DialogClose>
677
- <Button size={globalSize}>Accept</Button>
678
- </DialogFooter>
679
- </DialogContent>
680
-
681
- </Dialog>
682
- </ExampleSection>
634
+ <DialogContent className={contentClass}>
635
+ <DialogHeader>
636
+ <DialogTitle>Điều khoản Dịch vụ</DialogTitle>
637
+ <DialogDescription>
638
+ You must accept the new terms to continue using the
639
+ application.
640
+ </DialogDescription>
641
+ </DialogHeader>
642
+ <p className="text-sm text-muted-foreground">
643
+ Bằng cách chọn chấp nhận, bạn đồng ý với Điều khoản của Service
644
+ and Privacy Policy.
645
+ </p>
646
+ <DialogFooter className="-mx-4 -mb-4 mt-4 rounded-b-xl border-t border-t-border bg-muted/50 p-4">
647
+ <DialogClose
648
+ render={<Button variant="outline" size={globalSize} />}
649
+ >
650
+ Decline
651
+ </DialogClose>
652
+ <Button size={globalSize}>Accept</Button>
653
+ </DialogFooter>
654
+ </DialogContent>
655
+
656
+ </Dialog>
657
+ </>
658
+ } />
683
659
 
684
- <ExampleSection
685
- label="Large Content Sizing"
686
- description="Sử dụng sm:max-w-lg cho nội dung lớn hơn."
687
- codeString={`<Dialog>
660
+ <ShowcaseExample title="Large Content Sizing" description="Sử dụng sm:max-w-lg cho nội dung lớn hơn." code={`<Dialog>
688
661
  <DialogTrigger
689
662
  render={
690
663
  <Button variant="outline">View Report</Button>
@@ -693,9 +666,9 @@ function DialogMicroShowcase({ globalSize }: { globalSize: Size }) {
693
666
 
694
667
  <DialogContent className={contentClass}>
695
668
  <DialogHeader>
696
- <DialogTitle>Detailed Report</DialogTitle>
669
+ <DialogTitle>Báo cáo chi tiết</DialogTitle>
697
670
  <DialogDescription>
698
- Monthly analytics and performance overview.
671
+ Phân tích hàng tháng và tổng quan hiệu suất.
699
672
  </DialogDescription>
700
673
  </DialogHeader>
701
674
  <div className="flex h-[200px] items-center justify-center rounded-md border border-border border-dashed bg-muted/20">
@@ -721,56 +694,54 @@ function DialogMicroShowcase({ globalSize }: { globalSize: Size }) {
721
694
  </DialogClose>
722
695
  </DialogContent>
723
696
 
724
- </Dialog>`}
725
- >
726
- <Dialog>
727
- <DialogTrigger
728
- render={
729
- <Button variant="outline" size={globalSize}>
730
- View Report
731
- </Button>
732
- }
733
- />
697
+ </Dialog>`} preview={
698
+ <>
699
+ <Dialog>
700
+ <DialogTrigger
701
+ render={
702
+ <Button variant="outline" size={globalSize}>
703
+ View Report
704
+ </Button>
705
+ }
706
+ />
734
707
 
735
- <DialogContent className={contentClass}>
736
- <DialogHeader>
737
- <DialogTitle>Detailed Report</DialogTitle>
738
- <DialogDescription>
739
- Monthly analytics and performance overview.
740
- </DialogDescription>
741
- </DialogHeader>
742
- <div className="flex h-[200px] items-center justify-center rounded-md border border-border border-dashed bg-muted/20">
743
- <span className="text-sm text-muted-foreground">
744
- Large Content Area
745
- </span>
746
- </div>
747
- <DialogFooter className="-mx-4 -mb-4 mt-4 rounded-b-xl border-t border-t-border bg-muted/50 p-4">
748
- <Button size={globalSize}>Download PDF</Button>
749
- </DialogFooter>
750
- <DialogClose
751
- render={
752
- <Button
753
- variant="ghost"
754
- className="absolute top-2 right-2"
755
- size="sm"
756
- iconOnly
757
- />
758
- }
759
- >
760
- <XIcon />
761
- <span className="sr-only">Close</span>
762
- </DialogClose>
763
- </DialogContent>
764
-
765
- </Dialog>
766
- </ExampleSection>
708
+ <DialogContent className={contentClass}>
709
+ <DialogHeader>
710
+ <DialogTitle>Báo cáo chi tiết</DialogTitle>
711
+ <DialogDescription>
712
+ Phân tích hàng tháng và tổng quan hiệu suất.
713
+ </DialogDescription>
714
+ </DialogHeader>
715
+ <div className="flex h-[200px] items-center justify-center rounded-md border border-border border-dashed bg-muted/20">
716
+ <span className="text-sm text-muted-foreground">
717
+ Large Content Area
718
+ </span>
719
+ </div>
720
+ <DialogFooter className="-mx-4 -mb-4 mt-4 rounded-b-xl border-t border-t-border bg-muted/50 p-4">
721
+ <Button size={globalSize}>Download PDF</Button>
722
+ </DialogFooter>
723
+ <DialogClose
724
+ render={
725
+ <Button
726
+ variant="ghost"
727
+ className="absolute top-2 right-2"
728
+ size="sm"
729
+ iconOnly
730
+ />
731
+ }
732
+ >
733
+ <XIcon />
734
+ <span className="sr-only">Close</span>
735
+ </DialogClose>
736
+ </DialogContent>
737
+
738
+ </Dialog>
739
+ </>
740
+ } />
767
741
  </ExampleGrid>
768
742
 
769
743
  <ExampleGrid>
770
- <ExampleSection
771
- label="Controlled State"
772
- description="Sử dụng open và onOpenChange để quản lý trạng thái đóng mở bằng React state."
773
- codeString={`<div className="w-full flex flex-col gap-4 items-center justify-center">
744
+ <ShowcaseExample title="Controlled State" description="Sử dụng open và onOpenChange để quản lý trạng thái đóng mở bằng React state." code={`<div className="w-full flex flex-col gap-4 items-center justify-center">
774
745
  <div className="flex gap-4 items-center">
775
746
  <Button
776
747
  onClick={() => setControlledOpen(true)}
@@ -823,67 +794,65 @@ function DialogMicroShowcase({ globalSize }: { globalSize: Size }) {
823
794
  </DialogContent>
824
795
 
825
796
  </Dialog>
826
- </div>`}
827
- >
828
- <div className="w-full flex flex-col gap-4 items-center justify-center">
829
- <div className="flex gap-4 items-center">
830
- <Button
831
- onClick={() => setControlledOpen(true)}
832
- variant="outline"
833
- size={globalSize}
834
- >
835
- Open Controlled Dialog
836
- </Button>
837
- <span className="text-sm text-muted-foreground font-mono">
838
- State: {controlledOpen ? "true" : "false"}
839
- </span>
840
- </div>
797
+ </div>`} preview={
798
+ <>
799
+ <div className="w-full flex flex-col gap-4 items-center justify-center">
800
+ <div className="flex gap-4 items-center">
801
+ <Button
802
+ onClick={() => setControlledOpen(true)}
803
+ variant="outline"
804
+ size={globalSize}
805
+ >
806
+ Open Controlled Dialog
807
+ </Button>
808
+ <span className="text-sm text-muted-foreground font-mono">
809
+ State: {controlledOpen ? "true" : "false"}
810
+ </span>
811
+ </div>
841
812
 
842
- <Dialog open={controlledOpen} onOpenChange={setControlledOpen}>
843
-
844
- <DialogContent className={contentClass}>
845
- <DialogHeader>
846
- <DialogTitle>Controlled Dialog</DialogTitle>
847
- <DialogDescription>
848
- Trạng thái của dialog này được quản lý hoàn toàn bởi React
849
- state bên ngoài.
850
- </DialogDescription>
851
- </DialogHeader>
852
- <p className="text-sm text-foreground">
853
- Bạn có thể đóng bằng nút bên dưới hoặc dấu X.
854
- </p>
855
- <DialogFooter className="-mx-4 -mb-4 mt-4 rounded-b-xl border-t border-t-border bg-muted/50 p-4">
856
- <Button
857
- color="primary"
858
- onClick={() => setControlledOpen(false)}
859
- size={globalSize}
860
- >
861
- Close Manually
862
- </Button>
863
- </DialogFooter>
864
- <DialogClose
865
- render={
866
- <Button
867
- variant="ghost"
868
- className="absolute top-2 right-2"
869
- size="sm"
870
- iconOnly
871
- />
872
- }
873
- >
874
- <XIcon />
875
- <span className="sr-only">Close</span>
876
- </DialogClose>
877
- </DialogContent>
878
-
879
- </Dialog>
880
- </div>
881
- </ExampleSection>
813
+ <Dialog open={controlledOpen} onOpenChange={setControlledOpen}>
814
+
815
+ <DialogContent className={contentClass}>
816
+ <DialogHeader>
817
+ <DialogTitle>Controlled Dialog</DialogTitle>
818
+ <DialogDescription>
819
+ Trạng thái của dialog này được quản lý hoàn toàn bởi React
820
+ state bên ngoài.
821
+ </DialogDescription>
822
+ </DialogHeader>
823
+ <p className="text-sm text-foreground">
824
+ Bạn có thể đóng bằng nút bên dưới hoặc dấu X.
825
+ </p>
826
+ <DialogFooter className="-mx-4 -mb-4 mt-4 rounded-b-xl border-t border-t-border bg-muted/50 p-4">
827
+ <Button
828
+ color="primary"
829
+ onClick={() => setControlledOpen(false)}
830
+ size={globalSize}
831
+ >
832
+ Close Manually
833
+ </Button>
834
+ </DialogFooter>
835
+ <DialogClose
836
+ render={
837
+ <Button
838
+ variant="ghost"
839
+ className="absolute top-2 right-2"
840
+ size="sm"
841
+ iconOnly
842
+ />
843
+ }
844
+ >
845
+ <XIcon />
846
+ <span className="sr-only">Close</span>
847
+ </DialogClose>
848
+ </DialogContent>
849
+
850
+ </Dialog>
851
+ </div>
852
+ </>
853
+ } />
882
854
 
883
- <ExampleSection
884
- label="Sticky Footer (Long Content)"
885
- description="Ghi đè class của DialogContent thành flex-col để khóa scroll ở phần body."
886
- codeString={`<Dialog>
855
+ <ShowcaseExample title="Sticky Footer (Long Content)" description="Ghi đè class của DialogContent thành flex-col để khóa scroll ở phần body." code={`<Dialog>
887
856
  <DialogTrigger
888
857
  render={
889
858
  <Button variant="outline">View Long Content</Button>
@@ -897,7 +866,7 @@ function DialogMicroShowcase({ globalSize }: { globalSize: Size }) {
897
866
  )}
898
867
  >
899
868
  <DialogHeader className="shrink-0 p-4 pb-0">
900
- <DialogTitle>Terms & Conditions</DialogTitle>
869
+ <DialogTitle>Điều khoản & Điều kiện</DialogTitle>
901
870
  <DialogDescription>
902
871
  Cuộn xuống dưới cùng để có thể đồng ý với điều
903
872
  khoản.
@@ -923,7 +892,7 @@ function DialogMicroShowcase({ globalSize }: { globalSize: Size }) {
923
892
  <DialogClose render={<Button variant="ghost" />}>
924
893
  Cancel
925
894
  </DialogClose>
926
- <Button>I Agree</Button>
895
+ <Button>Tôi đồng ý</Button>
927
896
  </DialogFooter>
928
897
  <DialogClose
929
898
  render={
@@ -940,77 +909,73 @@ function DialogMicroShowcase({ globalSize }: { globalSize: Size }) {
940
909
  </DialogClose>
941
910
  </DialogContent>
942
911
 
943
- </Dialog>`}
944
- >
945
- <Dialog>
946
- <DialogTrigger
947
- render={
948
- <Button variant="outline" size={globalSize}>
949
- View Long Content
950
- </Button>
951
- }
952
- />
912
+ </Dialog>`} preview={
913
+ <>
914
+ <Dialog>
915
+ <DialogTrigger
916
+ render={
917
+ <Button variant="outline" size={globalSize}>
918
+ View Long Content
919
+ </Button>
920
+ }
921
+ />
953
922
 
954
- <DialogContent
955
- className={cn(
956
- contentClass,
957
- "flex flex-col gap-0 p-0 overflow-hidden",
958
- )}
959
- >
960
- <DialogHeader className="shrink-0 p-4 pb-0">
961
- <DialogTitle>Terms & Conditions</DialogTitle>
962
- <DialogDescription>
963
- Cuộn xuống dưới cùng để có thể đồng ý với điều khoản.
964
- </DialogDescription>
965
- </DialogHeader>
966
- <div className="flex-1 min-h-0 overflow-y-auto p-4">
967
- <div className="flex h-[800px] flex-col items-center justify-between rounded-md border border-border border-dashed bg-muted/20 py-8">
968
- <span className="text-sm font-medium text-muted-foreground">
969
- START OF CONTENT
970
- </span>
971
- <div className="flex flex-col items-center gap-2">
972
- <span className="text-4xl">👇</span>
973
- <span className="text-sm text-muted-foreground">
974
- Keep scrolling
975
- </span>
976
- </div>
977
- <span className="text-sm font-medium text-muted-foreground">
978
- END OF CONTENT
979
- </span>
980
- </div>
981
- </div>
982
- <DialogFooter className="shrink-0 rounded-b-xl border-t border-t-border bg-muted/50 p-4">
983
- <DialogClose
984
- render={<Button variant="ghost" size={globalSize} />}
985
- >
986
- Cancel
987
- </DialogClose>
988
- <Button size={globalSize}>I Agree</Button>
989
- </DialogFooter>
990
- <DialogClose
991
- render={
992
- <Button
993
- variant="ghost"
994
- className="absolute top-2 right-2"
995
- size="sm"
996
- iconOnly
997
- />
998
- }
999
- >
1000
- <XIcon />
1001
- <span className="sr-only">Close</span>
1002
- </DialogClose>
1003
- </DialogContent>
1004
-
1005
- </Dialog>
1006
- </ExampleSection>
923
+ <DialogContent
924
+ className={cn(
925
+ contentClass,
926
+ "flex flex-col gap-0 p-0 overflow-hidden",
927
+ )}
928
+ >
929
+ <DialogHeader className="shrink-0 p-4 pb-0">
930
+ <DialogTitle>Điều khoản & Điều kiện</DialogTitle>
931
+ <DialogDescription>
932
+ Cuộn xuống dưới cùng để có thể đồng ý với điều khoản.
933
+ </DialogDescription>
934
+ </DialogHeader>
935
+ <div className="flex-1 min-h-0 overflow-y-auto p-4">
936
+ <div className="flex h-[800px] flex-col items-center justify-between rounded-md border border-border border-dashed bg-muted/20 py-8">
937
+ <span className="text-sm font-medium text-muted-foreground">
938
+ START OF CONTENT
939
+ </span>
940
+ <div className="flex flex-col items-center gap-2">
941
+ <span className="text-4xl">👇</span>
942
+ <span className="text-sm text-muted-foreground">
943
+ Keep scrolling
944
+ </span>
945
+ </div>
946
+ <span className="text-sm font-medium text-muted-foreground">
947
+ END OF CONTENT
948
+ </span>
949
+ </div>
950
+ </div>
951
+ <DialogFooter className="shrink-0 rounded-b-xl border-t border-t-border bg-muted/50 p-4">
952
+ <DialogClose
953
+ render={<Button variant="ghost" size={globalSize} />}
954
+ >
955
+ Cancel
956
+ </DialogClose>
957
+ <Button size={globalSize}>Tôi đồng ý</Button>
958
+ </DialogFooter>
959
+ <DialogClose
960
+ render={
961
+ <Button
962
+ variant="ghost"
963
+ className="absolute top-2 right-2"
964
+ size="sm"
965
+ iconOnly
966
+ />
967
+ }
968
+ >
969
+ <XIcon />
970
+ <span className="sr-only">Close</span>
971
+ </DialogClose>
972
+ </DialogContent>
973
+
974
+ </Dialog>
975
+ </>
976
+ } />
1007
977
 
1008
- {/* ── Use Case Comparison ─────────────────────── */}
1009
- <ExampleSection
1010
- label="🧭 Use Case Comparison"
1011
- description="Các kịch bản thực tế giúp bạn quyết định nên dùng Micro hay Macro."
1012
- fullWidth
1013
- codeString={`<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
978
+ <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">
1014
979
  {/* ── Story 1: Macro wins ── */}
1015
980
  <div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
1016
981
  <div className="flex items-start gap-3">
@@ -1061,77 +1026,67 @@ function DialogMicroShowcase({ globalSize }: { globalSize: Size }) {
1061
1026
  từng phần.
1062
1027
  </p>
1063
1028
  </div>
1064
- </div>`}
1065
- >
1066
- <div className="grid grid-cols-1 gap-6 md:grid-cols-2">
1067
- {/* ── Story 1: Macro wins ── */}
1068
- <div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
1069
- <div className="flex items-start gap-3">
1070
- <span className="mt-0.5 shrink-0 rounded-full bg-green-500/10 p-1.5 text-green-600">
1071
- <CheckCircle2Icon className="size-4" aria-hidden="true" />
1072
- </span>
1073
- <div>
1074
- <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
1075
- Story 1 · Dùng Macro
1076
- </p>
1077
- <h3 className="mt-0.5 text-sm font-semibold text-foreground">
1078
- Cảnh báo hoặc Form cơ bản
1079
- </h3>
1080
- </div>
1081
- </div>
1082
- <p className="text-xs text-muted-foreground leading-relaxed">
1083
- Khi bạn chỉ cần một tiêu đề, tả vài nút bấm ở footer (hoặc
1084
- 1 form ngắn), Macro giúp bạn không phải khai báo hàng loạt
1085
- component con.
1086
- </p>
1087
- </div>
1029
+ </div>`} preview={
1030
+ <>
1031
+ <div className="grid grid-cols-1 gap-6 md:grid-cols-2">
1032
+ <div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
1033
+ <div className="flex items-start gap-3">
1034
+ <span className="mt-0.5 shrink-0 rounded-full bg-green-500/10 p-1.5 text-green-600">
1035
+ <CheckCircle2Icon className="size-4" aria-hidden="true" />
1036
+ </span>
1037
+ <div>
1038
+ <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
1039
+ Story 1 · Dùng Macro
1040
+ </p>
1041
+ <h3 className="mt-0.5 text-sm font-semibold text-foreground">
1042
+ Cảnh báo hoặc Form cơ bản
1043
+ </h3>
1044
+ </div>
1045
+ </div>
1046
+ <p className="text-xs text-muted-foreground leading-relaxed">
1047
+ Khi bạn chỉ cần một tiêu đề, mô tả và vài nút bấm ở footer (hoặc
1048
+ 1 form ngắn), Macro giúp bạn không phải khai báo hàng loạt
1049
+ component con.
1050
+ </p>
1051
+ </div>
1088
1052
 
1089
- {/* ── Story 2: Micro wins ── */}
1090
- <div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
1091
- <div className="flex items-start gap-3">
1092
- <span className="mt-0.5 shrink-0 rounded-full bg-blue-500/10 p-1.5 text-blue-600">
1093
- <LayersIcon className="size-4" aria-hidden="true" />
1094
- </span>
1095
- <div>
1096
- <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
1097
- Story 2 · Dùng Micro
1098
- </p>
1099
- <h3 className="mt-0.5 text-sm font-semibold text-foreground">
1100
- Layout tuỳ chỉnh phức tạp
1101
- </h3>
1102
- </div>
1103
- </div>
1104
- <p className="text-xs text-muted-foreground leading-relaxed">
1105
- Khi bạn muốn Header hình ảnh/icon đặc biệt, bỏ qua Footer
1106
- chuẩn, hoặc layout split-pane phức tạp bên trong Dialog.
1107
- Micro cho phép bạn tự do thay đổi từng phần.
1108
- </p>
1109
- </div>
1110
- </div>
1111
- </ExampleSection>
1053
+ <div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
1054
+ <div className="flex items-start gap-3">
1055
+ <span className="mt-0.5 shrink-0 rounded-full bg-blue-500/10 p-1.5 text-blue-600">
1056
+ <LayersIcon className="size-4" aria-hidden="true" />
1057
+ </span>
1058
+ <div>
1059
+ <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
1060
+ Story 2 · Dùng Micro
1061
+ </p>
1062
+ <h3 className="mt-0.5 text-sm font-semibold text-foreground">
1063
+ Layout tuỳ chỉnh phức tạp
1064
+ </h3>
1065
+ </div>
1066
+ </div>
1067
+ <p className="text-xs text-muted-foreground leading-relaxed">
1068
+ Khi bạn muốn Header có hình ảnh/icon đặc biệt, bỏ qua Footer
1069
+ chuẩn, hoặclayout split-pane phức tạp bên trong Dialog.
1070
+ Micro cho phép bạn tự do thay đổi từng phần.
1071
+ </p>
1072
+ </div>
1073
+ </div>
1074
+ </>
1075
+ } />
1112
1076
  </ExampleGrid>
1113
1077
  </div>
1114
1078
  );
1115
1079
  }
1116
1080
 
1117
- // ──────────────────────────────────────────────────────────
1118
- // Main Showcase
1119
- // ──────────────────────────────────────────────────────────
1120
1081
  export default function DialogShowcase() {
1121
1082
  const { size: globalSize } = useDevContext();
1122
1083
  return (
1123
1084
  <Showcase
1124
1085
  title="Dialog"
1125
1086
  description="Một cửa sổ phương thức làm gián đoạn người dùng với nội dung quan trọng và mong đợi phản hồi."
1126
- tabs={[
1127
- {
1128
- label: "Micro (Primitive)",
1129
- content: <DialogMicroShowcase globalSize={globalSize} /> },
1130
- {
1131
- label: "Macro (Preset)",
1132
- content: <DialogMacroShowcase globalSize={globalSize} /> },
1133
- ]}
1134
- generalConcept={
1087
+ micro={{ content: <DialogMicroShowcase globalSize={globalSize} /> }}
1088
+ macro={{ content: <DialogMacroShowcase globalSize={globalSize} /> }}
1089
+ guideline={
1135
1090
  <ShowcaseDocs>
1136
1091
  <DocsH3>Cấu trúc và Định tuyến</DocsH3>
1137
1092
  <DocsP>