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
@@ -19,15 +19,12 @@ import { useDevContext } from "../../dev/components/dev-context";
19
19
  import {
20
20
  DocsP,
21
21
  ExampleGrid,
22
- ExampleSection,
22
+ ShowcaseExample,
23
23
  Showcase,
24
24
  ShowcaseDocs
25
25
  } from "../../dev/components/showcase";
26
26
  import { type Size } from "../../lib/types";
27
27
 
28
- // ──────────────────────────────────────────────────────────
29
- // RHF Form Demo (Macro)
30
- // ──────────────────────────────────────────────────────────
31
28
  const formSchema = z.object({
32
29
  mobile: z.boolean().default(false).optional() });
33
30
  type FormValues = z.infer<typeof formSchema>;
@@ -90,62 +87,52 @@ function CheckboxForm({ size }: { size: Size }) {
90
87
  />
91
88
  )}
92
89
  />
93
- <Button type="submit" size={size}>Submit</Button>
90
+ <Button type="submit" size={size}>Xác nhận</Button>
94
91
  </form>
95
92
  );
96
93
  }`;
97
94
 
98
- // ──────────────────────────────────────────────────────────
99
- // SECTION 1: Macro Content
100
- // ──────────────────────────────────────────────────────────
101
95
  function CheckboxMacroShowcase({ globalSize }: { globalSize: Size }) {
102
96
  const [checked, setChecked] = useState(false);
103
97
 
104
98
  return (
105
- <div className="space-y-10 mt-6">
99
+ <div className="space-y-10">
106
100
  <ExampleGrid>
107
- <ExampleSection
108
- label="Tiêu chuẩn"
109
- description="Checkbox cơ bản kèm nhãn và mô tả."
110
- codeString={`<CheckboxPreset
101
+ <ShowcaseExample title="Tiêu chuẩn" description="Checkbox cơ bản kèm nhãn và mô tả." code={`<CheckboxPreset
111
102
  label="Đồng ý với điều khoản"
112
103
  description="Bạn phải đồng ý với các điều khoản và điều kiện sử dụng."
113
104
  className="w-full"
114
- />`}
115
- >
116
- <CheckboxPreset
117
- size={globalSize}
118
- label="Đồng ý với điều khoản"
119
- description="Bạn phải đồng ý với các điều khoản và điều kiện sử dụng."
120
- className="w-full"
121
- />
122
- </ExampleSection>
105
+ />`} preview={
106
+ <>
107
+ <CheckboxPreset
108
+ size={globalSize}
109
+ label="Đồng ý với điều khoản"
110
+ description="Bạn phải đồng ý với các điều khoản và điều kiện sử dụng."
111
+ className="w-full"
112
+ />
113
+ </>
114
+ } />
123
115
 
124
- <ExampleSection
125
- label="Trạng thái Lỗi (Error)"
126
- description="Báo lỗi khi chưa check vào ô (thường dùng trong form)."
127
- codeString={`<div className="w-full flex flex-col gap-6">
116
+ <ShowcaseExample title="Trạng thái Lỗi (Error)" description="Báo lỗi khi chưa check vào ô (thường dùng trong form)." code={`<div className="w-full flex flex-col gap-6">
128
117
  <CheckboxPreset
129
118
  label="Xác nhận đủ 18 tuổi"
130
119
  errorMessage="Bạn phải xác nhận đủ tuổi để tiếp tục."
131
120
  />
132
- </div>`}
133
- >
134
- <div className="w-full flex flex-col gap-6">
135
- <CheckboxPreset
136
- size={globalSize}
137
- label="Xác nhận đủ 18 tuổi"
138
- errorMessage="Bạn phải xác nhận đủ tuổi để tiếp tục."
139
- />
140
- </div>
141
- </ExampleSection>
121
+ </div>`} preview={
122
+ <>
123
+ <div className="w-full flex flex-col gap-6">
124
+ <CheckboxPreset
125
+ size={globalSize}
126
+ label="Xác nhận đủ 18 tuổi"
127
+ errorMessage="Bạn phải xác nhận đủ tuổi để tiếp tục."
128
+ />
129
+ </div>
130
+ </>
131
+ } />
142
132
  </ExampleGrid>
143
133
 
144
134
  <ExampleGrid>
145
- <ExampleSection
146
- label="Trạng thái Khóa (Disabled)"
147
- description="Checkbox bị vô hiệu hóa, không thể click."
148
- codeString={`<div className="w-full flex flex-col gap-6">
135
+ <ShowcaseExample title="Trạng thái Khóa (Disabled)" description="Checkbox bị vô hiệu hóa, không thể click." code={`<div className="w-full flex flex-col gap-6">
149
136
  <CheckboxPreset
150
137
  label="Đăng ký nhận bản tin"
151
138
  description="Tính năng này đang được bảo trì."
@@ -157,29 +144,27 @@ function CheckboxMacroShowcase({ globalSize }: { globalSize: Size }) {
157
144
  defaultChecked
158
145
  disabled
159
146
  />
160
- </div>`}
161
- >
162
- <div className="w-full flex flex-col gap-6">
163
- <CheckboxPreset
164
- size={globalSize}
165
- label="Đăng ký nhận bản tin"
166
- description="Tính năng này đang được bảo trì."
167
- disabled
168
- />
169
- <CheckboxPreset
170
- size={globalSize}
171
- label="Cho phép thu thập log"
172
- description="Hệ thống mặc định thu thập log bảo mật."
173
- defaultChecked
174
- disabled
175
- />
176
- </div>
177
- </ExampleSection>
147
+ </div>`} preview={
148
+ <>
149
+ <div className="w-full flex flex-col gap-6">
150
+ <CheckboxPreset
151
+ size={globalSize}
152
+ label="Đăng ký nhận bản tin"
153
+ description="Tính năng này đang được bảo trì."
154
+ disabled
155
+ />
156
+ <CheckboxPreset
157
+ size={globalSize}
158
+ label="Cho phép thu thập log"
159
+ description="Hệ thống mặc định thu thập log bảo mật."
160
+ defaultChecked
161
+ disabled
162
+ />
163
+ </div>
164
+ </>
165
+ } />
178
166
 
179
- <ExampleSection
180
- label="React Node Label (Custom Content)"
181
- description="Label có thể chứa các component React phức tạp như Badge."
182
- codeString={`<CheckboxPreset
167
+ <ShowcaseExample title="React Node Label (Custom Content)" description="Label có thể chứa các component React phức tạp như Badge." code={`<CheckboxPreset
183
168
  label={
184
169
  <span className="flex items-center gap-2">
185
170
  Tham gia chương trình BETA{" "}
@@ -190,79 +175,70 @@ function CheckboxMacroShowcase({ globalSize }: { globalSize: Size }) {
190
175
  }
191
176
  description="Được trải nghiệm sớm các tính năng mới trước khi phát hành chính thức. Có thể xảy ra lỗi."
192
177
  className="w-full"
193
- />`}
194
- >
195
- <CheckboxPreset
196
- size={globalSize}
197
- label={
198
- <span className="flex items-center gap-2">
199
- Tham gia chương trình BETA{" "}
200
- <span className="rounded bg-primary/20 px-1.5 py-0.5 text-[10px] font-semibold text-primary">
201
- NEW
202
- </span>
203
- </span>
204
- }
205
- description="Được trải nghiệm sớm các tính năng mới trước khi phát hành chính thức. Có thể xảy ra lỗi."
206
- className="w-full"
207
- />
208
- </ExampleSection>
178
+ />`} preview={
179
+ <>
180
+ <CheckboxPreset
181
+ size={globalSize}
182
+ label={
183
+ <span className="flex items-center gap-2">
184
+ Tham gia chương trình BETA{" "}
185
+ <span className="rounded bg-primary/20 px-1.5 py-0.5 text-[10px] font-semibold text-primary">
186
+ NEW
187
+ </span>
188
+ </span>
189
+ }
190
+ description="Được trải nghiệm sớm các tính năng mới trước khi phát hành chính thức. Có thể xảy ra lỗi."
191
+ className="w-full"
192
+ />
193
+ </>
194
+ } />
209
195
  </ExampleGrid>
210
196
 
211
197
  <ExampleGrid>
212
- <ExampleSection
213
- label="React State (Controlled Mode)"
214
- description="Sử dụng biến state của React để điều khiển."
215
- codeString={`const [checked, setChecked] = useState(false); return (
198
+ <ShowcaseExample title="React State (Controlled Mode)" description="Sử dụng biến state của React để điều khiển." code={`const [checked, setChecked] = useState(false); return (
216
199
  <CheckboxPreset
217
200
  checked={checked}
218
201
  onCheckedChange={(c) => setChecked(!!c)}
219
202
  label="Checkbox có kiểm soát"
220
203
  description="React quản lý trạng thái của checkbox này."
221
204
  />
222
- );`}
223
- >
224
- <div className="w-full flex flex-col gap-4">
225
- <CheckboxPreset
226
- size={globalSize}
227
- checked={checked}
228
- onCheckedChange={(c) => setChecked(!!c)}
229
- label="Checkbox có kiểm soát"
230
- description="React quản lý trạng thái của checkbox này."
231
- />
232
- <p className="text-sm text-muted-foreground">
233
- Giá trị hiện tại:{" "}
234
- <span className="font-mono font-bold text-foreground">
235
- {checked ? "TRUE" : "FALSE"}
236
- </span>
237
- </p>
238
- </div>
239
- </ExampleSection>
205
+ );`} preview={
206
+ <>
207
+ <div className="w-full flex flex-col gap-4">
208
+ <CheckboxPreset
209
+ size={globalSize}
210
+ checked={checked}
211
+ onCheckedChange={(c) => setChecked(!!c)}
212
+ label="Checkbox có kiểm soát"
213
+ description="React quản lý trạng thái của checkbox này."
214
+ />
215
+ <p className="text-sm text-muted-foreground">
216
+ Giá trị hiện tại:{" "}
217
+ <span className="font-mono font-bold text-foreground">
218
+ {checked ? "TRUE" : "FALSE"}
219
+ </span>
220
+ </p>
221
+ </div>
222
+ </>
223
+ } />
240
224
 
241
- <ExampleSection
242
- label="Tích hợp React Hook Form"
243
- description="Dùng Controller của RHF để bọc CheckboxPreset."
244
- codeString={rhfCode}
245
- >
246
- <CheckboxForm size={globalSize} />
247
- </ExampleSection>
225
+ <ShowcaseExample title="Tích hợp React Hook Form" description="Dùng Controller của RHF để bọc CheckboxPreset." code={rhfCode} preview={
226
+ <>
227
+ <CheckboxForm size={globalSize} />
228
+ </>
229
+ } />
248
230
  </ExampleGrid>
249
231
  </div>
250
232
  );
251
233
  }
252
234
 
253
- // ──────────────────────────────────────────────────────────
254
- // SECTION 2: Micro Content
255
- // ──────────────────────────────────────────────────────────
256
235
  function CheckboxMicroShowcase({ globalSize }: { globalSize: Size }) {
257
236
  const [checked, setChecked] = useState(false);
258
237
 
259
238
  return (
260
- <div className="space-y-10 mt-6">
239
+ <div className="space-y-10">
261
240
  <ExampleGrid>
262
- <ExampleSection
263
- label="Cơ bản (Primitive)"
264
- description="Kết nối thủ công Checkbox với thẻ Label html."
265
- codeString={`<div className="flex items-center gap-3">
241
+ <ShowcaseExample title="Cơ bản (Primitive)" description="Kết nối thủ công Checkbox với thẻ Label html." code={`<div className="flex items-center gap-3">
266
242
  <Checkbox id="cb-micro-default">
267
243
  <CheckboxIndicator>
268
244
  <CheckIcon />
@@ -274,27 +250,25 @@ function CheckboxMicroShowcase({ globalSize }: { globalSize: Size }) {
274
250
  >
275
251
  Đồng ý với điều khoản
276
252
  </Label>
277
- </div>`}
278
- >
279
- <div className="flex items-center gap-3">
280
- <Checkbox id="cb-micro-default" size={globalSize}>
281
- <CheckboxIndicator>
282
- <CheckIcon />
283
- </CheckboxIndicator>
284
- </Checkbox>
285
- <Label
286
- htmlFor="cb-micro-default"
287
- className="font-normal cursor-pointer"
288
- >
289
- Đồng ý với điều khoản
290
- </Label>
291
- </div>
292
- </ExampleSection>
253
+ </div>`} preview={
254
+ <>
255
+ <div className="flex items-center gap-3">
256
+ <Checkbox id="cb-micro-default" size={globalSize}>
257
+ <CheckboxIndicator>
258
+ <CheckIcon />
259
+ </CheckboxIndicator>
260
+ </Checkbox>
261
+ <Label
262
+ htmlFor="cb-micro-default"
263
+ className="font-normal cursor-pointer"
264
+ >
265
+ Đồng ý với điều khoản
266
+ </Label>
267
+ </div>
268
+ </>
269
+ } />
293
270
 
294
- <ExampleSection
295
- label="Icon Tuỳ Biến (Custom Icon)"
296
- description="Vì dùng Composition, bạn có thể truyền bất kỳ icon nào (VD: MinusIcon) vào Indicator."
297
- codeString={`<div className="flex items-center gap-3">
271
+ <ShowcaseExample title="Icon Tuỳ Biến (Custom Icon)" description="Vì dùng Composition, bạn có thể truyền bất kỳ icon nào (VD: MinusIcon) vào Indicator." code={`<div className="flex items-center gap-3">
298
272
  <Checkbox id="cb-custom-icon">
299
273
  <CheckboxIndicator>
300
274
  <MinusIcon />
@@ -306,29 +280,27 @@ function CheckboxMicroShowcase({ globalSize }: { globalSize: Size }) {
306
280
  >
307
281
  Trạng thái vô định (Indeterminate)
308
282
  </Label>
309
- </div>`}
310
- >
311
- <div className="flex items-center gap-3">
312
- <Checkbox id="cb-custom-icon" size={globalSize}>
313
- <CheckboxIndicator>
314
- <MinusIcon />
315
- </CheckboxIndicator>
316
- </Checkbox>
317
- <Label
318
- htmlFor="cb-custom-icon"
319
- className="font-normal cursor-pointer"
320
- >
321
- Trạng thái vô định (Indeterminate)
322
- </Label>
323
- </div>
324
- </ExampleSection>
283
+ </div>`} preview={
284
+ <>
285
+ <div className="flex items-center gap-3">
286
+ <Checkbox id="cb-custom-icon" size={globalSize}>
287
+ <CheckboxIndicator>
288
+ <MinusIcon />
289
+ </CheckboxIndicator>
290
+ </Checkbox>
291
+ <Label
292
+ htmlFor="cb-custom-icon"
293
+ className="font-normal cursor-pointer"
294
+ >
295
+ Trạng thái vô định (Indeterminate)
296
+ </Label>
297
+ </div>
298
+ </>
299
+ } />
325
300
  </ExampleGrid>
326
301
 
327
302
  <ExampleGrid>
328
- <ExampleSection
329
- label="Ghép nối với Field"
330
- description="Lắp ráp thủ công các thành phần Field khi cần layout phức tạp."
331
- codeString={`<Field className="flex items-start gap-3">
303
+ <ShowcaseExample title="Ghép nối với Field" description="Lắp ráp thủ công các thành phần Field khi cần layout phức tạp." code={`<Field className="flex items-start gap-3">
332
304
  {/* 1 khoảng trắng vô hình để căn chỉnh cho Label và Checkbox thẳng hàng với nhau theo dòng chữ đầu tiên */}
333
305
  <div className="flex items-center text-sm leading-snug group-data-[size=sm]/field:text-xs">
334
306
  &#8203;
@@ -349,36 +321,33 @@ function CheckboxMicroShowcase({ globalSize }: { globalSize: Size }) {
349
321
  Tự động đăng nhập vào lần sau.
350
322
  </FieldDescription>
351
323
  </div>
352
- </Field>`}
353
- >
354
- <Field className="flex items-start gap-3" data-size={globalSize}>
355
- {/* 1 khoảng trắng hình để căn chỉnh cho Label và Checkbox thẳng hàng với nhau theo dòng chữ đầu tiên */}
356
- <div className="flex items-center text-sm leading-snug group-data-[size=sm]/field:text-xs">
357
- &#8203;
358
- <Checkbox id="cb-field-micro" size={globalSize}>
359
- <CheckboxIndicator>
360
- <CheckIcon />
361
- </CheckboxIndicator>
362
- </Checkbox>
363
- </div>
364
- <div className="grid gap-1.5 leading-none">
365
- <FieldLabel
366
- htmlFor="cb-field-micro"
367
- className="font-medium cursor-pointer"
368
- >
369
- Lưu mật khẩu
370
- </FieldLabel>
371
- <FieldDescription>
372
- Tự động đăng nhập vào lần sau.
373
- </FieldDescription>
374
- </div>
375
- </Field>
376
- </ExampleSection>
324
+ </Field>`} preview={
325
+ <>
326
+ <Field className="flex items-start gap-3" data-size={globalSize}>
327
+ <div className="flex items-center text-sm leading-snug group-data-[size=sm]/field:text-xs">
328
+ &#8203;
329
+ <Checkbox id="cb-field-micro" size={globalSize}>
330
+ <CheckboxIndicator>
331
+ <CheckIcon />
332
+ </CheckboxIndicator>
333
+ </Checkbox>
334
+ </div>
335
+ <div className="grid gap-1.5 leading-none">
336
+ <FieldLabel
337
+ htmlFor="cb-field-micro"
338
+ className="font-medium cursor-pointer"
339
+ >
340
+ Lưu mật khẩu
341
+ </FieldLabel>
342
+ <FieldDescription>
343
+ Tự động đăng nhập vào lần sau.
344
+ </FieldDescription>
345
+ </div>
346
+ </Field>
347
+ </>
348
+ } />
377
349
 
378
- <ExampleSection
379
- label="Trạng thái Lỗi thủ công"
380
- description="Tự gắn aria-invalid vào Checkbox và dùng FieldError."
381
- codeString={`<Field
350
+ <ShowcaseExample title="Trạng thái Lỗi thủ công" description="Tự gắn aria-invalid vào Checkbox và dùng FieldError." code={`<Field
382
351
  className="flex flex-row items-start gap-3"
383
352
  data-invalid={true}
384
353
  >
@@ -399,39 +368,36 @@ function CheckboxMicroShowcase({ globalSize }: { globalSize: Size }) {
399
368
  </FieldLabel>
400
369
  <FieldError>Bắt buộc phải chọn ô này.</FieldError>
401
370
  </div>
402
- </Field>`}
403
- >
404
- <Field
405
- className="flex flex-row items-start gap-3"
406
- data-invalid={true}
407
- data-size={globalSize}
408
- >
409
- <div className="flex items-center text-sm leading-snug group-data-[size=sm]/field:text-xs">
410
- &#8203;
411
- <Checkbox id="cb-err-micro" size={globalSize} aria-invalid={true}>
412
- <CheckboxIndicator>
413
- <CheckIcon />
414
- </CheckboxIndicator>
415
- </Checkbox>
416
- </div>
417
- <div className="grid gap-1.5 leading-none">
418
- <FieldLabel
419
- htmlFor="cb-err-micro"
420
- className="font-medium cursor-pointer"
421
- >
422
- Đồng ý quy định
423
- </FieldLabel>
424
- <FieldError>Bắt buộc phải chọn ô này.</FieldError>
425
- </div>
426
- </Field>
427
- </ExampleSection>
371
+ </Field>`} preview={
372
+ <>
373
+ <Field
374
+ className="flex flex-row items-start gap-3"
375
+ data-invalid={true}
376
+ data-size={globalSize}
377
+ >
378
+ <div className="flex items-center text-sm leading-snug group-data-[size=sm]/field:text-xs">
379
+ &#8203;
380
+ <Checkbox id="cb-err-micro" size={globalSize} aria-invalid={true}>
381
+ <CheckboxIndicator>
382
+ <CheckIcon />
383
+ </CheckboxIndicator>
384
+ </Checkbox>
385
+ </div>
386
+ <div className="grid gap-1.5 leading-none">
387
+ <FieldLabel
388
+ htmlFor="cb-err-micro"
389
+ className="font-medium cursor-pointer"
390
+ >
391
+ Đồng ý quy định
392
+ </FieldLabel>
393
+ <FieldError>Bắt buộc phải chọn ô này.</FieldError>
394
+ </div>
395
+ </Field>
396
+ </>
397
+ } />
428
398
  </ExampleGrid>
429
399
 
430
- <ExampleSection
431
- label="🧭 Use Case Comparison"
432
- description="So sánh nhanh khi nào dùng Micro và Macro."
433
- fullWidth
434
- codeString={`<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
400
+ <ShowcaseExample title="🧭 So sánh Use Case" description="So sánh nhanh khi nào dùng Micro và Macro." code={`<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
435
401
  {/* Story 1: Macro wins */}
436
402
  <div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
437
403
  <div className="flex items-start gap-3">
@@ -533,124 +499,120 @@ function CheckboxMicroShowcase({ globalSize }: { globalSize: Size }) {
533
499
  </div>
534
500
  </div>
535
501
  </div>
536
- </div>`}
537
- >
538
- <div className="grid grid-cols-1 gap-6 md:grid-cols-2">
539
- {/* Story 1: Macro wins */}
540
- <div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
541
- <div className="flex items-start gap-3">
542
- <span className="mt-0.5 shrink-0 rounded-full bg-green-500/10 p-1.5 text-green-600">
543
- <svg
544
- xmlns="http://www.w3.org/2000/svg"
545
- className="size-4"
546
- viewBox="0 0 24 24"
547
- fill="none"
548
- stroke="currentColor"
549
- strokeWidth="2"
550
- strokeLinecap="round"
551
- strokeLinejoin="round"
552
- aria-hidden="true"
553
- >
554
- <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
555
- </svg>
556
- </span>
557
- <div>
558
- <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
559
- Story 1 · Dùng Macro
560
- </p>
561
- <h3 className="mt-0.5 text-sm font-semibold text-foreground">
562
- Checkbox trong trang Cài đặt
563
- </h3>
564
- </div>
565
- </div>
566
- <p className="text-xs text-muted-foreground leading-relaxed">
567
- Form cài đặt có rất nhiều tuỳ chọn dạng "Bật / Tắt" với mô tả dài.
568
- Code sẽ rất sạch và ngắn.
569
- </p>
570
- <div className="rounded-lg bg-muted/50 p-3 flex flex-col gap-4">
571
- <CheckboxPreset
572
- size="sm"
573
- label="Nhận Email Marketing"
574
- description="Gửi email cho bạn về các chương trình khuyến mãi hàng tuần."
575
- />
576
- <CheckboxPreset
577
- size="sm"
578
- label="Thông báo bảo mật"
579
- description="Cảnh báo khi có thiết bị lạ đăng nhập."
580
- defaultChecked
581
- />
582
- </div>
583
- </div>
502
+ </div>`} preview={
503
+ <>
504
+ <div className="grid grid-cols-1 gap-6 md:grid-cols-2">
505
+ <div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
506
+ <div className="flex items-start gap-3">
507
+ <span className="mt-0.5 shrink-0 rounded-full bg-green-500/10 p-1.5 text-green-600">
508
+ <svg
509
+ xmlns="http://www.w3.org/2000/svg"
510
+ className="size-4"
511
+ viewBox="0 0 24 24"
512
+ fill="none"
513
+ stroke="currentColor"
514
+ strokeWidth="2"
515
+ strokeLinecap="round"
516
+ strokeLinejoin="round"
517
+ aria-hidden="true"
518
+ >
519
+ <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
520
+ </svg>
521
+ </span>
522
+ <div>
523
+ <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
524
+ Story 1 · Dùng Macro
525
+ </p>
526
+ <h3 className="mt-0.5 text-sm font-semibold text-foreground">
527
+ Checkbox trong trang Cài đặt
528
+ </h3>
529
+ </div>
530
+ </div>
531
+ <p className="text-xs text-muted-foreground leading-relaxed">
532
+ Form cài đặt có rất nhiều tuỳ chọn dạng "Bật / Tắt" với mô tả dài.
533
+ Code sẽ rất sạch ngắn.
534
+ </p>
535
+ <div className="rounded-lg bg-muted/50 p-3 flex flex-col gap-4">
536
+ <CheckboxPreset
537
+ size="sm"
538
+ label="Nhận Email Marketing"
539
+ description="Gửi email cho bạn về các chương trình khuyến mãi hàng tuần."
540
+ />
541
+ <CheckboxPreset
542
+ size="sm"
543
+ label="Thông báo bảo mật"
544
+ description="Cảnh báo khi có thiết bị lạ đăng nhập."
545
+ defaultChecked
546
+ />
547
+ </div>
548
+ </div>
584
549
 
585
- {/* Story 2: Micro wins */}
586
- <div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
587
- <div className="flex items-start gap-3">
588
- <span className="mt-0.5 shrink-0 rounded-full bg-blue-500/10 p-1.5 text-blue-600">
589
- <svg
590
- xmlns="http://www.w3.org/2000/svg"
591
- className="size-4"
592
- viewBox="0 0 24 24"
593
- fill="none"
594
- stroke="currentColor"
595
- strokeWidth="2"
596
- strokeLinecap="round"
597
- strokeLinejoin="round"
598
- aria-hidden="true"
599
- >
600
- <path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z" />
601
- </svg>
602
- </span>
603
- <div>
604
- <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
605
- Story 2 · Dùng Micro
606
- </p>
607
- <h3 className="mt-0.5 text-sm font-semibold text-foreground">
608
- Table Row Selection
609
- </h3>
610
- </div>
611
- </div>
612
- <p className="text-xs text-muted-foreground leading-relaxed">
613
- Bạn cần ô Checkbox đầu mỗi dòng trong bảng để chọn nhiều hàng. Ở
614
- đây Checkbox đứng độc lập, hoàn toàn không cần Label hay
615
- Description đi kèm.
616
- </p>
617
- <div className="rounded-lg bg-muted/50 p-3">
618
- <div className="border border-border rounded-md divide-y overflow-hidden">
619
- <div className="flex items-center gap-3 p-2 bg-muted">
620
- <Checkbox size="sm">
621
- <CheckboxIndicator>
622
- <MinusIcon />
623
- </CheckboxIndicator>
624
- </Checkbox>
625
- <span className="text-xs font-semibold">Tên nhân viên</span>
626
- </div>
627
- <div className="flex items-center gap-3 p-2 bg-background hover:bg-muted/50">
628
- <Checkbox size="sm" defaultChecked>
629
- <CheckboxIndicator>
630
- <CheckIcon />
631
- </CheckboxIndicator>
632
- </Checkbox>
633
- <span className="text-xs">John Doe</span>
634
- </div>
635
- </div>
636
- </div>
637
- </div>
638
- </div>
639
- </ExampleSection>
550
+ <div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
551
+ <div className="flex items-start gap-3">
552
+ <span className="mt-0.5 shrink-0 rounded-full bg-blue-500/10 p-1.5 text-blue-600">
553
+ <svg
554
+ xmlns="http://www.w3.org/2000/svg"
555
+ className="size-4"
556
+ viewBox="0 0 24 24"
557
+ fill="none"
558
+ stroke="currentColor"
559
+ strokeWidth="2"
560
+ strokeLinecap="round"
561
+ strokeLinejoin="round"
562
+ aria-hidden="true"
563
+ >
564
+ <path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z" />
565
+ </svg>
566
+ </span>
567
+ <div>
568
+ <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
569
+ Story 2 · Dùng Micro
570
+ </p>
571
+ <h3 className="mt-0.5 text-sm font-semibold text-foreground">
572
+ Table Row Selection
573
+ </h3>
574
+ </div>
575
+ </div>
576
+ <p className="text-xs text-muted-foreground leading-relaxed">
577
+ Bạn cần ô Checkbox ở đầu mỗi dòng trong bảng để chọn nhiều hàng. Ở
578
+ đây Checkbox đứng độc lập, hoàn toàn không cần Label hay
579
+ Description đi kèm.
580
+ </p>
581
+ <div className="rounded-lg bg-muted/50 p-3">
582
+ <div className="border border-border rounded-md divide-y overflow-hidden">
583
+ <div className="flex items-center gap-3 p-2 bg-muted">
584
+ <Checkbox size="sm">
585
+ <CheckboxIndicator>
586
+ <MinusIcon />
587
+ </CheckboxIndicator>
588
+ </Checkbox>
589
+ <span className="text-xs font-semibold">Tên nhân viên</span>
590
+ </div>
591
+ <div className="flex items-center gap-3 p-2 bg-background hover:bg-muted/50">
592
+ <Checkbox size="sm" defaultChecked>
593
+ <CheckboxIndicator>
594
+ <CheckIcon />
595
+ </CheckboxIndicator>
596
+ </Checkbox>
597
+ <span className="text-xs">John Doe</span>
598
+ </div>
599
+ </div>
600
+ </div>
601
+ </div>
602
+ </div>
603
+ </>
604
+ } />
640
605
  </div>
641
606
  );
642
607
  }
643
608
 
644
- // ──────────────────────────────────────────────────────────
645
- // SECTION 3: Entry point
646
- // ──────────────────────────────────────────────────────────
647
609
  export default function CheckboxShowcase() {
648
610
  const { size: globalSize } = useDevContext();
649
611
  return (
650
612
  <Showcase
651
613
  title="Checkbox"
652
614
  description="Thành phần cho phép người dùng chọn hoặc bỏ chọn một tuỳ chọn độc lập."
653
- generalConcept={
615
+ guideline={
654
616
  <ShowcaseDocs>
655
617
  <DocsP>
656
618
  Dùng để thu thập đầu vào dạng đúng/sai hoặc nhiều lựa chọn độc lập
@@ -659,14 +621,8 @@ export default function CheckboxShowcase() {
659
621
  </DocsP>
660
622
  </ShowcaseDocs>
661
623
  }
662
- tabs={[
663
- {
664
- label: "Micro (Primitive)",
665
- content: <CheckboxMicroShowcase globalSize={globalSize} /> },
666
- {
667
- label: "Macro (Preset)",
668
- content: <CheckboxMacroShowcase globalSize={globalSize} /> },
669
- ]}
624
+ micro={{ content: <CheckboxMicroShowcase globalSize={globalSize} /> }}
625
+ macro={{ content: <CheckboxMacroShowcase globalSize={globalSize} /> }}
670
626
  />
671
627
  );
672
628
  }