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
@@ -29,7 +29,7 @@ import { Progress } from "../../components/micro/progress";
29
29
  import { Skeleton } from "../../components/micro/skeleton";
30
30
  import { Toaster } from "../../components/micro/sonner";
31
31
  import { Spinner } from "../../components/micro/spinner";
32
- import { SectionHeader, ShowcaseBlock } from "../../dev/components/showcase";
32
+ import { SectionHeader, ShowcaseExample } from "../../dev/components/showcase";
33
33
 
34
34
  export default function FeedbackSection() {
35
35
  const [progress1, setProgress1] = useState(25);
@@ -43,334 +43,324 @@ export default function FeedbackSection() {
43
43
  description="Alert, Progress, Skeleton, Spinner, Sonner, Empty"
44
44
  />
45
45
 
46
- {/* Toaster provider for this section */}
47
46
  <Toaster position="bottom-right" />
48
47
 
49
- {/* ── Alert ── */}
50
- <ShowcaseBlock title="Alert">
51
- <div className="space-y-3">
52
- <Alert color="info">
53
- <InfoIcon />
54
- <AlertTitle>Info</AlertTitle>
55
- <AlertDescription>
56
- Your session will expire in 10 minutes.
57
- </AlertDescription>
58
- </Alert>
59
- <Alert color="success">
60
- <CheckCircle2Icon />
61
- <AlertTitle>Success</AlertTitle>
62
- <AlertDescription>
63
- Your changes have been saved successfully.
64
- </AlertDescription>
65
- </Alert>
66
- <Alert color="warning">
67
- <TriangleAlertIcon />
68
- <AlertTitle>Warning</AlertTitle>
69
- <AlertDescription>
70
- This action cannot be undone easily.
71
- </AlertDescription>
72
- </Alert>
73
- <Alert color="destructive">
74
- <XCircleIcon />
75
- <AlertTitle>Error</AlertTitle>
76
- <AlertDescription>
77
- Failed to connect to the server.
78
- </AlertDescription>
79
- </Alert>
80
- </div>
81
- </ShowcaseBlock>
48
+ <ShowcaseExample title="Alert" preview={<>
49
+ <div className="space-y-3">
50
+ <Alert color="info">
51
+ <InfoIcon />
52
+ <AlertTitle>Info</AlertTitle>
53
+ <AlertDescription>
54
+ Phiên đăng nhập của bạn sẽ hết hạn sau 10 phút.
55
+ </AlertDescription>
56
+ </Alert>
57
+ <Alert color="success">
58
+ <CheckCircle2Icon />
59
+ <AlertTitle>Success</AlertTitle>
60
+ <AlertDescription>
61
+ Các thay đổi đã được lưu thành công.
62
+ </AlertDescription>
63
+ </Alert>
64
+ <Alert color="warning">
65
+ <TriangleAlertIcon />
66
+ <AlertTitle>Warning</AlertTitle>
67
+ <AlertDescription>
68
+ Hành động này không thể hoàn tác đâu nhé.
69
+ </AlertDescription>
70
+ </Alert>
71
+ <Alert color="destructive">
72
+ <XCircleIcon />
73
+ <AlertTitle>Error</AlertTitle>
74
+ <AlertDescription>
75
+ Lỗi kết nối đến máy chủ.
76
+ </AlertDescription>
77
+ </Alert>
78
+ </div>
79
+ </>} />
82
80
 
83
81
  <div className="grid gap-5 sm:grid-cols-2">
84
- {/* ── Progress ── */}
85
- <ShowcaseBlock title="Progress">
86
- <div className="space-y-4">
87
- <Progress value={progress1} size="sm" />
88
- <Progress value={progress2} size="md" />
89
- <Progress value={progress3} size="lg" />
90
- <div className="flex gap-2 pt-1">
91
- <Button
92
- size="sm"
93
- variant="outline"
94
- onClick={() => {
95
- setProgress1(Math.max(0, progress1 - 10));
96
- setProgress2(Math.max(0, progress2 - 10));
97
- setProgress3(Math.max(0, progress3 - 10));
98
- }}
99
- >
100
- − 10%
101
- </Button>
102
- <Button
103
- size="sm"
104
- variant="outline"
105
- onClick={() => {
106
- setProgress1(Math.min(100, progress1 + 10));
107
- setProgress2(Math.min(100, progress2 + 10));
108
- setProgress3(Math.min(100, progress3 + 10));
109
- }}
110
- >
111
- + 10%
112
- </Button>
113
- </div>
114
- </div>
115
- </ShowcaseBlock>
82
+ <ShowcaseExample title="Progress" preview={<>
83
+ <div className="space-y-4">
84
+ <Progress value={progress1} size="sm" />
85
+ <Progress value={progress2} size="md" />
86
+ <Progress value={progress3} size="lg" />
87
+ <div className="flex gap-2 pt-1">
88
+ <Button
89
+ size="sm"
90
+ variant="outline"
91
+ onClick={() => {
92
+ setProgress1(Math.max(0, progress1 - 10));
93
+ setProgress2(Math.max(0, progress2 - 10));
94
+ setProgress3(Math.max(0, progress3 - 10));
95
+ }}
96
+ >
97
+ − 10%
98
+ </Button>
99
+ <Button
100
+ size="sm"
101
+ variant="outline"
102
+ onClick={() => {
103
+ setProgress1(Math.min(100, progress1 + 10));
104
+ setProgress2(Math.min(100, progress2 + 10));
105
+ setProgress3(Math.min(100, progress3 + 10));
106
+ }}
107
+ >
108
+ + 10%
109
+ </Button>
110
+ </div>
111
+ </div>
112
+ </>} />
116
113
 
117
- {/* ── Skeleton ── */}
118
- <ShowcaseBlock title="Skeleton">
119
- <div className="space-y-3">
120
- <div className="flex items-center gap-3">
121
- <Skeleton className="size-10 rounded-full" />
122
- <div className="space-y-2 flex-1">
123
- <Skeleton className="h-3.5 w-1/3" />
124
- <Skeleton className="h-3 w-1/2" />
125
- </div>
126
- </div>
127
- <Skeleton className="h-28 w-full rounded-lg" />
128
- <div className="space-y-2">
129
- <Skeleton className="h-3 w-full" />
130
- <Skeleton className="h-3 w-5/6" />
131
- <Skeleton className="h-3 w-4/6" />
132
- </div>
133
- </div>
134
- </ShowcaseBlock>
114
+ <ShowcaseExample title="Skeleton" preview={<>
115
+ <div className="space-y-3">
116
+ <div className="flex items-center gap-3">
117
+ <Skeleton className="size-10 rounded-full" />
118
+ <div className="space-y-2 flex-1">
119
+ <Skeleton className="h-3.5 w-1/3" />
120
+ <Skeleton className="h-3 w-1/2" />
121
+ </div>
122
+ </div>
123
+ <Skeleton className="h-28 w-full rounded-lg" />
124
+ <div className="space-y-2">
125
+ <Skeleton className="h-3 w-full" />
126
+ <Skeleton className="h-3 w-5/6" />
127
+ <Skeleton className="h-3 w-4/6" />
128
+ </div>
129
+ </div>
130
+ </>} />
135
131
  </div>
136
132
 
137
133
  <div className="grid gap-5 sm:grid-cols-2">
138
- {/* ── Spinner ── */}
139
- <ShowcaseBlock title="Spinner">
140
- <div className="space-y-4">
141
- <div className="flex items-center gap-6">
142
- <div className="flex flex-col items-center gap-2">
143
- <Spinner size="sm" />
144
- <span className="text-xs text-muted-foreground">sm</span>
145
- </div>
146
- <div className="flex flex-col items-center gap-2">
147
- <Spinner size="md" />
148
- <span className="text-xs text-muted-foreground">md</span>
149
- </div>
150
- <div className="flex flex-col items-center gap-2">
151
- <Spinner size="lg" />
152
- <span className="text-xs text-muted-foreground">lg</span>
153
- </div>
154
- <div className="flex flex-col items-center gap-2">
155
- <Spinner className="size-8 text-primary" />
156
- <span className="text-xs text-muted-foreground">custom</span>
157
- </div>
158
- </div>
159
- <div className="flex items-center gap-3">
160
- <Button size="sm" disabled variant="outline">
161
- <Spinner size="sm" />
162
- Loading…
163
- </Button>
164
- <Button size="md" variant="outline" disabled>
165
- <Spinner size="md" />
166
- Please wait
167
- </Button>
168
- <Button size="lg" variant="outline" disabled>
169
- <Spinner size="lg" />
170
- Processing
171
- </Button>
172
- </div>
173
- </div>
174
- </ShowcaseBlock>
134
+ <ShowcaseExample title="Spinner" preview={<>
135
+ <div className="space-y-4">
136
+ <div className="flex items-center gap-6">
137
+ <div className="flex flex-col items-center gap-2">
138
+ <Spinner size="sm" />
139
+ <span className="text-xs text-muted-foreground">sm</span>
140
+ </div>
141
+ <div className="flex flex-col items-center gap-2">
142
+ <Spinner size="md" />
143
+ <span className="text-xs text-muted-foreground">md</span>
144
+ </div>
145
+ <div className="flex flex-col items-center gap-2">
146
+ <Spinner size="lg" />
147
+ <span className="text-xs text-muted-foreground">lg</span>
148
+ </div>
149
+ <div className="flex flex-col items-center gap-2">
150
+ <Spinner className="size-8 text-primary" />
151
+ <span className="text-xs text-muted-foreground">custom</span>
152
+ </div>
153
+ </div>
154
+ <div className="flex items-center gap-3">
155
+ <Button size="sm" disabled variant="outline">
156
+ <Spinner size="sm" />
157
+ Loading…
158
+ </Button>
159
+ <Button size="md" variant="outline" disabled>
160
+ <Spinner size="md" />
161
+ Please wait
162
+ </Button>
163
+ <Button size="lg" variant="outline" disabled>
164
+ <Spinner size="lg" />
165
+ Processing
166
+ </Button>
167
+ </div>
168
+ </div>
169
+ </>} />
175
170
 
176
- {/* ── Sonner (Toast) ── */}
177
- <ShowcaseBlock title="Sonner (Toast)">
178
- <div className="space-y-6">
179
- {/* States */}
180
- <div className="space-y-3">
181
- <div>
182
- <h4 className="text-sm font-medium">States</h4>
183
- <p className="text-xs text-muted-foreground">
184
- Basic toast variations for different intents.
185
- </p>
186
- </div>
187
- <div className="flex flex-wrap gap-2">
188
- <Button
189
- size="sm"
190
- variant="outline"
191
- onClick={() => toast("Event has been created")}
192
- >
193
- Default
194
- </Button>
195
- <Button
196
- size="sm"
197
- variant="outline"
198
- color="success"
199
- onClick={() => toast.success("Changes saved successfully")}
200
- >
201
- Success
202
- </Button>
203
- <Button
204
- size="sm"
205
- variant="outline"
206
- color="info"
207
- onClick={() => toast.info("Session expires in 10 minutes")}
208
- >
209
- Info
210
- </Button>
211
- <Button
212
- size="sm"
213
- variant="outline"
214
- color="warning"
215
- onClick={() => toast.warning("Disk space running low")}
216
- >
217
- Warning
218
- </Button>
219
- <Button
220
- size="sm"
221
- variant="outline"
222
- color="destructive"
223
- onClick={() => toast.error("Failed to save changes")}
224
- >
225
- Error
226
- </Button>
227
- </div>
228
- </div>
171
+ <ShowcaseExample title="Sonner (Toast)" preview={<>
172
+ <div className="space-y-6">
173
+ <div className="space-y-3">
174
+ <div>
175
+ <h4 className="text-sm font-medium">States</h4>
176
+ <p className="text-xs text-muted-foreground">
177
+ Các loại toast cơ bản.
178
+ </p>
179
+ </div>
180
+ <div className="flex flex-wrap gap-2">
181
+ <Button
182
+ size="sm"
183
+ variant="outline"
184
+ onClick={() => toast("Sự kiện đã được tạo")}
185
+ >
186
+ Default
187
+ </Button>
188
+ <Button
189
+ size="sm"
190
+ variant="outline"
191
+ color="success"
192
+ onClick={() => toast.success("Lưu thay đổi thành công")}
193
+ >
194
+ Success
195
+ </Button>
196
+ <Button
197
+ size="sm"
198
+ variant="outline"
199
+ color="info"
200
+ onClick={() => toast.info("Hết hạn phiên sau 10 phút")}
201
+ >
202
+ Info
203
+ </Button>
204
+ <Button
205
+ size="sm"
206
+ variant="outline"
207
+ color="warning"
208
+ onClick={() => toast.warning("Sắp hết dung lượng lưu trữ")}
209
+ >
210
+ Warning
211
+ </Button>
212
+ <Button
213
+ size="sm"
214
+ variant="outline"
215
+ color="destructive"
216
+ onClick={() => toast.error("Lưu thay đổi thất bại")}
217
+ >
218
+ Error
219
+ </Button>
220
+ </div>
221
+ </div>
229
222
 
230
- {/* Interactivity */}
231
- <div className="space-y-3">
232
- <div>
233
- <h4 className="text-sm font-medium">Interactivity</h4>
234
- <p className="text-xs text-muted-foreground">
235
- Toasts with actions, cancel options, or explicit close
236
- buttons.
237
- </p>
238
- </div>
239
- <div className="flex flex-wrap gap-2">
240
- <Button
241
- size="sm"
242
- variant="outline"
243
- onClick={() =>
244
- toast("You can close this toast manually", {
245
- closeButton: true,
246
- })
247
- }
248
- >
249
- With Close Button
250
- </Button>
251
- <Button
252
- size="sm"
253
- variant="outline"
254
- onClick={() =>
255
- toast("File uploaded", {
256
- description:
257
- "image.png has been uploaded to your gallery.",
258
- action: { label: "View", onClick: () => {} },
259
- })
260
- }
261
- >
262
- With Action
263
- </Button>
264
- <Button
265
- size="sm"
266
- variant="outline"
267
- onClick={() =>
268
- toast("Confirm deletion", {
269
- description: "Are you sure you want to delete this file?",
270
- action: {
271
- label: "Delete",
272
- onClick: () => toast.error("File deleted"),
273
- },
274
- cancel: {
275
- label: "Cancel",
276
- onClick: () => toast.info("Action cancelled"),
277
- },
278
- })
279
- }
280
- >
281
- With Cancel
282
- </Button>
283
- </div>
284
- </div>
223
+ <div className="space-y-3">
224
+ <div>
225
+ <h4 className="text-sm font-medium">Interactivity</h4>
226
+ <p className="text-xs text-muted-foreground">
227
+ Toasts with actions, cancel options, or explicit close
228
+ buttons.
229
+ </p>
230
+ </div>
231
+ <div className="flex flex-wrap gap-2">
232
+ <Button
233
+ size="sm"
234
+ variant="outline"
235
+ onClick={() =>
236
+ toast("Bạn có thể tự đóng toast này", {
237
+ closeButton: true,
238
+ })
239
+ }
240
+ >
241
+ With Close Button
242
+ </Button>
243
+ <Button
244
+ size="sm"
245
+ variant="outline"
246
+ onClick={() =>
247
+ toast("Đã tải file lên", {
248
+ description:
249
+ "image.png has been uploaded to your gallery.",
250
+ action: { label: "View", onClick: () => {} },
251
+ })
252
+ }
253
+ >
254
+ With Action
255
+ </Button>
256
+ <Button
257
+ size="sm"
258
+ variant="outline"
259
+ onClick={() =>
260
+ toast("Xác nhận xoá", {
261
+ description: "Are you sure you want to delete this file?",
262
+ action: {
263
+ label: "Delete",
264
+ onClick: () => toast.error("Đã xoá file"),
265
+ },
266
+ cancel: {
267
+ label: "Cancel",
268
+ onClick: () => toast.info("Đã huỷ hành động"),
269
+ },
270
+ })
271
+ }
272
+ >
273
+ With Cancel
274
+ </Button>
275
+ </div>
276
+ </div>
285
277
 
286
- {/* Advanced */}
287
- <div className="space-y-3">
288
- <div>
289
- <h4 className="text-sm font-medium">Advanced</h4>
290
- <p className="text-xs text-muted-foreground">
291
- Promises and custom positions.
292
- </p>
293
- </div>
294
- <div className="flex flex-wrap gap-2">
295
- <Button
296
- size="sm"
297
- variant="outline"
298
- onClick={() => {
299
- const promise = new Promise((resolve) =>
300
- setTimeout(resolve, 2000),
301
- );
302
- toast.promise(promise, {
303
- loading: "Loading data...",
304
- success: "Data loaded successfully",
305
- error: "Failed to load data",
306
- });
307
- }}
308
- >
309
- Promise
310
- </Button>
311
- <Button
312
- size="sm"
313
- variant="outline"
314
- onClick={() =>
315
- toast("Top Center Toast", { position: "top-center" })
316
- }
317
- >
318
- Top Center Position
319
- </Button>
320
- </div>
321
- </div>
322
- </div>
323
- </ShowcaseBlock>
278
+ <div className="space-y-3">
279
+ <div>
280
+ <h4 className="text-sm font-medium">Advanced</h4>
281
+ <p className="text-xs text-muted-foreground">
282
+ Promises and custom positions.
283
+ </p>
284
+ </div>
285
+ <div className="flex flex-wrap gap-2">
286
+ <Button
287
+ size="sm"
288
+ variant="outline"
289
+ onClick={() => {
290
+ const promise = new Promise((resolve) =>
291
+ setTimeout(resolve, 2000),
292
+ );
293
+ toast.promise(promise, {
294
+ loading: "Loading data...",
295
+ success: "Data loaded successfully",
296
+ error: "Failed to load data",
297
+ });
298
+ }}
299
+ >
300
+ Promise
301
+ </Button>
302
+ <Button
303
+ size="sm"
304
+ variant="outline"
305
+ onClick={() =>
306
+ toast("Toast ở giữa phía trên", { position: "top-center" })
307
+ }
308
+ >
309
+ Top Center Position
310
+ </Button>
311
+ </div>
312
+ </div>
313
+ </div>
314
+ </>} />
324
315
  </div>
325
316
 
326
- {/* ── Empty ── */}
327
- <ShowcaseBlock title="Empty">
328
- <div className="grid gap-5 sm:grid-cols-3">
329
- <Empty className="border border-border">
330
- <EmptyHeader>
331
- <EmptyMedia variant="icon">
332
- <InboxIcon />
333
- </EmptyMedia>
334
- <EmptyTitle>No messages</EmptyTitle>
335
- <EmptyDescription>
336
- Your inbox is empty. New messages will appear here.
337
- </EmptyDescription>
338
- </EmptyHeader>
339
- </Empty>
317
+ <ShowcaseExample title="Empty" preview={<>
318
+ <div className="grid gap-5 sm:grid-cols-3">
319
+ <Empty className="border border-border">
320
+ <EmptyHeader>
321
+ <EmptyMedia variant="icon">
322
+ <InboxIcon />
323
+ </EmptyMedia>
324
+ <EmptyTitle>No messages</EmptyTitle>
325
+ <EmptyDescription>
326
+ Your inbox is empty. New messages will appear here.
327
+ </EmptyDescription>
328
+ </EmptyHeader>
329
+ </Empty>
340
330
 
341
- <Empty className="border border-border">
342
- <EmptyHeader>
343
- <EmptyMedia variant="icon">
344
- <SearchIcon />
345
- </EmptyMedia>
346
- <EmptyTitle>No results found</EmptyTitle>
347
- <EmptyDescription>
348
- Try adjusting your search or filter criteria.
349
- </EmptyDescription>
350
- </EmptyHeader>
351
- <EmptyContent>
352
- <Button size="sm" variant="outline">
353
- Clear filters
354
- </Button>
355
- </EmptyContent>
356
- </Empty>
331
+ <Empty className="border border-border">
332
+ <EmptyHeader>
333
+ <EmptyMedia variant="icon">
334
+ <SearchIcon />
335
+ </EmptyMedia>
336
+ <EmptyTitle>No results found</EmptyTitle>
337
+ <EmptyDescription>
338
+ Try adjusting your search or filter criteria.
339
+ </EmptyDescription>
340
+ </EmptyHeader>
341
+ <EmptyContent>
342
+ <Button size="sm" variant="outline">
343
+ Clear filters
344
+ </Button>
345
+ </EmptyContent>
346
+ </Empty>
357
347
 
358
- <Empty className="border border-border">
359
- <EmptyHeader>
360
- <EmptyMedia variant="icon">
361
- <FileX2Icon />
362
- </EmptyMedia>
363
- <EmptyTitle>No documents</EmptyTitle>
364
- <EmptyDescription>
365
- Get started by creating your first document.
366
- </EmptyDescription>
367
- </EmptyHeader>
368
- <EmptyContent>
369
- <Button size="sm">Create document</Button>
370
- </EmptyContent>
371
- </Empty>
372
- </div>
373
- </ShowcaseBlock>
348
+ <Empty className="border border-border">
349
+ <EmptyHeader>
350
+ <EmptyMedia variant="icon">
351
+ <FileX2Icon />
352
+ </EmptyMedia>
353
+ <EmptyTitle>No documents</EmptyTitle>
354
+ <EmptyDescription>
355
+ Get started by creating your first document.
356
+ </EmptyDescription>
357
+ </EmptyHeader>
358
+ <EmptyContent>
359
+ <Button size="sm">Create document</Button>
360
+ </EmptyContent>
361
+ </Empty>
362
+ </div>
363
+ </>} />
374
364
  </div>
375
365
  );
376
366
  }