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
@@ -0,0 +1,535 @@
1
+ import React from "react";
2
+ import {
3
+ BlocksIcon,
4
+ ShieldCheckIcon,
5
+ SlidersHorizontalIcon,
6
+ BoxIcon,
7
+ PaintbrushIcon,
8
+ ComponentIcon,
9
+ LayersIcon,
10
+ PaletteIcon,
11
+ CopyIcon,
12
+ AccessibilityIcon,
13
+ DatabaseIcon,
14
+ SparklesIcon,
15
+ ArrowRightIcon
16
+ } from "lucide-react";
17
+ import { CodeBlock } from "./CodeBlock";
18
+ import { Button } from "../../../components/micro/button";
19
+ import { cn } from "../../../lib/utils";
20
+
21
+ export function FeatureGridSection({ className }: { className?: string }) {
22
+ return (
23
+ <div className={className}>
24
+ <div className="columns-1 md:columns-2 gap-6">
25
+
26
+ <div className="break-inside-avoid mb-6 rounded-[2rem] border border-border bg-card/20 p-4 md:p-10 flex flex-col justify-between group overflow-hidden relative hover:bg-card/40 transition-colors duration-500">
27
+ <div className="absolute -top-10 -right-10 p-8 opacity-5 group-hover:opacity-10 transition-all pointer-events-none transform group-hover:scale-110 group-hover:-rotate-12 duration-700">
28
+ <BlocksIcon className="w-80 h-80" />
29
+ </div>
30
+ <div className="relative z-10 space-y-4 mb-10">
31
+ <h3 className="text-2xl md:text-4xl font-extrabold tracking-tight">
32
+ Luật chơi Micro/Macro
33
+ </h3>
34
+ <p className="text-muted-foreground max-w-lg text-lg leading-relaxed">
35
+ Micro chỉ là những mảnh lego thuần túy — đẹp nhưng vô tri. Macro mới là người chỉ huy — sắp xếp các mảnh lego thành giao diện hoàn chỉnh.
36
+ <strong className="text-foreground block mt-2">
37
+ Micro không bao giờ được phép tự tiện lo chuyện layout (margin, width). Việc đó là của Macro!
38
+ </strong>
39
+ </p>
40
+ </div>
41
+ <div className="relative z-10 mt-auto pt-6 space-y-3">
42
+ <CodeBlock type="success" title="Đúng — Để Macro lo layout:">
43
+ <span className="text-success/80">
44
+ {"/* Macro biết con mình là gì → gắn class chính xác */"}
45
+ </span>
46
+ <br />
47
+ <span className="text-foreground">{"<AlertDialogFooter>"}</span>
48
+ <br />
49
+ <span className="pl-4">
50
+ {'<Button variant="ghost">Trợ giúp</Button>'}
51
+ </span>
52
+ <br />
53
+ <span className="pl-4 text-success font-bold">
54
+ {'<Button className="ml-auto">Xác nhận</Button>'}
55
+ </span>
56
+ <br />
57
+ <span className="text-foreground">
58
+ {"</AlertDialogFooter>"}
59
+ </span>
60
+ </CodeBlock>
61
+
62
+ <CodeBlock type="destructive" title="Sai — Micro tự đoán layout:">
63
+ <span className="text-destructive/80">
64
+ {"/* Micro không biết con mình là gì → phải đoán bằng CSS */"}
65
+ </span>
66
+ <br />
67
+ <span className="text-foreground">{"<AlertDialogFooter"}</span>
68
+ <br />
69
+ <span className="pl-4 text-destructive font-bold line-through">
70
+ {'className="[&>*:last-child]:ml-auto"'}
71
+ </span>
72
+ <br />
73
+ <span className="text-foreground">{">"}</span>
74
+ <br />
75
+ <span className="pl-4">{"{children}"}</span>
76
+ <br />
77
+ <span className="text-foreground">
78
+ {"</AlertDialogFooter>"}
79
+ </span>
80
+ </CodeBlock>
81
+ </div>
82
+ </div>
83
+
84
+
85
+ <div className="break-inside-avoid mb-6 rounded-[2rem] border border-border bg-card/20 p-4 md:p-10 flex flex-col group overflow-hidden relative hover:bg-card/40 transition-colors duration-500">
86
+ <div className="absolute top-0 right-0 p-8 opacity-5 group-hover:opacity-10 transition-all pointer-events-none transform group-hover:scale-110 group-hover:rotate-12 duration-700">
87
+ <ShieldCheckIcon className="w-56 h-56" />
88
+ </div>
89
+ <div className="relative z-10 space-y-4">
90
+ <h3 className="text-2xl font-extrabold tracking-tight">
91
+ Style Encapsulation
92
+ </h3>
93
+ <p className="text-muted-foreground text-base leading-relaxed">
94
+ Style của mỗi component không rò rỉ ra ngoài. Muốn tuỳ chỉnh thì
95
+ dùng <code>data-slot</code> — contract rõ ràng, có sẵn.{" "}
96
+ <strong className="text-foreground">
97
+ Refactor bên trong mà không ảnh hưởng bên ngoài.
98
+ </strong>
99
+ </p>
100
+ </div>
101
+ <div className="relative z-10 mt-auto pt-6 space-y-3">
102
+ <div className="p-3 rounded-xl border border-destructive/20 bg-destructive/5 text-xs font-mono shadow-sm flex items-center">
103
+ <span className="text-destructive font-bold mr-3 text-lg">
104
+
105
+ </span>
106
+ <span className="opacity-80 line-through">
107
+ {"[&>div>span]:color"}
108
+ </span>
109
+ </div>
110
+ <div className="p-3 rounded-xl border border-success/20 bg-success/5 text-xs font-mono shadow-sm flex items-center">
111
+ <span className="text-success font-bold mr-3 text-lg">✅</span>
112
+ <span className="text-foreground font-medium">
113
+ data-[slot=icon]:color
114
+ </span>
115
+ </div>
116
+ </div>
117
+ </div>
118
+
119
+
120
+ <div className="break-inside-avoid mb-6 rounded-[2rem] border border-border bg-card/20 p-4 md:p-10 flex flex-col group overflow-hidden relative hover:bg-card/40 transition-colors duration-500">
121
+ <div className="absolute top-0 right-0 p-8 opacity-5 group-hover:opacity-10 transition-all pointer-events-none transform group-hover:scale-110 group-hover:-rotate-12 duration-700">
122
+ <SlidersHorizontalIcon className="w-80 h-80" />
123
+ </div>
124
+ <div className="relative z-10 space-y-4">
125
+ <h3 className="text-2xl md:text-4xl font-extrabold tracking-tight">
126
+ Variant × Color
127
+ </h3>
128
+ <p className="text-muted-foreground text-lg leading-relaxed max-w-lg">
129
+ Variant (solid, outline, ghost...) và Color (primary,
130
+ destructive...) là hai trục độc lập. Kết hợp tự do mà class
131
+ không phình ra.
132
+ </p>
133
+ </div>
134
+ <div className="relative z-10 mt-auto pt-8 grid sm:grid-cols-2 gap-4">
135
+ <div className="p-3 sm:p-5 rounded-2xl border border-border bg-background/60 backdrop-blur-md shadow-sm hover:shadow-md transition-shadow">
136
+ <strong className="block text-foreground text-base mb-2 flex items-center gap-2">
137
+ <BoxIcon className="size-4 text-muted-foreground" /> Trục
138
+ Variant
139
+ </strong>
140
+ <span className="text-sm text-muted-foreground leading-relaxed">
141
+ solid, outline, ghost, soft. Quyết định cách component trông
142
+ như thế nào.
143
+ </span>
144
+ </div>
145
+ <div className="p-3 sm:p-5 rounded-2xl border border-border bg-background/60 backdrop-blur-md shadow-sm hover:shadow-md transition-shadow">
146
+ <strong className="block text-foreground text-base mb-2 flex items-center gap-2">
147
+ <PaintbrushIcon className="size-4 text-muted-foreground" />{" "}
148
+ Trục Color
149
+ </strong>
150
+ <span className="text-sm text-muted-foreground leading-relaxed">
151
+ primary, secondary, destructive. Quyết định bảng màu của
152
+ component.
153
+ </span>
154
+ </div>
155
+ </div>
156
+ </div>
157
+
158
+ <div className="break-inside-avoid mb-6 rounded-[2rem] border border-border bg-card/20 p-4 md:p-10 flex flex-col group overflow-hidden relative hover:bg-card/40 transition-colors duration-500">
159
+ <div className="absolute top-0 right-0 p-8 opacity-5 group-hover:opacity-10 transition-all pointer-events-none transform group-hover:scale-110 group-hover:-rotate-12 duration-700">
160
+ <ComponentIcon className="w-80 h-80" />
161
+ </div>
162
+ <div className="relative z-10 space-y-4">
163
+ <h3 className="text-2xl md:text-4xl font-extrabold tracking-tight">
164
+ Zero-prop Defaults
165
+ </h3>
166
+ <p className="text-muted-foreground text-lg leading-relaxed max-w-lg">
167
+ Đặt component vào mà không truyền prop nào — vẫn chạy đẹp, vẫn
168
+ đúng behavior.{" "}
169
+ <strong className="text-foreground">
170
+ Không phải tra docs mỗi lần dùng.
171
+ </strong>
172
+ </p>
173
+ </div>
174
+ <div className="relative z-10 mt-auto pt-8 flex flex-col gap-4">
175
+ <div className="flex items-center justify-between gap-4 p-4 rounded-xl border border-success/20 bg-success/5 shadow-sm">
176
+ <Button>Click Me</Button>
177
+ <span className="text-[11px] sm:text-xs font-mono text-success font-medium">
178
+ {"<Button>Click Me</Button>"}
179
+ </span>
180
+ </div>
181
+ <div className="flex items-center justify-between gap-4 p-4 rounded-xl border border-destructive/20 bg-destructive/5 shadow-sm opacity-60">
182
+ <Button size="md" color="primary">
183
+ Click Me
184
+ </Button>
185
+ <span className="text-[11px] sm:text-xs font-mono text-destructive font-medium line-through">
186
+ {'<Button size="md" color="primary">...'}
187
+ </span>
188
+ </div>
189
+ </div>
190
+ </div>
191
+
192
+
193
+ <div className="break-inside-avoid mb-6 rounded-[2rem] border border-border bg-card/20 p-4 md:p-10 flex flex-col group overflow-hidden relative hover:bg-card/40 transition-colors duration-500">
194
+ <div className="absolute top-0 right-0 p-8 opacity-5 group-hover:opacity-10 transition-all pointer-events-none transform group-hover:scale-110 group-hover:rotate-12 duration-700">
195
+ <LayersIcon className="w-56 h-56" />
196
+ </div>
197
+ <div className="relative z-10 space-y-4">
198
+ <h3 className="text-2xl font-extrabold tracking-tight">
199
+ Headless + Style
200
+ </h3>
201
+ <p className="text-muted-foreground text-base leading-relaxed">
202
+ Keyboard, focus, ARIA — Base UI lo hết. Micro component chỉ thêm
203
+ lớp style lên trên, không tự viết logic tương tác.{" "}
204
+ <strong className="text-foreground">
205
+ Behavior đúng sẵn, không cần test lại.
206
+ </strong>
207
+ </p>
208
+ </div>
209
+ <div className="relative z-10 mt-auto pt-8">
210
+ <div className="p-4 rounded-xl bg-foreground/5 border border-border/50 text-[11px] sm:text-xs font-mono shadow-inner space-y-1">
211
+ <div className="text-muted-foreground">
212
+
213
+ </div>
214
+ <div>
215
+ <span className="text-primary">{"<Base UI Select>"}</span>
216
+ <span className="text-muted-foreground"> ← behavior</span>
217
+ </div>
218
+ <div className="pl-4">
219
+ <span className="text-success">{"<SelectTrigger>"}</span>
220
+ <span className="text-muted-foreground"> ← style only</span>
221
+ </div>
222
+ </div>
223
+ </div>
224
+ </div>
225
+
226
+ <div className="break-inside-avoid mb-6 rounded-[2rem] border border-border bg-card/20 p-4 md:p-10 flex flex-col group overflow-hidden relative hover:bg-card/40 transition-colors duration-500">
227
+ <div className="absolute top-0 right-0 p-8 opacity-5 group-hover:opacity-10 transition-all pointer-events-none transform group-hover:scale-110 group-hover:rotate-12 duration-700">
228
+ <PaletteIcon className="w-56 h-56" />
229
+ </div>
230
+ <div className="relative z-10 space-y-4">
231
+ <h3 className="text-2xl md:text-4xl font-extrabold tracking-tight">
232
+ CSS Token
233
+ </h3>
234
+ <p className="text-muted-foreground text-lg leading-relaxed max-w-lg">
235
+ Không component nào hardcode màu hay spacing. Tất cả đều tham
236
+ chiếu từ hệ thống token chung.{" "}
237
+ <strong className="text-foreground">
238
+ Đổi một token — cả app cập nhật.
239
+ </strong>
240
+ </p>
241
+ </div>
242
+ <div className="relative z-10 mt-auto pt-8 grid sm:grid-cols-2 gap-4">
243
+ <div className="p-4 rounded-xl border border-success/20 bg-success/5 shadow-sm">
244
+ <div className="text-success font-semibold mb-2 text-sm">
245
+ ✅ Token
246
+ </div>
247
+ <div className="text-[11px] font-mono text-success/80">
248
+ oklch(var(--primary))
249
+ </div>
250
+ </div>
251
+ <div className="p-4 rounded-xl border border-destructive/20 bg-destructive/5 shadow-sm opacity-60">
252
+ <div className="text-destructive font-semibold mb-2 text-sm">
253
+ ❌ Hardcode
254
+ </div>
255
+ <div className="text-[11px] font-mono text-destructive/80 line-through">
256
+ #2563eb
257
+ </div>
258
+ </div>
259
+ </div>
260
+ </div>
261
+
262
+
263
+ <div className="break-inside-avoid mb-6 rounded-[2rem] border border-border bg-card/20 p-4 md:p-10 flex flex-col group overflow-hidden relative hover:bg-card/40 transition-colors duration-500">
264
+ <div className="absolute top-0 right-0 p-8 opacity-5 group-hover:opacity-10 transition-all pointer-events-none transform group-hover:scale-110 group-hover:rotate-12 duration-700">
265
+ <CopyIcon className="w-56 h-56" />
266
+ </div>
267
+ <div className="relative z-10 space-y-4">
268
+ <h3 className="text-2xl font-extrabold tracking-tight">
269
+ Polymorphism
270
+ </h3>
271
+ <p className="text-muted-foreground text-base leading-relaxed">
272
+ Dùng <code>render</code> prop để đổi thẻ HTML root — ví dụ biến
273
+ Button thành Link. Không cần prop <code>as</code> hay tạo
274
+ wrapper lồng nhau.
275
+ </p>
276
+ </div>
277
+ <div className="relative z-10 mt-auto pt-6 space-y-3">
278
+ <div className="p-3 rounded-xl border border-success/20 bg-success/5 text-[11px] font-mono shadow-sm flex items-center">
279
+ <span className="text-success font-bold mr-3 text-lg">✅</span>
280
+ <span className="text-success/90">
281
+ &lt;Button render=&#123;&lt;Link/&gt;&#125;&gt;
282
+ </span>
283
+ </div>
284
+ <div className="p-3 rounded-xl border border-destructive/20 bg-destructive/5 text-[11px] font-mono shadow-sm flex items-center opacity-70">
285
+ <span className="text-destructive font-bold mr-3 text-lg">
286
+
287
+ </span>
288
+ <span className="text-destructive/80 line-through">
289
+ &lt;Button as="a" href="/"&gt;
290
+ </span>
291
+ </div>
292
+ </div>
293
+ </div>
294
+
295
+
296
+ <div className="break-inside-avoid mb-6 rounded-[2rem] border border-border bg-card/20 p-4 md:p-10 flex flex-col group overflow-hidden relative hover:bg-card/40 transition-colors duration-500">
297
+ <div className="absolute top-0 right-0 p-8 opacity-5 group-hover:opacity-10 transition-all pointer-events-none transform group-hover:scale-110 group-hover:rotate-12 duration-700">
298
+ <BoxIcon className="w-56 h-56" />
299
+ </div>
300
+ <div className="relative z-10 space-y-4">
301
+ <h3 className="text-2xl font-extrabold tracking-tight">
302
+ Stateless Primitive
303
+ </h3>
304
+ <p className="text-muted-foreground text-base leading-relaxed">
305
+ Micro component không chứa <code>useState</code> hay{" "}
306
+ <code>useEffect</code>. State nằm ở Headless UI hoặc Macro.{" "}
307
+ <strong className="text-foreground">
308
+ Component càng đơn giản, càng ít bug.
309
+ </strong>
310
+ </p>
311
+ </div>
312
+ <div className="relative z-10 mt-auto pt-6 space-y-3">
313
+ <div className="p-3 rounded-xl border border-success/20 bg-success/5 text-[11px] font-mono shadow-sm flex items-center">
314
+ <span className="text-success font-bold mr-3 text-lg">✅</span>
315
+ <span className="text-success/90">
316
+ {"function Button({ ...props })"}
317
+ </span>
318
+ </div>
319
+ <div className="p-3 rounded-xl border border-destructive/20 bg-destructive/5 text-[11px] font-mono shadow-sm flex items-center opacity-70">
320
+ <span className="text-destructive font-bold mr-3 text-lg">
321
+
322
+ </span>
323
+ <span className="text-destructive/80 line-through">
324
+ {"const [open, setOpen] = useState()"}
325
+ </span>
326
+ </div>
327
+ </div>
328
+ </div>
329
+
330
+
331
+ <div className="break-inside-avoid mb-6 rounded-[2rem] border border-border bg-card/20 p-4 md:p-10 flex flex-col group overflow-hidden relative hover:bg-card/40 transition-colors duration-500">
332
+ <div className="absolute top-0 right-0 p-8 opacity-5 group-hover:opacity-10 transition-all pointer-events-none transform group-hover:scale-110 group-hover:rotate-12 duration-700">
333
+ <AccessibilityIcon className="w-56 h-56" />
334
+ </div>
335
+ <div className="relative z-10 space-y-4">
336
+ <h3 className="text-2xl font-extrabold tracking-tight">
337
+ Accessibility
338
+ </h3>
339
+ <p className="text-muted-foreground text-base leading-relaxed">
340
+ Semantic HTML, <code>aria-describedby</code> cho form, icon
341
+ trang trí tự ẩn khỏi screen reader.{" "}
342
+ <strong className="text-foreground">
343
+ Chuẩn WCAG — không cần nghĩ thêm.
344
+ </strong>
345
+ </p>
346
+ </div>
347
+ <div className="relative z-10 mt-auto pt-6 space-y-3">
348
+ <div className="p-3 rounded-xl border border-success/20 bg-success/5 text-[11px] font-mono shadow-sm flex items-center">
349
+ <span className="text-success font-bold mr-3 text-lg">✅</span>
350
+ <span className="text-success/90">
351
+ &lt;svg aria-hidden="true" /&gt;
352
+ </span>
353
+ </div>
354
+ <div className="p-3 rounded-xl border border-destructive/20 bg-destructive/5 text-[11px] font-mono shadow-sm flex items-center opacity-70">
355
+ <span className="text-destructive font-bold mr-3 text-lg">
356
+
357
+ </span>
358
+ <span className="text-destructive/80 line-through">
359
+ &lt;div role="button"&gt;
360
+ </span>
361
+ </div>
362
+ </div>
363
+ </div>
364
+
365
+ <div className="break-inside-avoid mb-6 rounded-[2rem] border border-border bg-card/20 p-4 md:p-10 flex flex-col group overflow-hidden relative hover:bg-card/40 transition-colors duration-500">
366
+ <div className="absolute top-0 right-0 p-8 opacity-5 group-hover:opacity-10 transition-all pointer-events-none transform group-hover:scale-110 group-hover:rotate-12 duration-700">
367
+ <DatabaseIcon className="w-56 h-56" />
368
+ </div>
369
+ <div className="relative z-10 space-y-4">
370
+ <h3 className="text-2xl font-extrabold tracking-tight">
371
+ Explicit State Contract
372
+ </h3>
373
+ <p className="text-muted-foreground text-base leading-relaxed">
374
+ Component công khai trạng thái qua <code>data-attributes</code>,
375
+ không phải qua imperative ref. Bạn style và animate trực tiếp
376
+ trên từng trạng thái, không cần JavaScript.{" "}
377
+ <strong className="text-foreground">
378
+ State là public API — tường minh và ổn định.
379
+ </strong>
380
+ </p>
381
+ </div>
382
+ <div className="relative z-10 mt-auto pt-8">
383
+ <div className="p-4 rounded-xl bg-foreground/5 border border-border/50 text-[11px] sm:text-xs font-mono shadow-inner space-y-2">
384
+ <div>
385
+ <span className="text-success">data-[state=open]</span>
386
+ <span className="text-muted-foreground">:rotate-180</span>
387
+ </div>
388
+ <div>
389
+ <span className="text-success">data-disabled</span>
390
+ <span className="text-muted-foreground">:opacity-50</span>
391
+ </div>
392
+ <div className="pt-1 border-t border-border/30">
393
+ <span className="text-destructive/60 line-through">
394
+ ref.current.isOpen
395
+ </span>
396
+ </div>
397
+ </div>
398
+ </div>
399
+ </div>
400
+
401
+ <div className="break-inside-avoid mb-6 rounded-[2rem] border border-border bg-card/20 p-4 md:p-10 flex flex-col group overflow-hidden relative hover:bg-card/40 transition-colors duration-500">
402
+ <div className="absolute top-0 right-0 p-8 opacity-5 group-hover:opacity-10 transition-all pointer-events-none transform group-hover:scale-110 group-hover:rotate-12 duration-700">
403
+ <SlidersHorizontalIcon className="w-56 h-56" />
404
+ </div>
405
+ <div className="relative z-10 space-y-4">
406
+ <h3 className="text-2xl font-extrabold tracking-tight">
407
+ 3-Layer Source Ownership
408
+ </h3>
409
+ <p className="text-muted-foreground text-base leading-relaxed">
410
+ Source được phân tầng: <code>micro/</code> (primitive không có
411
+ layout cứng nhắc), <code>macro/</code> (preset lắp ráp có chủ
412
+ đích), <code>index.css</code> (token toàn hệ thống).{" "}
413
+ <strong className="text-foreground">
414
+ Sửa ở tầng nào chỉ ảnh hưởng đến tầng đó.
415
+ </strong>
416
+ </p>
417
+ </div>
418
+ <div className="relative z-10 mt-auto pt-6 space-y-2">
419
+ <div className="p-3 rounded-xl border border-border bg-background/60 text-[11px] font-mono flex items-center gap-3">
420
+ <span className="text-destructive font-bold">CSS</span>
421
+ <span className="text-muted-foreground">
422
+ index.css — token toàn cục
423
+ </span>
424
+ </div>
425
+ <div className="p-3 rounded-xl border border-border bg-background/60 text-[11px] font-mono flex items-center gap-3">
426
+ <span className="text-warning font-bold">Macro</span>
427
+ <span className="text-muted-foreground">
428
+ macro/ — preset lắp ráp
429
+ </span>
430
+ </div>
431
+ <div className="p-3 rounded-xl border border-border bg-background/60 text-[11px] font-mono flex items-center gap-3">
432
+ <span className="text-success font-bold">Micro</span>
433
+ <span className="text-muted-foreground">
434
+ micro/ — primitive thuần
435
+ </span>
436
+ </div>
437
+ </div>
438
+ </div>
439
+
440
+ <div className="break-inside-avoid mb-6 rounded-[2rem] border border-border bg-card/20 p-4 md:p-10 flex flex-col group overflow-hidden relative hover:bg-card/40 transition-colors duration-500">
441
+ <div className="absolute top-0 right-0 p-8 opacity-5 group-hover:opacity-10 transition-all pointer-events-none transform group-hover:scale-110 group-hover:rotate-12 duration-700">
442
+ <BlocksIcon className="w-56 h-56" />
443
+ </div>
444
+ <div className="relative z-10 space-y-4">
445
+ <h3 className="text-2xl font-extrabold tracking-tight">
446
+ Pure Composition
447
+ </h3>
448
+ <p className="text-muted-foreground text-base leading-relaxed">
449
+ Design component theo dạng lắp ghép (ví dụ: Root, Trigger,
450
+ Content) thay vì ôm đồm nhận vào một mảng data rồi tự{" "}
451
+ <code>map()</code> bên trong.
452
+ </p>
453
+ </div>
454
+ <div className="relative z-10 mt-auto pt-6 space-y-3">
455
+ <div className="p-3 rounded-xl border border-success/20 bg-success/5 text-[11px] font-mono shadow-sm flex items-center">
456
+ <span className="text-success font-bold mr-3 text-lg">✅</span>
457
+ <span className="text-success/90">
458
+ &lt;Select&gt;
459
+ <br />
460
+ &nbsp;&nbsp;&lt;SelectTrigger/&gt;
461
+ <br />
462
+ &nbsp;&nbsp;&lt;SelectContent/&gt;
463
+ <br />
464
+ &lt;/Select&gt;
465
+ </span>
466
+ </div>
467
+ <div className="p-3 rounded-xl border border-destructive/20 bg-destructive/5 text-[11px] font-mono shadow-sm flex items-center opacity-70">
468
+ <span className="text-destructive font-bold mr-3 text-lg">
469
+
470
+ </span>
471
+ <span className="text-destructive/80 line-through">
472
+ &lt;Select items=&#123;[...]&#125; /&gt;
473
+ </span>
474
+ </div>
475
+ </div>
476
+ </div>
477
+
478
+ </div>
479
+
480
+ <section className="mt-16 mb-16">
481
+ <div className="rounded-[2.5rem] border border-warning/30 bg-warning/5 p-10 md:p-16 shadow-xl relative overflow-hidden group">
482
+ <div className="absolute -top-10 -right-10 p-8 opacity-10 pointer-events-none group-hover:rotate-12 group-hover:scale-125 transition-all duration-1000 text-warning">
483
+ <SparklesIcon className="size-64 md:size-[400px]" />
484
+ </div>
485
+
486
+ <div className="relative z-10 max-w-3xl mb-14 space-y-5">
487
+ <h3 className="text-3xl md:text-5xl font-extrabold tracking-tight text-warning">
488
+ Scoped Theme Tunnel
489
+ </h3>
490
+ <p className="text-muted-foreground text-xl leading-relaxed">
491
+ Tooltip hay Dialog thường bị <strong className="text-foreground">mất theme (Dark/Light cục bộ)</strong> khi nhảy ra ngoài DOM tree qua cơ chế Portaling.
492
+ </p>
493
+ <p className="text-muted-foreground text-xl leading-relaxed">
494
+ Nhờ <strong>Zero-Portal API</strong>, khả năng giữ theme đã được nhúng sẵn vào các <code className="text-sm bg-warning/20 text-warning px-1.5 py-0.5 rounded">*Content</code> (VD: <code className="text-sm bg-warning/20 text-warning px-1.5 py-0.5 rounded">DialogContent</code>). Mọi thứ hoạt động trơn tru tự động, bạn không cần phải import hay bọc <code className="text-sm bg-warning/20 text-warning px-1.5 py-0.5 rounded">ThemeWrapper</code> thủ công nữa!
495
+ </p>
496
+ </div>
497
+
498
+ <div className="relative z-10 grid sm:grid-cols-2 gap-6 max-w-3xl">
499
+ <div className="p-6 rounded-2xl border border-success/30 bg-success/10 shadow-sm flex flex-col gap-2">
500
+ <div className="text-success font-semibold text-lg flex items-center gap-2">
501
+ ✅ gladvn
502
+ </div>
503
+ <p className="text-success/80 text-sm leading-relaxed">
504
+ Tooltip, Dialog trong dark section luôn đúng màu — kể cả khi
505
+ Portal render ra{" "}
506
+ <code className="opacity-80">document.body</code>.
507
+ </p>
508
+ </div>
509
+ <div className="p-6 rounded-2xl border border-destructive/30 bg-destructive/10 shadow-sm opacity-80 flex flex-col gap-2">
510
+ <div className="text-destructive font-semibold text-lg flex items-center gap-2">
511
+ ❌ Thư viện khác
512
+ </div>
513
+ <p className="text-destructive/80 text-sm leading-relaxed">
514
+ Tooltip, Dialog "trắng lạc quẻ" — theme bị mất khi vượt Portal.
515
+ </p>
516
+ </div>
517
+ </div>
518
+
519
+ <div className="relative z-10 mt-10">
520
+ <Button
521
+ render={<a href="/dialog" />}
522
+ nativeButton={false}
523
+ variant="outline"
524
+ color="warning"
525
+ className="gap-2 font-bold px-6 py-5 rounded-xl border-warning/30 bg-warning/10 hover:bg-warning/20 shadow-sm"
526
+ >
527
+ Xem demo thực tế
528
+ <ArrowRightIcon className="size-4" />
529
+ </Button>
530
+ </div>
531
+ </div>
532
+ </section>
533
+ </div>
534
+ );
535
+ }