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.
- package/README.md +1 -1
- package/package.json +1 -1
- package/scripts/strip-comments.ts +79 -0
- package/src/blocks/auth-form.tsx +34 -30
- package/src/blocks/auth-recovery.tsx +9 -13
- package/src/blocks/auth-split.tsx +46 -36
- package/src/blocks/settings.tsx +84 -117
- package/src/components/macro/alert-preset.tsx +3 -1
- package/src/components/macro/carousel-preset.tsx +0 -1
- package/src/components/macro/checkbox-preset.test.tsx +2 -2
- package/src/components/macro/checkbox-preset.tsx +1 -2
- package/src/components/macro/command-preset.tsx +1 -1
- package/src/components/macro/date-picker.tsx +5 -18
- package/src/components/macro/dialog-preset.tsx +5 -3
- package/src/components/macro/input-preset.tsx +0 -1
- package/src/components/macro/select-preset.tsx +1 -1
- package/src/components/macro/switch-preset.test.tsx +1 -1
- package/src/components/micro/accordion.test.tsx +6 -12
- package/src/components/micro/alert-dialog.tsx +0 -2
- package/src/components/micro/alert.test.tsx +5 -8
- package/src/components/micro/alert.tsx +0 -2
- package/src/components/micro/badge.test.tsx +5 -7
- package/src/components/micro/badge.tsx +1 -3
- package/src/components/micro/button.test.tsx +19 -26
- package/src/components/micro/button.tsx +3 -11
- package/src/components/micro/calendar.tsx +12 -13
- package/src/components/micro/card.test.tsx +3 -5
- package/src/components/micro/carousel.tsx +0 -1
- package/src/components/micro/chart.tsx +3 -2
- package/src/components/micro/checkbox.test.tsx +9 -18
- package/src/components/micro/combobox.tsx +1 -3
- package/src/components/micro/command.tsx +23 -11
- package/src/components/micro/context-menu.tsx +0 -2
- package/src/components/micro/dialog.test.tsx +6 -14
- package/src/components/micro/dialog.tsx +0 -2
- package/src/components/micro/drawer.tsx +0 -3
- package/src/components/micro/dropdown-menu.test.tsx +8 -14
- package/src/components/micro/dropdown-menu.tsx +0 -2
- package/src/components/micro/field.tsx +3 -3
- package/src/components/micro/hover-card.tsx +0 -2
- package/src/components/micro/input-group.tsx +9 -42
- package/src/components/micro/input.test.tsx +15 -24
- package/src/components/micro/navigation-menu.tsx +0 -2
- package/src/components/micro/popover.test.tsx +5 -9
- package/src/components/micro/progress.tsx +5 -1
- package/src/components/micro/select.test.tsx +5 -18
- package/src/components/micro/select.tsx +3 -5
- package/src/components/micro/separator.tsx +1 -1
- package/src/components/micro/sheet.test.tsx +6 -14
- package/src/components/micro/sheet.tsx +0 -2
- package/src/components/micro/sidebar.tsx +5 -6
- package/src/components/micro/sonner.tsx +0 -1
- package/src/components/micro/switch.test.tsx +9 -18
- package/src/components/micro/switch.tsx +1 -1
- package/src/components/micro/tabs.test.tsx +5 -11
- package/src/components/micro/theme-provider.tsx +0 -12
- package/src/components/micro/toggle-group.tsx +1 -12
- package/src/components/micro/tooltip.test.tsx +7 -12
- package/src/dev/App.tsx +6 -6
- package/src/dev/components/BlockViewer.tsx +15 -4
- package/src/dev/components/Container.tsx +20 -0
- package/src/dev/components/GladvnLogo.tsx +3 -9
- package/src/dev/components/code-highlighter.tsx +5 -3
- package/src/dev/components/showcase.tsx +116 -168
- package/src/dev/sections/buttons.tsx +4 -9
- package/src/dev/sections/display.tsx +68 -72
- package/src/dev/sections/feedback.tsx +304 -314
- package/src/dev/sections/forms.tsx +10 -14
- package/src/dev/sections/interactive.tsx +32 -32
- package/src/dev/sections/overview.tsx +2 -10
- package/src/dev/showcase/accordion.tsx +512 -554
- package/src/dev/showcase/alert-dialog.tsx +525 -565
- package/src/dev/showcase/alert.tsx +352 -402
- package/src/dev/showcase/aspect-ratio.tsx +167 -193
- package/src/dev/showcase/avatar.tsx +231 -269
- package/src/dev/showcase/badge.tsx +92 -140
- package/src/dev/showcase/breadcrumb.tsx +113 -135
- package/src/dev/showcase/button.tsx +140 -173
- package/src/dev/showcase/calendar.tsx +187 -237
- package/src/dev/showcase/card.tsx +229 -261
- package/src/dev/showcase/carousel.tsx +288 -315
- package/src/dev/showcase/chart.tsx +44 -50
- package/src/dev/showcase/checkbox.tsx +286 -330
- package/src/dev/showcase/collapsible.tsx +143 -160
- package/src/dev/showcase/combobox.tsx +327 -369
- package/src/dev/showcase/command.tsx +106 -120
- package/src/dev/showcase/context-menu.tsx +93 -107
- package/src/dev/showcase/dialog.tsx +585 -630
- package/src/dev/showcase/drawer.tsx +176 -196
- package/src/dev/showcase/dropdown-menu.tsx +183 -201
- package/src/dev/showcase/empty.tsx +232 -274
- package/src/dev/showcase/hover-card.tsx +153 -180
- package/src/dev/showcase/input-group.tsx +221 -253
- package/src/dev/showcase/input-otp.tsx +204 -250
- package/src/dev/showcase/input.tsx +246 -325
- package/src/dev/showcase/item.tsx +134 -152
- package/src/dev/showcase/kbd.tsx +149 -172
- package/src/dev/showcase/label.tsx +50 -68
- package/src/dev/showcase/menubar.tsx +194 -213
- package/src/dev/showcase/navigation-menu.tsx +119 -133
- package/src/dev/showcase/overview-components/ArchitectureSection.tsx +126 -0
- package/src/dev/showcase/overview-components/CodeBlock.tsx +50 -0
- package/src/dev/showcase/overview-components/ColorPaletteSection.tsx +44 -0
- package/src/dev/showcase/overview-components/DashboardPreview.tsx +159 -0
- package/src/dev/showcase/overview-components/FeatureGridSection.tsx +535 -0
- package/src/dev/showcase/overview-components/FooterCTA.tsx +137 -0
- package/src/dev/showcase/overview-components/HeroSection.tsx +65 -0
- package/src/dev/showcase/overview-components/PrinciplesSection.tsx +128 -0
- package/src/dev/showcase/overview.tsx +21 -1163
- package/src/dev/showcase/pagination.tsx +144 -190
- package/src/dev/showcase/popover.tsx +181 -196
- package/src/dev/showcase/progress.tsx +141 -189
- package/src/dev/showcase/radio-group.tsx +272 -332
- package/src/dev/showcase/resizable.tsx +119 -141
- package/src/dev/showcase/scroll-area.tsx +21 -36
- package/src/dev/showcase/select.tsx +262 -322
- package/src/dev/showcase/separator.tsx +75 -73
- package/src/dev/showcase/sheet.tsx +333 -361
- package/src/dev/showcase/sidebar.tsx +53 -59
- package/src/dev/showcase/skeleton.tsx +93 -112
- package/src/dev/showcase/slider.tsx +244 -296
- package/src/dev/showcase/sonner.tsx +251 -258
- package/src/dev/showcase/spinner.tsx +46 -67
- package/src/dev/showcase/switch.tsx +298 -362
- package/src/dev/showcase/table.tsx +76 -80
- package/src/dev/showcase/tabs.tsx +302 -355
- package/src/dev/showcase/textarea.tsx +240 -293
- package/src/dev/showcase/toast.tsx +48 -54
- package/src/dev/showcase/toggle-group.tsx +104 -129
- package/src/dev/showcase/toggle.tsx +82 -102
- package/src/dev/showcase/tooltip.tsx +173 -192
- package/src/dev/showcase/why.tsx +6 -12
- package/src/hooks/use-mobile.test.ts +3 -2
- 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
|
+
<Button render={<Link/>}>
|
|
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
|
+
<Button as="a" href="/">
|
|
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
|
+
<svg aria-hidden="true" />
|
|
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
|
+
<div role="button">
|
|
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
|
+
<Select>
|
|
459
|
+
<br />
|
|
460
|
+
<SelectTrigger/>
|
|
461
|
+
<br />
|
|
462
|
+
<SelectContent/>
|
|
463
|
+
<br />
|
|
464
|
+
</Select>
|
|
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
|
+
<Select items={[...]} />
|
|
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
|
+
}
|