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
@@ -14,22 +14,16 @@ import {
14
14
  DocsH3,
15
15
  DocsP,
16
16
  ExampleGrid,
17
- ExampleSection,
17
+ ShowcaseExample,
18
18
  Showcase,
19
19
  ShowcaseDocs
20
20
  } from "../../dev/components/showcase";
21
21
  import { type Size } from "../../lib/types";
22
22
 
23
- // ──────────────────────────────────────────────────────────
24
- // SECTION 1: Micro Content (Only Micro exists)
25
- // ──────────────────────────────────────────────────────────
26
23
  function TooltipMicroShowcase({ globalSize }: { globalSize: Size }) {
27
24
  return (
28
- <div className="space-y-10 mt-6">
29
- <ExampleSection
30
- label="Vị trí (Placements)"
31
- description="Tooltip có thể được đặt ở bất kỳ cạnh nào của trigger bằng thuộc tính side."
32
- codeString={`<div className="grid grid-cols-2 gap-4 max-w-md w-full place-items-center">
25
+ <div className="space-y-10">
26
+ <ShowcaseExample title="Vị trí (Placements)" description="Tooltip có thể được đặt ở bất kỳ cạnh nào của trigger bằng thuộc tính side." code={`<div className="grid grid-cols-2 gap-4 max-w-md w-full place-items-center">
33
27
  <TooltipProvider>
34
28
  <Tooltip>
35
29
  <TooltipTrigger
@@ -83,70 +77,68 @@ function TooltipMicroShowcase({ globalSize }: { globalSize: Size }) {
83
77
 
84
78
  </Tooltip>
85
79
  </TooltipProvider>
86
- </div>`}
87
- >
88
- <div className="grid grid-cols-2 gap-4 max-w-md w-full place-items-center">
89
- <TooltipProvider>
90
- <Tooltip>
91
- <TooltipTrigger
92
- render={
93
- <Button variant="outline" size={globalSize}>
94
- Trên (Top)
95
- </Button>
96
- }
97
- />
80
+ </div>`} preview={
81
+ <>
82
+ <div className="grid grid-cols-2 gap-4 max-w-md w-full place-items-center">
83
+ <TooltipProvider>
84
+ <Tooltip>
85
+ <TooltipTrigger
86
+ render={
87
+ <Button variant="outline" size={globalSize}>
88
+ Trên (Top)
89
+ </Button>
90
+ }
91
+ />
98
92
 
99
- <TooltipContent side="top">Tooltip nằm trên</TooltipContent>
100
-
101
- </Tooltip>
93
+ <TooltipContent side="top">Tooltip nằm trên</TooltipContent>
94
+
95
+ </Tooltip>
102
96
 
103
- <Tooltip>
104
- <TooltipTrigger
105
- render={
106
- <Button variant="outline" size={globalSize}>
107
- Dưới (Bottom)
108
- </Button>
109
- }
110
- />
97
+ <Tooltip>
98
+ <TooltipTrigger
99
+ render={
100
+ <Button variant="outline" size={globalSize}>
101
+ Dưới (Bottom)
102
+ </Button>
103
+ }
104
+ />
111
105
 
112
- <TooltipContent side="bottom">Tooltip nằm dưới</TooltipContent>
113
-
114
- </Tooltip>
106
+ <TooltipContent side="bottom">Tooltip nằm dưới</TooltipContent>
107
+
108
+ </Tooltip>
115
109
 
116
- <Tooltip>
117
- <TooltipTrigger
118
- render={
119
- <Button variant="outline" size={globalSize}>
120
- Trái (Left)
121
- </Button>
122
- }
123
- />
110
+ <Tooltip>
111
+ <TooltipTrigger
112
+ render={
113
+ <Button variant="outline" size={globalSize}>
114
+ Trái (Left)
115
+ </Button>
116
+ }
117
+ />
124
118
 
125
- <TooltipContent side="left">Tooltip nằm trái</TooltipContent>
126
-
127
- </Tooltip>
119
+ <TooltipContent side="left">Tooltip nằm trái</TooltipContent>
120
+
121
+ </Tooltip>
128
122
 
129
- <Tooltip>
130
- <TooltipTrigger
131
- render={
132
- <Button variant="outline" size={globalSize}>
133
- Phải (Right)
134
- </Button>
135
- }
136
- />
123
+ <Tooltip>
124
+ <TooltipTrigger
125
+ render={
126
+ <Button variant="outline" size={globalSize}>
127
+ Phải (Right)
128
+ </Button>
129
+ }
130
+ />
137
131
 
138
- <TooltipContent side="right">Tooltip nằm phải</TooltipContent>
139
-
140
- </Tooltip>
141
- </TooltipProvider>
142
- </div>
143
- </ExampleSection>
132
+ <TooltipContent side="right">Tooltip nằm phải</TooltipContent>
133
+
134
+ </Tooltip>
135
+ </TooltipProvider>
136
+ </div>
137
+ </>
138
+ } />
144
139
 
145
140
  <ExampleGrid>
146
- <ExampleSection
147
- label="Nội dung dài (Long Content)"
148
- description="Tooltip tự động giới hạn chiều rộng và xuống dòng khi nội dung quá dài."
149
- codeString={`<TooltipProvider>
141
+ <ShowcaseExample title="Nội dung dài (Long Content)" description="Tooltip tự động giới hạn chiều rộng và xuống dòng khi nội dung quá dài." code={`<TooltipProvider>
150
142
  <Tooltip>
151
143
  <TooltipTrigger
152
144
  render={
@@ -166,34 +158,32 @@ function TooltipMicroShowcase({ globalSize }: { globalSize: Size }) {
166
158
  </TooltipContent>
167
159
 
168
160
  </Tooltip>
169
- </TooltipProvider>`}
170
- >
171
- <TooltipProvider>
172
- <Tooltip>
173
- <TooltipTrigger
174
- render={
175
- <Button variant="outline" size={globalSize} iconOnly>
176
- <InfoIcon />
177
- </Button>
178
- }
179
- />
161
+ </TooltipProvider>`} preview={
162
+ <>
163
+ <TooltipProvider>
164
+ <Tooltip>
165
+ <TooltipTrigger
166
+ render={
167
+ <Button variant="outline" size={globalSize} iconOnly>
168
+ <InfoIcon />
169
+ </Button>
170
+ }
171
+ />
180
172
 
181
- <TooltipContent>
182
- <p>
183
- Đây là một đoạn nội dung tooltip khá dài nhằm mục đích trình
184
- diễn cách mà Tooltip tự động cắt và xuống dòng khi vượt quá
185
- chiều rộng tối đa (max-width) cho phép.
186
- </p>
187
- </TooltipContent>
188
-
189
- </Tooltip>
190
- </TooltipProvider>
191
- </ExampleSection>
173
+ <TooltipContent>
174
+ <p>
175
+ Đây là một đoạn nội dung tooltip khá dài nhằm mục đích trình
176
+ diễn cách mà Tooltip tự động cắt và xuống dòng khi vượt quá
177
+ chiều rộng tối đa (max-width) cho phép.
178
+ </p>
179
+ </TooltipContent>
180
+
181
+ </Tooltip>
182
+ </TooltipProvider>
183
+ </>
184
+ } />
192
185
 
193
- <ExampleSection
194
- label="Trigger bị vô hiệu (Disabled Trigger)"
195
- description="Để bắt sự kiện hover trên nút disabled, cần bọc nó trong một thẻ span có tabIndex."
196
- codeString={`<TooltipProvider>
186
+ <ShowcaseExample title="Trigger bị vô hiệu (Disabled Trigger)" description="Để bắt sự kiện hover trên nút disabled, cần bọc nó trong một thẻ span có tabIndex." code={`<TooltipProvider>
197
187
  <Tooltip>
198
188
  <TooltipTrigger
199
189
  render={
@@ -218,43 +208,40 @@ function TooltipMicroShowcase({ globalSize }: { globalSize: Size }) {
218
208
  </TooltipContent>
219
209
 
220
210
  </Tooltip>
221
- </TooltipProvider>`}
222
- >
223
- <TooltipProvider>
224
- <Tooltip>
225
- <TooltipTrigger
226
- render={
227
- <span
228
- tabIndex={0}
229
- className="inline-block cursor-not-allowed"
230
- >
231
- <Button
232
- variant="outline"
233
- size={globalSize}
234
- disabled
235
- className="pointer-events-none w-full h-full"
236
- iconOnly
237
- >
238
- <ShieldAlertIcon />
239
- </Button>
240
- </span>
241
- }
242
- />
211
+ </TooltipProvider>`} preview={
212
+ <>
213
+ <TooltipProvider>
214
+ <Tooltip>
215
+ <TooltipTrigger
216
+ render={
217
+ <span
218
+ tabIndex={0}
219
+ className="inline-block cursor-not-allowed"
220
+ >
221
+ <Button
222
+ variant="outline"
223
+ size={globalSize}
224
+ disabled
225
+ className="pointer-events-none w-full h-full"
226
+ iconOnly
227
+ >
228
+ <ShieldAlertIcon />
229
+ </Button>
230
+ </span>
231
+ }
232
+ />
243
233
 
244
- <TooltipContent side="right">
245
- <p>Bạn không có quyền thực hiện hành động này.</p>
246
- </TooltipContent>
247
-
248
- </Tooltip>
249
- </TooltipProvider>
250
- </ExampleSection>
234
+ <TooltipContent side="right">
235
+ <p>Bạn không có quyền thực hiện hành động này.</p>
236
+ </TooltipContent>
237
+
238
+ </Tooltip>
239
+ </TooltipProvider>
240
+ </>
241
+ } />
251
242
  </ExampleGrid>
252
243
 
253
- <ExampleSection
254
- label="Độ trễ tuỳ chỉnh (Custom Delay)"
255
- description="Thay đổi thời gian trễ trước khi tooltip xuất hiện thông qua thuộc tính delay của TooltipProvider."
256
- fullWidth
257
- codeString={`<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
244
+ <ShowcaseExample title="Độ trễ tuỳ chỉnh (Custom Delay)" description="Thay đổi thời gian trễ trước khi tooltip xuất hiện thông qua thuộc tính delay của TooltipProvider." code={`<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
258
245
  <TooltipProvider delay={0}>
259
246
  <Tooltip>
260
247
  <TooltipTrigger
@@ -305,81 +292,79 @@ function TooltipMicroShowcase({ globalSize }: { globalSize: Size }) {
305
292
 
306
293
  </Tooltip>
307
294
  </TooltipProvider>
308
- </div>`}
309
- >
310
- <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
311
- <TooltipProvider delay={0}>
312
- <Tooltip>
313
- <TooltipTrigger
314
- render={
315
- <Button
316
- variant="outline"
317
- size={globalSize}
318
- className="w-full"
319
- >
320
- Tức thì (0ms)
321
- </Button>
322
- }
323
- />
324
-
325
- <TooltipContent>Xuất hiện ngay lập tức</TooltipContent>
326
-
327
- </Tooltip>
328
- </TooltipProvider>
295
+ </div>`} preview={
296
+ <>
297
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
298
+ <TooltipProvider delay={0}>
299
+ <Tooltip>
300
+ <TooltipTrigger
301
+ render={
302
+ <Button
303
+ variant="outline"
304
+ size={globalSize}
305
+ className="w-full"
306
+ >
307
+ Tức thì (0ms)
308
+ </Button>
309
+ }
310
+ />
311
+
312
+ <TooltipContent>Xuất hiện ngay lập tức</TooltipContent>
313
+
314
+ </Tooltip>
315
+ </TooltipProvider>
329
316
 
330
- <TooltipProvider delay={500}>
331
- <Tooltip>
332
- <TooltipTrigger
333
- render={
334
- <Button
335
- variant="outline"
336
- size={globalSize}
337
- className="w-full"
338
- >
339
- Mặc định (500ms)
340
- </Button>
341
- }
342
- />
343
-
344
- <TooltipContent>Xuất hiện sau nửa giây</TooltipContent>
345
-
346
- </Tooltip>
347
- </TooltipProvider>
317
+ <TooltipProvider delay={500}>
318
+ <Tooltip>
319
+ <TooltipTrigger
320
+ render={
321
+ <Button
322
+ variant="outline"
323
+ size={globalSize}
324
+ className="w-full"
325
+ >
326
+ Mặc định (500ms)
327
+ </Button>
328
+ }
329
+ />
330
+
331
+ <TooltipContent>Xuất hiện sau nửa giây</TooltipContent>
332
+
333
+ </Tooltip>
334
+ </TooltipProvider>
348
335
 
349
- <TooltipProvider delay={2000}>
350
- <Tooltip>
351
- <TooltipTrigger
352
- render={
353
- <Button
354
- variant="outline"
355
- size={globalSize}
356
- className="w-full"
357
- >
358
- Chậm (2000ms)
359
- </Button>
360
- }
361
- />
362
-
363
- <TooltipContent>Xuất hiện sau 2 giây chờ đợi</TooltipContent>
364
-
365
- </Tooltip>
366
- </TooltipProvider>
367
- </div>
368
- </ExampleSection>
336
+ <TooltipProvider delay={2000}>
337
+ <Tooltip>
338
+ <TooltipTrigger
339
+ render={
340
+ <Button
341
+ variant="outline"
342
+ size={globalSize}
343
+ className="w-full"
344
+ >
345
+ Chậm (2000ms)
346
+ </Button>
347
+ }
348
+ />
349
+
350
+ <TooltipContent>Xuất hiện sau 2 giây chờ đợi</TooltipContent>
351
+
352
+ </Tooltip>
353
+ </TooltipProvider>
354
+ </div>
355
+ </>
356
+ } />
369
357
  </div>
370
358
  );
371
359
  }
372
360
 
373
- // ──────────────────────────────────────────────────────────
374
- // SECTION 3: Entry point
375
- // ──────────────────────────────────────────────────────────
376
361
  export default function TooltipShowcase() {
377
362
  const { size: globalSize } = useDevContext();
378
363
  return (
379
364
  <Showcase
380
365
  title="Tooltip"
381
366
  description="Một popup nhỏ hiển thị thông tin bổ sung khi người dùng di chuột hoặc trỏ tiêu điểm vào một phần tử."
382
- generalConcept={
367
+ guideline={
383
368
  <ShowcaseDocs>
384
369
  <DocsH3>Tooltip (Gợi ý)</DocsH3>
385
370
  <DocsP>
@@ -390,11 +375,7 @@ export default function TooltipShowcase() {
390
375
  </DocsP>
391
376
  </ShowcaseDocs>
392
377
  }
393
- tabs={[
394
- {
395
- label: "Micro (Primitive)",
396
- content: <TooltipMicroShowcase globalSize={globalSize} /> },
397
- ]}
378
+ micro={{ content: <TooltipMicroShowcase globalSize={globalSize} /> }}
398
379
  />
399
380
  );
400
381
  }
@@ -23,7 +23,6 @@ export default function WhyGladvn() {
23
23
 
24
24
  return (
25
25
  <div className="space-y-24 overflow-hidden pb-24 font-sans max-w-5xl mx-auto">
26
- {/* HERO SECTION */}
27
26
  <section className="relative pt-20 pb-16">
28
27
  <div className="absolute inset-0 -z-10 h-full w-full bg-background bg-[radial-gradient(ellipse_80%_80%_at_50%_-20%,rgba(var(--primary-rgb),0.2),rgba(255,255,255,0))] dark:bg-[radial-gradient(ellipse_80%_80%_at_50%_-20%,rgba(var(--primary-rgb),0.15),rgba(255,255,255,0))]" />
29
28
 
@@ -70,14 +69,13 @@ export default function WhyGladvn() {
70
69
  </div>
71
70
  </section>
72
71
 
73
- {/* THE PROBLEM */}
74
72
  <section className="px-4">
75
73
  <div className="rounded-[2.5rem] border border-destructive/20 bg-destructive/5 p-8 md:p-16 text-center">
76
74
  <h2 className="text-3xl md:text-4xl font-extrabold tracking-tight mb-6">
77
75
  Most UI libraries force a choice:
78
76
  </h2>
79
77
  <p className="text-xl md:text-2xl text-muted-foreground mb-12">
80
- Low-level pain <span className="text-destructive font-bold">OR</span> High-level lock-in.
78
+ Đau đầu với Low-level <span className="text-destructive font-bold">HOẶC</span> Bị gò bó bởi High-level.
81
79
  </p>
82
80
 
83
81
  <div className="grid md:grid-cols-3 gap-6 max-w-4xl mx-auto text-left">
@@ -106,7 +104,6 @@ export default function WhyGladvn() {
106
104
  </div>
107
105
  </section>
108
106
 
109
- {/* THE SOLUTION */}
110
107
  <section className="px-4 space-y-12">
111
108
  <div className="text-center max-w-2xl mx-auto space-y-4">
112
109
  <h2 className="text-3xl md:text-4xl font-extrabold tracking-tight">
@@ -123,7 +120,7 @@ export default function WhyGladvn() {
123
120
  <div className="inline-flex p-3 rounded-xl bg-primary/10 text-primary mb-6">
124
121
  <CodeIcon className="size-6" />
125
122
  </div>
126
- <h3 className="text-2xl font-bold mb-4">Micro: Build your way</h3>
123
+ <h3 className="text-2xl font-bold mb-4">Micro: Xây dựng theo cách của bạn</h3>
127
124
  <p className="text-muted-foreground mb-8">
128
125
  Lắp ráp từng mảnh ghép để kiểm soát 100% UI.
129
126
  </p>
@@ -133,7 +130,7 @@ export default function WhyGladvn() {
133
130
  <span className="text-info">variant=</span><span className="text-success">"solid"</span>
134
131
  <span className="text-info"> color=</span><span className="text-success">"primary"</span>
135
132
  <span className="text-primary">{">"}</span>
136
- <span className="text-foreground">Submit</span>
133
+ <span className="text-foreground">Xác nhận</span>
137
134
  <span className="text-primary">{"</Button>"}</span>
138
135
  </div>
139
136
  </div>
@@ -143,7 +140,7 @@ export default function WhyGladvn() {
143
140
  <div className="inline-flex p-3 rounded-xl bg-info/10 text-info mb-6">
144
141
  <LayersIcon className="size-6" />
145
142
  </div>
146
- <h3 className="text-2xl font-bold mb-4">Macro: Move fast</h3>
143
+ <h3 className="text-2xl font-bold mb-4">Macro: Triển khai thần tốc</h3>
147
144
  <p className="text-muted-foreground mb-8">
148
145
  Dùng các preset làm sẵn để phát triển nhanh chóng.
149
146
  </p>
@@ -161,9 +158,8 @@ export default function WhyGladvn() {
161
158
  </div>
162
159
  </section>
163
160
 
164
- {/* MORE REASONS */}
165
161
  <section className="px-4">
166
- <h2 className="text-2xl font-bold mb-8 pl-4 border-l-4 border-primary">More Reasons to Choose Gladvn</h2>
162
+ <h2 className="text-2xl font-bold mb-8 pl-4 border-l-4 border-primary">Thêm do để chọn Gladvn</h2>
167
163
  <div className="grid md:grid-cols-3 gap-6">
168
164
  <Card className="hover:border-primary/50 transition-colors">
169
165
  <CardContent className="p-6 space-y-4">
@@ -195,7 +191,6 @@ export default function WhyGladvn() {
195
191
  </div>
196
192
  </section>
197
193
 
198
- {/* VS SHADCN */}
199
194
  <section className="px-4">
200
195
  <h2 className="text-2xl font-bold mb-8 text-center">So sánh nhanh</h2>
201
196
  <div className="overflow-x-auto rounded-2xl border border-border bg-card">
@@ -250,12 +245,11 @@ export default function WhyGladvn() {
250
245
  </div>
251
246
  </section>
252
247
 
253
- {/* CTA */}
254
248
  <section className="px-4 pb-20">
255
249
  <div className="rounded-[3rem] bg-foreground text-background p-12 md:p-20 text-center relative overflow-hidden">
256
250
  <div className="absolute inset-0 bg-[radial-gradient(ellipse_at_top,rgba(255,255,255,0.1),transparent)]" />
257
251
  <div className="relative z-10">
258
- <h2 className="text-4xl md:text-5xl font-black mb-8">Ready to build differently?</h2>
252
+ <h2 className="text-4xl md:text-5xl font-black mb-8">Sẵn sàng trải nghiệm khác biệt?</h2>
259
253
  <button
260
254
  onClick={handleCopy}
261
255
  className="bg-background text-foreground hover:bg-muted px-8 py-4 rounded-full font-mono text-base font-bold shadow-xl flex items-center gap-4 mx-auto transition-transform hover:scale-105"
@@ -1,5 +1,6 @@
1
1
  import { act, renderHook } from "@testing-library/react";
2
2
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
3
+
3
4
  import { useIsMobile } from "./use-mobile";
4
5
 
5
6
  describe("useIsMobile hook", () => {
@@ -7,7 +8,7 @@ describe("useIsMobile hook", () => {
7
8
 
8
9
  beforeEach(() => {
9
10
  originalInnerWidth = window.innerWidth;
10
-
11
+
11
12
  // Mock matchMedia
12
13
  Object.defineProperty(window, "matchMedia", {
13
14
  writable: true,
@@ -43,7 +44,7 @@ describe("useIsMobile hook", () => {
43
44
 
44
45
  it("should update when resize event changes innerWidth", () => {
45
46
  let changeCallback: () => void = () => {};
46
-
47
+
47
48
  // Custom mock to capture the event listener
48
49
  Object.defineProperty(window, "matchMedia", {
49
50
  writable: true,
@@ -1,4 +1,5 @@
1
1
  import { describe, expect, it } from "vitest";
2
+
2
3
  import { cn } from "./utils";
3
4
 
4
5
  describe("cn utility function", () => {
@@ -14,9 +15,9 @@ describe("cn utility function", () => {
14
15
  });
15
16
 
16
17
  it("should handle conditional classes", () => {
17
- expect(cn("base-class", true && "truthy-class", false && "falsy-class")).toBe(
18
- "base-class truthy-class"
19
- );
18
+ expect(
19
+ cn("base-class", true && "truthy-class", false && "falsy-class"),
20
+ ).toBe("base-class truthy-class");
20
21
  });
21
22
 
22
23
  it("should handle arrays of classes", () => {
@@ -25,7 +26,7 @@ describe("cn utility function", () => {
25
26
 
26
27
  it("should ignore null and undefined values", () => {
27
28
  expect(cn("valid-class", null, undefined, "another-class")).toBe(
28
- "valid-class another-class"
29
+ "valid-class another-class",
29
30
  );
30
31
  });
31
32
  });