gladvn 0.2.17 → 0.2.19
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/bin/cli.js +9 -6
- package/dist/components/macro/accordion-preset.d.ts.map +1 -1
- package/dist/components/macro/alert-dialog-preset.d.ts.map +1 -1
- package/dist/components/macro/alert-preset.d.ts.map +1 -1
- package/dist/components/macro/avatar-preset.d.ts.map +1 -1
- package/dist/components/macro/breadcrumb-preset.d.ts.map +1 -1
- package/dist/components/macro/card-preset.d.ts.map +1 -1
- package/dist/components/macro/carousel-preset.d.ts.map +1 -1
- package/dist/components/macro/checkbox-preset.d.ts.map +1 -1
- package/dist/components/macro/combobox-preset.d.ts.map +1 -1
- package/dist/components/macro/command-preset.d.ts +1 -1
- package/dist/components/macro/command-preset.d.ts.map +1 -1
- package/dist/components/macro/date-picker.d.ts.map +1 -1
- package/dist/components/macro/dialog-preset.d.ts.map +1 -1
- package/dist/components/macro/empty-preset.d.ts.map +1 -1
- package/dist/components/macro/field-preset.d.ts.map +1 -1
- package/dist/components/macro/input-otp-preset.d.ts +6 -0
- package/dist/components/macro/input-otp-preset.d.ts.map +1 -1
- package/dist/components/macro/input-preset.d.ts +1 -1
- package/dist/components/macro/input-preset.d.ts.map +1 -1
- package/dist/components/macro/pagination-preset.d.ts.map +1 -1
- package/dist/components/macro/progress-preset.d.ts.map +1 -1
- package/dist/components/macro/radio-group-preset.d.ts.map +1 -1
- package/dist/components/macro/select-preset.d.ts.map +1 -1
- package/dist/components/macro/slider-preset.d.ts.map +1 -1
- package/dist/components/macro/switch-preset.d.ts.map +1 -1
- package/dist/components/macro/tabs-preset.d.ts +1 -1
- package/dist/components/macro/tabs-preset.d.ts.map +1 -1
- package/dist/components/macro/textarea-preset.d.ts +1 -1
- package/dist/components/macro/textarea-preset.d.ts.map +1 -1
- package/dist/components/micro/accordion.d.ts +7 -0
- package/dist/components/micro/accordion.d.ts.map +1 -1
- package/dist/components/micro/alert-dialog.d.ts.map +1 -1
- package/dist/components/micro/alert.d.ts +7 -0
- package/dist/components/micro/alert.d.ts.map +1 -1
- package/dist/components/micro/aspect-ratio.d.ts +7 -0
- package/dist/components/micro/aspect-ratio.d.ts.map +1 -1
- package/dist/components/micro/avatar.d.ts.map +1 -1
- package/dist/components/micro/badge.d.ts +8 -1
- package/dist/components/micro/badge.d.ts.map +1 -1
- package/dist/components/micro/breadcrumb.d.ts +7 -0
- package/dist/components/micro/breadcrumb.d.ts.map +1 -1
- package/dist/components/micro/button.d.ts +8 -1
- package/dist/components/micro/button.d.ts.map +1 -1
- package/dist/components/micro/calendar.d.ts +2 -2
- package/dist/components/micro/calendar.d.ts.map +1 -1
- package/dist/components/micro/carousel.d.ts.map +1 -1
- package/dist/components/micro/chart.d.ts.map +1 -1
- package/dist/components/micro/checkbox.d.ts.map +1 -1
- package/dist/components/micro/collapsible.d.ts.map +1 -1
- package/dist/components/micro/combobox.d.ts.map +1 -1
- package/dist/components/micro/command.d.ts.map +1 -1
- package/dist/components/micro/context-menu.d.ts.map +1 -1
- package/dist/components/micro/dialog.d.ts.map +1 -1
- package/dist/components/micro/drawer.d.ts.map +1 -1
- package/dist/components/micro/dropdown-menu.d.ts.map +1 -1
- package/dist/components/micro/empty.d.ts +7 -0
- package/dist/components/micro/empty.d.ts.map +1 -1
- package/dist/components/micro/field.d.ts.map +1 -1
- package/dist/components/micro/hover-card.d.ts +1 -1
- package/dist/components/micro/hover-card.d.ts.map +1 -1
- package/dist/components/micro/input-group.d.ts.map +1 -1
- package/dist/components/micro/input-otp.d.ts.map +1 -1
- package/dist/components/micro/input.d.ts +7 -0
- package/dist/components/micro/input.d.ts.map +1 -1
- package/dist/components/micro/item.d.ts.map +1 -1
- package/dist/components/micro/label.d.ts.map +1 -1
- package/dist/components/micro/menubar.d.ts.map +1 -1
- package/dist/components/micro/navigation-menu.d.ts +8 -1
- package/dist/components/micro/navigation-menu.d.ts.map +1 -1
- package/dist/components/micro/pagination.d.ts.map +1 -1
- package/dist/components/micro/popover.d.ts.map +1 -1
- package/dist/components/micro/progress.d.ts.map +1 -1
- package/dist/components/micro/radio-group.d.ts.map +1 -1
- package/dist/components/micro/select.d.ts +1 -1
- package/dist/components/micro/select.d.ts.map +1 -1
- package/dist/components/micro/sheet.d.ts.map +1 -1
- package/dist/components/micro/sidebar.d.ts.map +1 -1
- package/dist/components/micro/skeleton.d.ts +7 -0
- package/dist/components/micro/skeleton.d.ts.map +1 -1
- package/dist/components/micro/slider.d.ts +7 -0
- package/dist/components/micro/slider.d.ts.map +1 -1
- package/dist/components/micro/sonner.d.ts.map +1 -1
- package/dist/components/micro/spinner.d.ts.map +1 -1
- package/dist/components/micro/switch.d.ts.map +1 -1
- package/dist/components/micro/table.d.ts.map +1 -1
- package/dist/components/micro/tabs.d.ts +1 -1
- package/dist/components/micro/tabs.d.ts.map +1 -1
- package/dist/components/micro/textarea.d.ts +7 -0
- package/dist/components/micro/textarea.d.ts.map +1 -1
- package/dist/components/micro/toggle-group.d.ts.map +1 -1
- package/dist/components/micro/toggle.d.ts.map +1 -1
- package/dist/components/micro/tooltip.d.ts +1 -1
- package/dist/components/micro/tooltip.d.ts.map +1 -1
- package/dist/dev/App.d.ts.map +1 -1
- package/dist/dev/components/code-highlighter.d.ts.map +1 -1
- package/dist/dev/components/dev-context.d.ts.map +1 -1
- package/dist/dev/components/showcase.d.ts +1 -1
- package/dist/dev/components/showcase.d.ts.map +1 -1
- package/dist/dev/data.d.ts.map +1 -1
- package/dist/dev/main.d.ts.map +1 -1
- package/dist/dev/sections/buttons.d.ts.map +1 -1
- package/dist/dev/sections/feedback.d.ts.map +1 -1
- package/dist/dev/sections/overview.d.ts.map +1 -1
- package/dist/dev/showcase/accordion.d.ts.map +1 -1
- package/dist/dev/showcase/alert-dialog.d.ts.map +1 -1
- package/dist/dev/showcase/alert.d.ts.map +1 -1
- package/dist/dev/showcase/aspect-ratio.d.ts.map +1 -1
- package/dist/dev/showcase/avatar.d.ts.map +1 -1
- package/dist/dev/showcase/breadcrumb.d.ts.map +1 -1
- package/dist/dev/showcase/button.d.ts.map +1 -1
- package/dist/dev/showcase/calendar.d.ts.map +1 -1
- package/dist/dev/showcase/card.d.ts.map +1 -1
- package/dist/dev/showcase/carousel.d.ts.map +1 -1
- package/dist/dev/showcase/chart.d.ts.map +1 -1
- package/dist/dev/showcase/checkbox.d.ts.map +1 -1
- package/dist/dev/showcase/collapsible.d.ts.map +1 -1
- package/dist/dev/showcase/combobox.d.ts.map +1 -1
- package/dist/dev/showcase/command.d.ts.map +1 -1
- package/dist/dev/showcase/context-menu.d.ts.map +1 -1
- package/dist/dev/showcase/dialog.d.ts.map +1 -1
- package/dist/dev/showcase/drawer.d.ts.map +1 -1
- package/dist/dev/showcase/dropdown-menu.d.ts.map +1 -1
- package/dist/dev/showcase/empty.d.ts.map +1 -1
- package/dist/dev/showcase/hover-card.d.ts.map +1 -1
- package/dist/dev/showcase/input-group.d.ts.map +1 -1
- package/dist/dev/showcase/input-otp.d.ts.map +1 -1
- package/dist/dev/showcase/input.d.ts.map +1 -1
- package/dist/dev/showcase/item.d.ts.map +1 -1
- package/dist/dev/showcase/kbd.d.ts.map +1 -1
- package/dist/dev/showcase/label.d.ts.map +1 -1
- package/dist/dev/showcase/menubar.d.ts.map +1 -1
- package/dist/dev/showcase/navigation-menu.d.ts.map +1 -1
- package/dist/dev/showcase/overview.d.ts.map +1 -1
- package/dist/dev/showcase/pagination.d.ts.map +1 -1
- package/dist/dev/showcase/popover.d.ts.map +1 -1
- package/dist/dev/showcase/progress.d.ts.map +1 -1
- package/dist/dev/showcase/radio-group.d.ts.map +1 -1
- package/dist/dev/showcase/resizable.d.ts.map +1 -1
- package/dist/dev/showcase/scroll-area.d.ts.map +1 -1
- package/dist/dev/showcase/select.d.ts.map +1 -1
- package/dist/dev/showcase/separator.d.ts.map +1 -1
- package/dist/dev/showcase/sheet.d.ts.map +1 -1
- package/dist/dev/showcase/sidebar.d.ts.map +1 -1
- package/dist/dev/showcase/skeleton.d.ts.map +1 -1
- package/dist/dev/showcase/slider.d.ts.map +1 -1
- package/dist/dev/showcase/sonner.d.ts.map +1 -1
- package/dist/dev/showcase/spinner.d.ts.map +1 -1
- package/dist/dev/showcase/switch.d.ts.map +1 -1
- package/dist/dev/showcase/table.d.ts.map +1 -1
- package/dist/dev/showcase/tabs.d.ts.map +1 -1
- package/dist/dev/showcase/textarea.d.ts.map +1 -1
- package/dist/dev/showcase/theme-provider.d.ts.map +1 -1
- package/dist/dev/showcase/toast.d.ts.map +1 -1
- package/dist/dev/showcase/toggle-group.d.ts.map +1 -1
- package/dist/dev/showcase/toggle.d.ts.map +1 -1
- package/dist/dev/showcase/tooltip.d.ts.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/utils.d.ts.map +1 -1
- package/package.json +3 -1
- package/scripts/format-codestrings.ts +87 -0
- package/scripts/organize-imports.ts +21 -0
- package/scripts/regex-format.cjs +67 -0
- package/scripts/tmp.tsx +25 -0
- package/src/components/macro/accordion-preset.test.tsx +1 -0
- package/src/components/macro/accordion-preset.tsx +2 -1
- package/src/components/macro/alert-dialog-preset.tsx +44 -43
- package/src/components/macro/alert-preset.tsx +7 -3
- package/src/components/macro/avatar-preset.tsx +2 -1
- package/src/components/macro/breadcrumb-preset.tsx +2 -1
- package/src/components/macro/card-preset.tsx +2 -1
- package/src/components/macro/carousel-preset.tsx +5 -2
- package/src/components/macro/checkbox-preset.test.tsx +1 -0
- package/src/components/macro/checkbox-preset.tsx +6 -2
- package/src/components/macro/combobox-preset.tsx +6 -3
- package/src/components/macro/command-preset.tsx +7 -3
- package/src/components/macro/date-picker.tsx +77 -59
- package/src/components/macro/dialog-preset.tsx +42 -38
- package/src/components/macro/empty-preset.tsx +2 -1
- package/src/components/macro/field-preset.test.tsx +1 -0
- package/src/components/macro/field-preset.tsx +2 -1
- package/src/components/macro/input-otp-preset.tsx +6 -2
- package/src/components/macro/input-preset.test.tsx +1 -0
- package/src/components/macro/input-preset.tsx +4 -2
- package/src/components/macro/pagination-preset.tsx +3 -1
- package/src/components/macro/progress-preset.test.tsx +1 -0
- package/src/components/macro/progress-preset.tsx +2 -1
- package/src/components/macro/radio-group-preset.tsx +4 -1
- package/src/components/macro/select-preset.tsx +35 -30
- package/src/components/macro/slider-preset.test.tsx +1 -0
- package/src/components/macro/slider-preset.tsx +4 -1
- package/src/components/macro/switch-preset.test.tsx +1 -0
- package/src/components/macro/switch-preset.tsx +4 -1
- package/src/components/macro/tabs-preset.test.tsx +1 -0
- package/src/components/macro/tabs-preset.tsx +4 -2
- package/src/components/macro/textarea-preset.test.tsx +1 -0
- package/src/components/macro/textarea-preset.tsx +4 -1
- package/src/components/micro/accordion.tsx +3 -2
- package/src/components/micro/alert-dialog.tsx +2 -1
- package/src/components/micro/alert.tsx +3 -2
- package/src/components/micro/aspect-ratio.tsx +2 -1
- package/src/components/micro/avatar.tsx +2 -1
- package/src/components/micro/badge.tsx +3 -3
- package/src/components/micro/breadcrumb.tsx +3 -2
- package/src/components/micro/button.test.tsx +1 -0
- package/src/components/micro/button.tsx +3 -3
- package/src/components/micro/calendar.tsx +10 -9
- package/src/components/micro/carousel.tsx +3 -2
- package/src/components/micro/chart.tsx +1 -0
- package/src/components/micro/checkbox.tsx +2 -2
- package/src/components/micro/collapsible.tsx +4 -2
- package/src/components/micro/combobox.tsx +41 -29
- package/src/components/micro/command.tsx +23 -16
- package/src/components/micro/context-menu.tsx +3 -2
- package/src/components/micro/dialog.tsx +2 -1
- package/src/components/micro/drawer.tsx +2 -1
- package/src/components/micro/dropdown-menu.tsx +3 -2
- package/src/components/micro/empty.tsx +2 -1
- package/src/components/micro/field.tsx +4 -3
- package/src/components/micro/hover-card.tsx +20 -19
- package/src/components/micro/input-group.tsx +2 -1
- package/src/components/micro/input-otp.tsx +3 -2
- package/src/components/micro/input.tsx +3 -2
- package/src/components/micro/item.tsx +1 -0
- package/src/components/micro/label.tsx +2 -1
- package/src/components/micro/menubar.tsx +2 -1
- package/src/components/micro/navigation-menu.tsx +18 -17
- package/src/components/micro/pagination.tsx +2 -1
- package/src/components/micro/popover.tsx +2 -1
- package/src/components/micro/progress.tsx +2 -1
- package/src/components/micro/radio-group.tsx +3 -3
- package/src/components/micro/select.tsx +5 -4
- package/src/components/micro/sheet.tsx +2 -1
- package/src/components/micro/sidebar.tsx +4 -1
- package/src/components/micro/skeleton.tsx +2 -1
- package/src/components/micro/slider.tsx +4 -1
- package/src/components/micro/sonner.tsx +2 -1
- package/src/components/micro/spinner.tsx +1 -2
- package/src/components/micro/switch.tsx +2 -2
- package/src/components/micro/table.tsx +2 -1
- package/src/components/micro/tabs.tsx +4 -3
- package/src/components/micro/textarea.tsx +2 -1
- package/src/components/micro/toggle-group.tsx +1 -0
- package/src/components/micro/toggle.tsx +1 -3
- package/src/components/micro/tooltip.tsx +9 -3
- package/src/dev/App.tsx +66 -41
- package/src/dev/components/code-highlighter.tsx +2 -1
- package/src/dev/components/dev-context.tsx +1 -0
- package/src/dev/components/showcase.tsx +13 -14
- package/src/dev/data.ts +206 -52
- package/src/dev/main.tsx +4 -4
- package/src/dev/sections/buttons.tsx +14 -12
- package/src/dev/sections/feedback.tsx +7 -2
- package/src/dev/sections/forms.tsx +11 -11
- package/src/dev/sections/overview.tsx +2 -1
- package/src/dev/showcase/accordion.tsx +399 -314
- package/src/dev/showcase/alert-dialog.tsx +387 -384
- package/src/dev/showcase/alert.tsx +271 -258
- package/src/dev/showcase/aspect-ratio.tsx +102 -105
- package/src/dev/showcase/avatar.tsx +216 -145
- package/src/dev/showcase/badge.tsx +78 -50
- package/src/dev/showcase/breadcrumb.tsx +88 -85
- package/src/dev/showcase/button.tsx +72 -96
- package/src/dev/showcase/calendar.tsx +41 -39
- package/src/dev/showcase/card.tsx +170 -148
- package/src/dev/showcase/carousel.tsx +239 -77
- package/src/dev/showcase/chart.tsx +5 -4
- package/src/dev/showcase/checkbox.tsx +206 -140
- package/src/dev/showcase/collapsible.tsx +108 -84
- package/src/dev/showcase/combobox.tsx +272 -199
- package/src/dev/showcase/command.tsx +31 -28
- package/src/dev/showcase/context-menu.tsx +94 -77
- package/src/dev/showcase/dialog.tsx +445 -424
- package/src/dev/showcase/drawer.tsx +142 -135
- package/src/dev/showcase/dropdown-menu.tsx +165 -161
- package/src/dev/showcase/empty.tsx +173 -158
- package/src/dev/showcase/hover-card.tsx +92 -52
- package/src/dev/showcase/input-group.tsx +193 -160
- package/src/dev/showcase/input-otp.tsx +109 -99
- package/src/dev/showcase/input.tsx +78 -42
- package/src/dev/showcase/item.tsx +101 -98
- package/src/dev/showcase/kbd.tsx +78 -62
- package/src/dev/showcase/label.tsx +16 -23
- package/src/dev/showcase/menubar.tsx +274 -251
- package/src/dev/showcase/navigation-menu.tsx +175 -170
- package/src/dev/showcase/overview.tsx +164 -148
- package/src/dev/showcase/pagination.tsx +101 -69
- package/src/dev/showcase/popover.tsx +113 -86
- package/src/dev/showcase/progress.tsx +99 -69
- package/src/dev/showcase/radio-group.tsx +217 -134
- package/src/dev/showcase/resizable.tsx +65 -55
- package/src/dev/showcase/scroll-area.tsx +32 -22
- package/src/dev/showcase/select.tsx +192 -136
- package/src/dev/showcase/separator.tsx +28 -24
- package/src/dev/showcase/sheet.tsx +182 -134
- package/src/dev/showcase/sidebar.tsx +9 -5
- package/src/dev/showcase/skeleton.tsx +54 -59
- package/src/dev/showcase/slider.tsx +158 -129
- package/src/dev/showcase/sonner.tsx +3 -5
- package/src/dev/showcase/spinner.tsx +22 -18
- package/src/dev/showcase/switch.tsx +207 -110
- package/src/dev/showcase/table.tsx +44 -32
- package/src/dev/showcase/tabs.tsx +272 -267
- package/src/dev/showcase/textarea.tsx +162 -116
- package/src/dev/showcase/theme-provider.tsx +596 -534
- package/src/dev/showcase/toast.tsx +37 -38
- package/src/dev/showcase/toggle-group.tsx +87 -39
- package/src/dev/showcase/toggle.tsx +36 -27
- package/src/dev/showcase/tooltip.tsx +154 -119
- package/src/lib/utils.test.ts +1 -0
- package/src/lib/utils.ts +1 -1
- package/src/styles/gladvn.css +0 -1
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
|
|
1
3
|
import {
|
|
2
4
|
AccessibilityIcon,
|
|
3
5
|
ArrowRightIcon,
|
|
4
6
|
BlocksIcon,
|
|
5
7
|
BoxIcon,
|
|
6
8
|
CheckIcon,
|
|
9
|
+
CodeIcon,
|
|
7
10
|
ComponentIcon,
|
|
8
11
|
CopyIcon,
|
|
9
12
|
DatabaseIcon,
|
|
@@ -13,15 +16,15 @@ import {
|
|
|
13
16
|
ShieldCheckIcon,
|
|
14
17
|
SlidersHorizontalIcon,
|
|
15
18
|
SparklesIcon,
|
|
16
|
-
CodeIcon,
|
|
17
19
|
} from "lucide-react";
|
|
18
|
-
import { useEffect, useState } from "react";
|
|
19
20
|
import { toast } from "sonner";
|
|
20
|
-
import { GladvnLogo } from "../../dev/components/GladvnLogo";
|
|
21
21
|
|
|
22
22
|
import { ProgressPreset as Progress } from "../../components/macro/progress-preset";
|
|
23
|
-
import {
|
|
24
|
-
|
|
23
|
+
import {
|
|
24
|
+
Avatar,
|
|
25
|
+
AvatarFallback,
|
|
26
|
+
AvatarImage,
|
|
27
|
+
} from "../../components/micro/avatar";
|
|
25
28
|
import { Button } from "../../components/micro/button";
|
|
26
29
|
import {
|
|
27
30
|
Card,
|
|
@@ -34,8 +37,9 @@ import {
|
|
|
34
37
|
Select,
|
|
35
38
|
SelectContent,
|
|
36
39
|
SelectItem,
|
|
40
|
+
SelectPortal,
|
|
37
41
|
SelectTrigger,
|
|
38
|
-
SelectValue,
|
|
42
|
+
SelectValue,
|
|
39
43
|
} from "../../components/micro/select";
|
|
40
44
|
import { Switch } from "../../components/micro/switch";
|
|
41
45
|
import { ColorSwatch } from "../../dev/components/showcase";
|
|
@@ -115,12 +119,10 @@ export default function OverviewSection() {
|
|
|
115
119
|
</div>
|
|
116
120
|
|
|
117
121
|
<div className="container relative z-10 flex flex-col items-center text-center px-4">
|
|
118
|
-
<div
|
|
119
|
-
className="inline-flex items-center gap-2 px-4 py-1.5 mb-8 text-sm font-medium rounded-full border border-primary/20 bg-background/50 backdrop-blur-md shadow-sm animate-fade-up"
|
|
120
|
-
>
|
|
122
|
+
<div className="inline-flex items-center gap-2 px-4 py-1.5 mb-8 text-sm font-medium rounded-full border border-primary/20 bg-background/50 backdrop-blur-md shadow-sm animate-fade-up">
|
|
121
123
|
<CodeIcon className="w-3.5 h-3.5 text-primary" />
|
|
122
124
|
<span className="text-muted-foreground">
|
|
123
|
-
Copy
|
|
125
|
+
Copy mã · Tuỳ biến tự do · Không lock-in
|
|
124
126
|
</span>
|
|
125
127
|
</div>
|
|
126
128
|
|
|
@@ -132,7 +134,7 @@ export default function OverviewSection() {
|
|
|
132
134
|
Tinh tế. Đẳng cấp.
|
|
133
135
|
</span>
|
|
134
136
|
<span className="block mt-2 bg-gradient-to-r leading-[1.2] from-primary via-info to-primary bg-[length:200%_auto] bg-clip-text text-transparent animate-[spin_8s_linear_infinite] [animation-name:gradient] [animation-duration:8s] [animation-timing-function:linear] [animation-iteration-count:infinite]">
|
|
135
|
-
|
|
137
|
+
Của bạn.
|
|
136
138
|
</span>
|
|
137
139
|
</h1>
|
|
138
140
|
|
|
@@ -140,11 +142,14 @@ export default function OverviewSection() {
|
|
|
140
142
|
className="max-w-2xl text-lg md:text-xl text-muted-foreground leading-relaxed mb-10 animate-fade-up"
|
|
141
143
|
style={{ animationDelay: "200ms", animationFillMode: "both" }}
|
|
142
144
|
>
|
|
143
|
-
|
|
144
|
-
|
|
145
|
+
Phần lớn component library giữ code trong node_modules — bạn dùng
|
|
146
|
+
được nhưng không sửa được. gladvn copy thẳng vào{" "}
|
|
147
|
+
<code className="text-sm bg-primary/20 text-primary px-1.5 py-0.5 rounded">
|
|
148
|
+
src/
|
|
149
|
+
</code>{" "}
|
|
150
|
+
của bạn.{" "}
|
|
145
151
|
<strong className="text-foreground">
|
|
146
|
-
|
|
147
|
-
vendor lock-in.
|
|
152
|
+
Đọc được, sửa được, xóa được.
|
|
148
153
|
</strong>
|
|
149
154
|
</p>
|
|
150
155
|
</div>
|
|
@@ -243,7 +248,7 @@ export default function OverviewSection() {
|
|
|
243
248
|
Kiến trúc Micro/Macro
|
|
244
249
|
</h4>
|
|
245
250
|
<p className="text-xs text-muted-foreground font-medium mt-1">
|
|
246
|
-
|
|
251
|
+
Primitive nhỏ, lắp thành preset lớn
|
|
247
252
|
</p>
|
|
248
253
|
</div>
|
|
249
254
|
</div>
|
|
@@ -253,9 +258,11 @@ export default function OverviewSection() {
|
|
|
253
258
|
<DatabaseIcon className="size-6" />
|
|
254
259
|
</div>
|
|
255
260
|
<div>
|
|
256
|
-
<h4 className="font-bold text-sm">
|
|
261
|
+
<h4 className="font-bold text-sm">
|
|
262
|
+
Thiết kế theo Dữ liệu
|
|
263
|
+
</h4>
|
|
257
264
|
<p className="text-xs text-muted-foreground font-medium mt-1">
|
|
258
|
-
|
|
265
|
+
Truyền items vào root, không map() thủ công
|
|
259
266
|
</p>
|
|
260
267
|
</div>
|
|
261
268
|
</div>
|
|
@@ -265,7 +272,7 @@ export default function OverviewSection() {
|
|
|
265
272
|
<ShieldCheckIcon className="size-6" />
|
|
266
273
|
</div>
|
|
267
274
|
<div>
|
|
268
|
-
<h4 className="font-bold text-sm">
|
|
275
|
+
<h4 className="font-bold text-sm">Styling có Kỷ luật</h4>
|
|
269
276
|
<p className="text-xs text-muted-foreground font-medium mt-1">
|
|
270
277
|
Nói không với Magic CSS
|
|
271
278
|
</p>
|
|
@@ -302,12 +309,11 @@ export default function OverviewSection() {
|
|
|
302
309
|
<section className="container max-w-6xl mx-auto space-y-12 px-4">
|
|
303
310
|
<div className="text-center max-w-2xl mx-auto space-y-4">
|
|
304
311
|
<h2 className="text-3xl md:text-4xl font-extrabold tracking-tight">
|
|
305
|
-
|
|
312
|
+
Kiến trúc rõ ràng. Sửa không lo vỡ.
|
|
306
313
|
</h2>
|
|
307
314
|
<p className="text-muted-foreground text-lg">
|
|
308
|
-
Nhiều dự án bắt đầu gãy ở năm thứ hai —
|
|
309
|
-
không
|
|
310
|
-
thành{" "}
|
|
315
|
+
Nhiều dự án bắt đầu gãy ở năm thứ hai — muốn sửa mà không dám, vì
|
|
316
|
+
không biết gì sẽ vỡ theo. gladvn chia code thành{" "}
|
|
311
317
|
<strong className="text-foreground">các tầng rõ ràng</strong>
|
|
312
318
|
{", "}nên bạn luôn biết mình đang sửa ở đâu và ảnh hưởng đến đâu.
|
|
313
319
|
</p>
|
|
@@ -321,22 +327,22 @@ export default function OverviewSection() {
|
|
|
321
327
|
<div className="flex flex-col md:flex-row items-start gap-6 md:gap-8">
|
|
322
328
|
<div className="relative z-10 flex-1 space-y-6">
|
|
323
329
|
<div className="inline-flex items-center gap-2 px-4 py-1.5 rounded-full bg-primary text-primary-foreground text-sm font-bold uppercase tracking-wider shadow-lg shadow-primary/20">
|
|
324
|
-
<SparklesIcon className="size-4" />
|
|
330
|
+
<SparklesIcon className="size-4" /> Cốt lõi
|
|
325
331
|
</div>
|
|
326
332
|
<h3 className="text-3xl md:text-5xl font-extrabold tracking-tight">
|
|
327
333
|
Code là của bạn, 100%
|
|
328
334
|
</h3>
|
|
329
335
|
<p className="text-muted-foreground text-lg leading-relaxed max-w-2xl">
|
|
330
|
-
Chạy một lệnh — toàn bộ components, hooks, styles, contexts
|
|
331
|
-
|
|
336
|
+
Chạy một lệnh — toàn bộ components, hooks, styles, contexts được
|
|
337
|
+
copy thẳng vào thư mục{" "}
|
|
332
338
|
<code className="text-sm bg-primary/20 text-primary px-1.5 py-0.5 rounded">
|
|
333
339
|
src/
|
|
334
340
|
</code>{" "}
|
|
335
341
|
của bạn.{" "}
|
|
336
342
|
<strong className="text-foreground">
|
|
337
|
-
Không qua node_modules
|
|
343
|
+
Không qua node_modules. Không phụ thuộc vào ai.
|
|
338
344
|
</strong>{" "}
|
|
339
|
-
|
|
345
|
+
Đọc được, sửa được, xoá được từng dòng.
|
|
340
346
|
</p>
|
|
341
347
|
|
|
342
348
|
<div className="flex items-center gap-4 pt-2">
|
|
@@ -409,7 +415,6 @@ export default function OverviewSection() {
|
|
|
409
415
|
Tuỳ chỉnh theo từng tầng kiến trúc
|
|
410
416
|
</p>
|
|
411
417
|
<div className="grid sm:grid-cols-3 gap-4">
|
|
412
|
-
|
|
413
418
|
{/* MACRO — RECOMMENDED */}
|
|
414
419
|
<div className="p-5 rounded-2xl border-2 border-primary/40 bg-primary/5 space-y-3 relative">
|
|
415
420
|
<div className="absolute top-3 right-3 text-[10px] font-bold uppercase tracking-wider text-primary bg-primary/10 px-2 py-0.5 rounded-full">
|
|
@@ -419,7 +424,7 @@ export default function OverviewSection() {
|
|
|
419
424
|
src/components/macro/
|
|
420
425
|
</div>
|
|
421
426
|
<h4 className="font-bold text-foreground text-base">
|
|
422
|
-
|
|
427
|
+
Macro — Sửa an toàn
|
|
423
428
|
</h4>
|
|
424
429
|
<p className="text-sm text-muted-foreground leading-relaxed">
|
|
425
430
|
Bắt đầu ở đây. Mỗi Macro là một preset độc lập — thêm footer
|
|
@@ -441,7 +446,7 @@ export default function OverviewSection() {
|
|
|
441
446
|
src/components/micro/
|
|
442
447
|
</div>
|
|
443
448
|
<h4 className="font-bold text-foreground text-base">
|
|
444
|
-
|
|
449
|
+
Micro — Sửa cẩn thận
|
|
445
450
|
</h4>
|
|
446
451
|
<p className="text-sm text-muted-foreground leading-relaxed">
|
|
447
452
|
Micro là nền — mọi Macro đều xây trên nó. Sửa variant của
|
|
@@ -462,18 +467,17 @@ export default function OverviewSection() {
|
|
|
462
467
|
src/index.css
|
|
463
468
|
</div>
|
|
464
469
|
<h4 className="font-bold text-foreground text-base">
|
|
465
|
-
|
|
470
|
+
CSS Token — Đổi một chỗ, cả app thay đổi
|
|
466
471
|
</h4>
|
|
467
472
|
<p className="text-sm text-muted-foreground leading-relaxed">
|
|
468
|
-
CSS token quyết định màu, font, border-radius cho tất cả.
|
|
469
|
-
|
|
473
|
+
CSS token quyết định màu, font, border-radius cho tất cả. Đổi
|
|
474
|
+
một token ở đây thì{" "}
|
|
470
475
|
<strong className="text-foreground">
|
|
471
476
|
toàn bộ giao diện cập nhật ngay
|
|
472
477
|
</strong>
|
|
473
478
|
. Dùng khi muốn rebrand, không phải để vá lỗi lẻ tẻ.
|
|
474
479
|
</p>
|
|
475
480
|
</div>
|
|
476
|
-
|
|
477
481
|
</div>
|
|
478
482
|
</div>
|
|
479
483
|
</div>
|
|
@@ -489,19 +493,17 @@ export default function OverviewSection() {
|
|
|
489
493
|
Micro & Macro
|
|
490
494
|
</h3>
|
|
491
495
|
<p className="text-muted-foreground max-w-lg text-lg leading-relaxed">
|
|
492
|
-
Micro là component thuần — chỉ lo style, không ép layout.
|
|
493
|
-
|
|
496
|
+
Micro là component thuần — chỉ lo style, không ép layout. Macro
|
|
497
|
+
là preset — lắp ghép Micro thành giao diện hoàn chỉnh.
|
|
494
498
|
<strong className="text-foreground block mt-2">
|
|
495
499
|
Micro không bao giờ tự quyết layout. Việc đó thuộc về Macro.
|
|
496
500
|
</strong>
|
|
497
501
|
</p>
|
|
498
502
|
</div>
|
|
499
503
|
<div className="relative z-10 mt-auto pt-6 space-y-3">
|
|
500
|
-
<CodeBlock type="success" title="
|
|
504
|
+
<CodeBlock type="success" title="Đúng — Để Macro lo layout:">
|
|
501
505
|
<span className="text-success/80">
|
|
502
|
-
{
|
|
503
|
-
"/* Macro thấy toàn bộ cấu trúc nên gắn class thẳng vào đích */"
|
|
504
|
-
}
|
|
506
|
+
{"/* Macro biết con mình là gì → gắn class chính xác */"}
|
|
505
507
|
</span>
|
|
506
508
|
<br />
|
|
507
509
|
<span className="text-foreground">{"<AlertDialogFooter>"}</span>
|
|
@@ -519,14 +521,9 @@ export default function OverviewSection() {
|
|
|
519
521
|
</span>
|
|
520
522
|
</CodeBlock>
|
|
521
523
|
|
|
522
|
-
<CodeBlock
|
|
523
|
-
type="destructive"
|
|
524
|
-
title="Ép Layout ở Micro (Primitive):"
|
|
525
|
-
>
|
|
524
|
+
<CodeBlock type="destructive" title="Sai — Micro tự đoán layout:">
|
|
526
525
|
<span className="text-destructive/80">
|
|
527
|
-
{
|
|
528
|
-
"/* Micro mù mờ về thẻ con nên phải dùng Magic CSS đoán mò */"
|
|
529
|
-
}
|
|
526
|
+
{"/* Micro không biết con mình là gì → phải đoán bằng CSS */"}
|
|
530
527
|
</span>
|
|
531
528
|
<br />
|
|
532
529
|
<span className="text-foreground">{"<AlertDialogFooter"}</span>
|
|
@@ -556,22 +553,27 @@ export default function OverviewSection() {
|
|
|
556
553
|
Style Encapsulation
|
|
557
554
|
</h3>
|
|
558
555
|
<p className="text-muted-foreground text-base leading-relaxed">
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
<code>data-slot</code> — đã có sẵn contract rõ ràng.{" "}
|
|
556
|
+
Style của mỗi component không rò rỉ ra ngoài. Muốn tuỳ chỉnh thì
|
|
557
|
+
dùng <code>data-slot</code> — contract rõ ràng, có sẵn.{" "}
|
|
562
558
|
<strong className="text-foreground">
|
|
563
|
-
Refactor bên trong
|
|
559
|
+
Refactor bên trong mà không ảnh hưởng bên ngoài.
|
|
564
560
|
</strong>
|
|
565
561
|
</p>
|
|
566
562
|
</div>
|
|
567
563
|
<div className="relative z-10 mt-auto pt-6 space-y-3">
|
|
568
564
|
<div className="p-3 rounded-xl border border-destructive/20 bg-destructive/5 text-xs font-mono shadow-sm flex items-center">
|
|
569
|
-
<span className="text-destructive font-bold mr-3 text-lg"
|
|
570
|
-
|
|
565
|
+
<span className="text-destructive font-bold mr-3 text-lg">
|
|
566
|
+
❌
|
|
567
|
+
</span>
|
|
568
|
+
<span className="opacity-80 line-through">
|
|
569
|
+
{"[&>div>span]:color"}
|
|
570
|
+
</span>
|
|
571
571
|
</div>
|
|
572
572
|
<div className="p-3 rounded-xl border border-success/20 bg-success/5 text-xs font-mono shadow-sm flex items-center">
|
|
573
573
|
<span className="text-success font-bold mr-3 text-lg">✅</span>
|
|
574
|
-
<span className="text-foreground font-medium">
|
|
574
|
+
<span className="text-foreground font-medium">
|
|
575
|
+
data-[slot=icon]:color
|
|
576
|
+
</span>
|
|
575
577
|
</div>
|
|
576
578
|
</div>
|
|
577
579
|
</div>
|
|
@@ -586,9 +588,9 @@ export default function OverviewSection() {
|
|
|
586
588
|
Variant × Color
|
|
587
589
|
</h3>
|
|
588
590
|
<p className="text-muted-foreground text-lg leading-relaxed max-w-lg">
|
|
589
|
-
Variant (solid, outline, ghost...) và Color (primary,
|
|
590
|
-
là hai trục
|
|
591
|
-
|
|
591
|
+
Variant (solid, outline, ghost...) và Color (primary,
|
|
592
|
+
destructive...) là hai trục độc lập. Kết hợp tự do mà class
|
|
593
|
+
không phình ra.
|
|
592
594
|
</p>
|
|
593
595
|
</div>
|
|
594
596
|
<div className="relative z-10 mt-auto pt-8 grid sm:grid-cols-2 gap-4">
|
|
@@ -598,8 +600,8 @@ export default function OverviewSection() {
|
|
|
598
600
|
Variant
|
|
599
601
|
</strong>
|
|
600
602
|
<span className="text-sm text-muted-foreground leading-relaxed">
|
|
601
|
-
solid, outline, ghost, soft. Quyết định
|
|
602
|
-
|
|
603
|
+
solid, outline, ghost, soft. Quyết định cách component trông
|
|
604
|
+
như thế nào.
|
|
603
605
|
</span>
|
|
604
606
|
</div>
|
|
605
607
|
<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">
|
|
@@ -608,7 +610,8 @@ export default function OverviewSection() {
|
|
|
608
610
|
Trục Color
|
|
609
611
|
</strong>
|
|
610
612
|
<span className="text-sm text-muted-foreground leading-relaxed">
|
|
611
|
-
primary, secondary, destructive. Quyết định
|
|
613
|
+
primary, secondary, destructive. Quyết định bảng màu của
|
|
614
|
+
component.
|
|
612
615
|
</span>
|
|
613
616
|
</div>
|
|
614
617
|
</div>
|
|
@@ -624,8 +627,8 @@ export default function OverviewSection() {
|
|
|
624
627
|
Zero-prop Defaults
|
|
625
628
|
</h3>
|
|
626
629
|
<p className="text-muted-foreground text-lg leading-relaxed max-w-lg">
|
|
627
|
-
|
|
628
|
-
|
|
630
|
+
Đặt component vào mà không truyền prop nào — vẫn chạy đẹp, vẫn
|
|
631
|
+
đúng behavior.{" "}
|
|
629
632
|
<strong className="text-foreground">
|
|
630
633
|
Không phải tra docs mỗi lần dùng.
|
|
631
634
|
</strong>
|
|
@@ -659,8 +662,8 @@ export default function OverviewSection() {
|
|
|
659
662
|
Headless + Style
|
|
660
663
|
</h3>
|
|
661
664
|
<p className="text-muted-foreground text-base leading-relaxed">
|
|
662
|
-
Keyboard, focus, ARIA — Base UI lo hết. Micro component chỉ
|
|
663
|
-
|
|
665
|
+
Keyboard, focus, ARIA — Base UI lo hết. Micro component chỉ thêm
|
|
666
|
+
lớp style lên trên, không tự viết logic tương tác.{" "}
|
|
664
667
|
<strong className="text-foreground">
|
|
665
668
|
Behavior đúng sẵn, không cần test lại.
|
|
666
669
|
</strong>
|
|
@@ -668,13 +671,15 @@ export default function OverviewSection() {
|
|
|
668
671
|
</div>
|
|
669
672
|
<div className="relative z-10 mt-auto pt-8">
|
|
670
673
|
<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">
|
|
671
|
-
<div className="text-muted-foreground"
|
|
674
|
+
<div className="text-muted-foreground">
|
|
675
|
+
// Micro = Headless + Style
|
|
676
|
+
</div>
|
|
672
677
|
<div>
|
|
673
|
-
<span className="text-primary">{
|
|
678
|
+
<span className="text-primary">{"<Base UI Select>"}</span>
|
|
674
679
|
<span className="text-muted-foreground"> ← behavior</span>
|
|
675
680
|
</div>
|
|
676
681
|
<div className="pl-4">
|
|
677
|
-
<span className="text-success">{
|
|
682
|
+
<span className="text-success">{"<SelectTrigger>"}</span>
|
|
678
683
|
<span className="text-muted-foreground"> ← style only</span>
|
|
679
684
|
</div>
|
|
680
685
|
</div>
|
|
@@ -690,8 +695,8 @@ export default function OverviewSection() {
|
|
|
690
695
|
CSS Token
|
|
691
696
|
</h3>
|
|
692
697
|
<p className="text-muted-foreground text-lg leading-relaxed max-w-lg">
|
|
693
|
-
Không component nào hardcode màu hay spacing. Tất cả đều
|
|
694
|
-
|
|
698
|
+
Không component nào hardcode màu hay spacing. Tất cả đều tham
|
|
699
|
+
chiếu từ hệ thống token chung.{" "}
|
|
695
700
|
<strong className="text-foreground">
|
|
696
701
|
Đổi một token — cả app cập nhật.
|
|
697
702
|
</strong>
|
|
@@ -699,13 +704,17 @@ export default function OverviewSection() {
|
|
|
699
704
|
</div>
|
|
700
705
|
<div className="relative z-10 mt-auto pt-8 grid sm:grid-cols-2 gap-4">
|
|
701
706
|
<div className="p-4 rounded-xl border border-success/20 bg-success/5 shadow-sm">
|
|
702
|
-
<div className="text-success font-semibold mb-2 text-sm"
|
|
707
|
+
<div className="text-success font-semibold mb-2 text-sm">
|
|
708
|
+
✅ Token
|
|
709
|
+
</div>
|
|
703
710
|
<div className="text-[11px] font-mono text-success/80">
|
|
704
711
|
oklch(var(--primary))
|
|
705
712
|
</div>
|
|
706
713
|
</div>
|
|
707
714
|
<div className="p-4 rounded-xl border border-destructive/20 bg-destructive/5 shadow-sm opacity-60">
|
|
708
|
-
<div className="text-destructive font-semibold mb-2 text-sm"
|
|
715
|
+
<div className="text-destructive font-semibold mb-2 text-sm">
|
|
716
|
+
❌ Hardcode
|
|
717
|
+
</div>
|
|
709
718
|
<div className="text-[11px] font-mono text-destructive/80 line-through">
|
|
710
719
|
#2563eb
|
|
711
720
|
</div>
|
|
@@ -723,9 +732,9 @@ export default function OverviewSection() {
|
|
|
723
732
|
Polymorphism
|
|
724
733
|
</h3>
|
|
725
734
|
<p className="text-muted-foreground text-base leading-relaxed">
|
|
726
|
-
Dùng <code>render</code> prop để đổi thẻ HTML root —
|
|
727
|
-
|
|
728
|
-
|
|
735
|
+
Dùng <code>render</code> prop để đổi thẻ HTML root — ví dụ biến
|
|
736
|
+
Button thành Link. Không cần prop <code>as</code> hay tạo
|
|
737
|
+
wrapper lồng nhau.
|
|
729
738
|
</p>
|
|
730
739
|
</div>
|
|
731
740
|
<div className="relative z-10 mt-auto pt-6 space-y-3">
|
|
@@ -756,9 +765,8 @@ export default function OverviewSection() {
|
|
|
756
765
|
Stateless Primitive
|
|
757
766
|
</h3>
|
|
758
767
|
<p className="text-muted-foreground text-base leading-relaxed">
|
|
759
|
-
Micro component không chứa{" "}
|
|
760
|
-
<code>
|
|
761
|
-
Headless UI hoặc Macro.{" "}
|
|
768
|
+
Micro component không chứa <code>useState</code> hay{" "}
|
|
769
|
+
<code>useEffect</code>. State nằm ở Headless UI hoặc Macro.{" "}
|
|
762
770
|
<strong className="text-foreground">
|
|
763
771
|
Component càng đơn giản, càng ít bug.
|
|
764
772
|
</strong>
|
|
@@ -767,10 +775,14 @@ export default function OverviewSection() {
|
|
|
767
775
|
<div className="relative z-10 mt-auto pt-6 space-y-3">
|
|
768
776
|
<div className="p-3 rounded-xl border border-success/20 bg-success/5 text-[11px] font-mono shadow-sm flex items-center">
|
|
769
777
|
<span className="text-success font-bold mr-3 text-lg">✅</span>
|
|
770
|
-
<span className="text-success/90">
|
|
778
|
+
<span className="text-success/90">
|
|
779
|
+
{"function Button({ ...props })"}
|
|
780
|
+
</span>
|
|
771
781
|
</div>
|
|
772
782
|
<div className="p-3 rounded-xl border border-destructive/20 bg-destructive/5 text-[11px] font-mono shadow-sm flex items-center opacity-70">
|
|
773
|
-
<span className="text-destructive font-bold mr-3 text-lg"
|
|
783
|
+
<span className="text-destructive font-bold mr-3 text-lg">
|
|
784
|
+
❌
|
|
785
|
+
</span>
|
|
774
786
|
<span className="text-destructive/80 line-through">
|
|
775
787
|
{"const [open, setOpen] = useState()"}
|
|
776
788
|
</span>
|
|
@@ -788,8 +800,8 @@ export default function OverviewSection() {
|
|
|
788
800
|
Accessibility
|
|
789
801
|
</h3>
|
|
790
802
|
<p className="text-muted-foreground text-base leading-relaxed">
|
|
791
|
-
Semantic HTML, <code>aria-describedby</code> cho form,
|
|
792
|
-
|
|
803
|
+
Semantic HTML, <code>aria-describedby</code> cho form, icon
|
|
804
|
+
trang trí tự ẩn khỏi screen reader.{" "}
|
|
793
805
|
<strong className="text-foreground">
|
|
794
806
|
Chuẩn WCAG — không cần nghĩ thêm.
|
|
795
807
|
</strong>
|
|
@@ -823,12 +835,11 @@ export default function OverviewSection() {
|
|
|
823
835
|
Explicit State Contract
|
|
824
836
|
</h3>
|
|
825
837
|
<p className="text-muted-foreground text-base leading-relaxed">
|
|
826
|
-
Component
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
trạng thái mà không cần JavaScript.{" "}
|
|
838
|
+
Component công khai trạng thái qua <code>data-attributes</code>,
|
|
839
|
+
không phải qua imperative ref. Bạn style và animate trực tiếp
|
|
840
|
+
trên từng trạng thái, không cần JavaScript.{" "}
|
|
830
841
|
<strong className="text-foreground">
|
|
831
|
-
State là public API —
|
|
842
|
+
State là public API — tường minh và ổn định.
|
|
832
843
|
</strong>
|
|
833
844
|
</p>
|
|
834
845
|
</div>
|
|
@@ -843,7 +854,9 @@ export default function OverviewSection() {
|
|
|
843
854
|
<span className="text-muted-foreground">:opacity-50</span>
|
|
844
855
|
</div>
|
|
845
856
|
<div className="pt-1 border-t border-border/30">
|
|
846
|
-
<span className="text-destructive/60 line-through">
|
|
857
|
+
<span className="text-destructive/60 line-through">
|
|
858
|
+
ref.current.isOpen
|
|
859
|
+
</span>
|
|
847
860
|
</div>
|
|
848
861
|
</div>
|
|
849
862
|
</div>
|
|
@@ -859,9 +872,9 @@ export default function OverviewSection() {
|
|
|
859
872
|
3-Layer Source Ownership
|
|
860
873
|
</h3>
|
|
861
874
|
<p className="text-muted-foreground text-base leading-relaxed">
|
|
862
|
-
Source được phân tầng: <code>micro/</code> (primitive không
|
|
863
|
-
|
|
864
|
-
|
|
875
|
+
Source được phân tầng: <code>micro/</code> (primitive không có
|
|
876
|
+
layout cứng nhắc), <code>macro/</code> (preset lắp ráp có chủ
|
|
877
|
+
đích), <code>index.css</code> (token toàn hệ thống).{" "}
|
|
865
878
|
<strong className="text-foreground">
|
|
866
879
|
Sửa ở tầng nào chỉ ảnh hưởng đến tầng đó.
|
|
867
880
|
</strong>
|
|
@@ -870,15 +883,21 @@ export default function OverviewSection() {
|
|
|
870
883
|
<div className="relative z-10 mt-auto pt-6 space-y-2">
|
|
871
884
|
<div className="p-3 rounded-xl border border-border bg-background/60 text-[11px] font-mono flex items-center gap-3">
|
|
872
885
|
<span className="text-destructive font-bold">CSS</span>
|
|
873
|
-
<span className="text-muted-foreground">
|
|
886
|
+
<span className="text-muted-foreground">
|
|
887
|
+
index.css — token toàn cục
|
|
888
|
+
</span>
|
|
874
889
|
</div>
|
|
875
890
|
<div className="p-3 rounded-xl border border-border bg-background/60 text-[11px] font-mono flex items-center gap-3">
|
|
876
891
|
<span className="text-warning font-bold">Macro</span>
|
|
877
|
-
<span className="text-muted-foreground">
|
|
892
|
+
<span className="text-muted-foreground">
|
|
893
|
+
macro/ — preset lắp ráp
|
|
894
|
+
</span>
|
|
878
895
|
</div>
|
|
879
896
|
<div className="p-3 rounded-xl border border-border bg-background/60 text-[11px] font-mono flex items-center gap-3">
|
|
880
897
|
<span className="text-success font-bold">Micro</span>
|
|
881
|
-
<span className="text-muted-foreground">
|
|
898
|
+
<span className="text-muted-foreground">
|
|
899
|
+
micro/ — primitive thuần
|
|
900
|
+
</span>
|
|
882
901
|
</div>
|
|
883
902
|
</div>
|
|
884
903
|
</div>
|
|
@@ -936,66 +955,41 @@ export default function OverviewSection() {
|
|
|
936
955
|
Scoped Theme Tunnel
|
|
937
956
|
</h3>
|
|
938
957
|
<p className="text-muted-foreground text-xl leading-relaxed">
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
{"<ThemeProvider defaultMode=\"dark\">"}
|
|
944
|
-
</code>{" "}
|
|
945
|
-
là đủ để mọi component con hiểu ngữ cảnh đang là Dark và tự điều
|
|
946
|
-
chỉnh màu sắc.
|
|
958
|
+
Dark section bên trong Light app? Dễ. Nhưng khi Tooltip hay Dialog
|
|
959
|
+
render qua Portal — chúng thoát khỏi DOM tree và{" "}
|
|
960
|
+
<strong className="text-foreground">mất theme</strong>. Hầu hết
|
|
961
|
+
thư viện bỏ cuộc ở đây.
|
|
947
962
|
</p>
|
|
948
963
|
<p className="text-muted-foreground text-xl leading-relaxed">
|
|
949
|
-
|
|
950
|
-
Nhưng có một bẫy ẩn:
|
|
951
|
-
</strong>{" "}
|
|
952
|
-
khi người dùng mở Tooltip hoặc Dialog từ bên trong vùng tối đó,
|
|
953
|
-
component này render ra{" "}
|
|
954
|
-
<code className="text-sm bg-warning/20 text-warning px-1.5 py-0.5 rounded">
|
|
955
|
-
document.body
|
|
956
|
-
</code>{" "}
|
|
957
|
-
qua React Portal — thoát hoàn toàn khỏi DOM tree. CSS variable
|
|
958
|
-
dark mode mất theo. Tooltip hiện ra{" "}
|
|
959
|
-
<strong className="text-foreground">trắng lạc quẻ</strong> giữa
|
|
960
|
-
nền đen. Đây là điểm mà hầu hết thư viện bỏ cuộc.
|
|
961
|
-
</p>
|
|
962
|
-
<p className="text-muted-foreground text-xl leading-relaxed">
|
|
963
|
-
gladvn giải quyết bằng{" "}
|
|
964
|
+
gladvn dùng{" "}
|
|
964
965
|
<code className="text-sm bg-warning/20 text-warning px-1.5 py-0.5 rounded">
|
|
965
966
|
{"<ThemeWrapper>"}
|
|
966
967
|
</code>{" "}
|
|
967
|
-
|
|
968
|
-
<strong className="text-foreground">ngay bên trong Portal</strong>{" "}
|
|
969
|
-
để đọc theme context từ trước khi vượt qua ranh giới Portal và
|
|
970
|
-
tái-inject nó vào phía bên kia.{" "}
|
|
968
|
+
để tunnel theme xuyên qua Portal boundary.{" "}
|
|
971
969
|
<strong className="text-foreground">
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
</strong>
|
|
975
|
-
Kết quả: Dialog, Tooltip, Select... luôn hiển thị đúng màu dark
|
|
976
|
-
dù chúng render ở đâu trong DOM.
|
|
970
|
+
Dialog, Tooltip, Select... luôn đúng màu, dù render ở đâu trong
|
|
971
|
+
DOM.
|
|
972
|
+
</strong>
|
|
977
973
|
</p>
|
|
978
974
|
</div>
|
|
979
975
|
|
|
980
976
|
<div className="relative z-10 grid sm:grid-cols-2 gap-6 max-w-3xl">
|
|
981
977
|
<div className="p-6 rounded-2xl border border-success/30 bg-success/10 shadow-sm flex flex-col gap-2">
|
|
982
978
|
<div className="text-success font-semibold text-lg flex items-center gap-2">
|
|
983
|
-
✅ gladvn
|
|
979
|
+
✅ gladvn
|
|
984
980
|
</div>
|
|
985
981
|
<p className="text-success/80 text-sm leading-relaxed">
|
|
986
|
-
|
|
987
|
-
|
|
982
|
+
Tooltip, Dialog trong dark section luôn đúng màu — kể cả khi
|
|
983
|
+
Portal render ra{" "}
|
|
988
984
|
<code className="opacity-80">document.body</code>.
|
|
989
985
|
</p>
|
|
990
986
|
</div>
|
|
991
987
|
<div className="p-6 rounded-2xl border border-destructive/30 bg-destructive/10 shadow-sm opacity-80 flex flex-col gap-2">
|
|
992
988
|
<div className="text-destructive font-semibold text-lg flex items-center gap-2">
|
|
993
|
-
❌
|
|
989
|
+
❌ Thư viện khác
|
|
994
990
|
</div>
|
|
995
991
|
<p className="text-destructive/80 text-sm leading-relaxed">
|
|
996
|
-
|
|
997
|
-
dark section vẫn hiển thị màu Light Mode — lỗi thầm lặng, khó
|
|
998
|
-
debug.
|
|
992
|
+
Tooltip, Dialog "trắng lạc quẻ" — theme bị mất khi vượt Portal.
|
|
999
993
|
</p>
|
|
1000
994
|
</div>
|
|
1001
995
|
</div>
|
|
@@ -1007,7 +1001,7 @@ export default function OverviewSection() {
|
|
|
1007
1001
|
color="warning"
|
|
1008
1002
|
className="gap-2 font-bold px-6 py-5 rounded-xl border-warning/30 bg-warning/10 hover:bg-warning/20 shadow-sm"
|
|
1009
1003
|
>
|
|
1010
|
-
Xem
|
|
1004
|
+
Xem demo thực tế
|
|
1011
1005
|
<ArrowRightIcon className="size-4" />
|
|
1012
1006
|
</Button>
|
|
1013
1007
|
</div>
|
|
@@ -1026,9 +1020,9 @@ export default function OverviewSection() {
|
|
|
1026
1020
|
Không gian màu OKLCH
|
|
1027
1021
|
</h3>
|
|
1028
1022
|
<p className="text-muted-foreground text-xl leading-relaxed">
|
|
1029
|
-
Mọi token màu sắc được tính
|
|
1030
|
-
|
|
1031
|
-
|
|
1023
|
+
Mọi token màu sắc được tính trên không gian OKLCH — chuyển sắc
|
|
1024
|
+
mượt, tương phản đạt WCAG AA/AAA trên mọi theme mà không cần định
|
|
1025
|
+
nghĩa thủ công từng dải màu.
|
|
1032
1026
|
</p>
|
|
1033
1027
|
</div>
|
|
1034
1028
|
|
|
@@ -1065,7 +1059,7 @@ export default function OverviewSection() {
|
|
|
1065
1059
|
role: "Creator & Maintainer",
|
|
1066
1060
|
avatar: "https://github.com/duongacy.png",
|
|
1067
1061
|
url: "https://github.com/duongacy",
|
|
1068
|
-
}
|
|
1062
|
+
},
|
|
1069
1063
|
].map((user) => (
|
|
1070
1064
|
<a
|
|
1071
1065
|
key={user.name}
|
|
@@ -1076,18 +1070,34 @@ export default function OverviewSection() {
|
|
|
1076
1070
|
>
|
|
1077
1071
|
<Avatar className="size-16 border-2 border-transparent group-hover:border-primary/20 transition-all duration-300 group-hover:scale-105">
|
|
1078
1072
|
<AvatarImage src={user.avatar} alt={user.name} />
|
|
1079
|
-
<AvatarFallback className="text-lg bg-primary/5 text-primary">
|
|
1073
|
+
<AvatarFallback className="text-lg bg-primary/5 text-primary">
|
|
1074
|
+
{user.name.substring(0, 2).toUpperCase()}
|
|
1075
|
+
</AvatarFallback>
|
|
1080
1076
|
</Avatar>
|
|
1081
1077
|
<div className="text-center">
|
|
1082
|
-
<div className="font-semibold text-sm group-hover:text-primary transition-colors">
|
|
1083
|
-
|
|
1078
|
+
<div className="font-semibold text-sm group-hover:text-primary transition-colors">
|
|
1079
|
+
{user.name}
|
|
1080
|
+
</div>
|
|
1081
|
+
<div className="text-xs text-muted-foreground mt-0.5">
|
|
1082
|
+
{user.role}
|
|
1083
|
+
</div>
|
|
1084
1084
|
</div>
|
|
1085
1085
|
</a>
|
|
1086
1086
|
))}
|
|
1087
1087
|
</div>
|
|
1088
1088
|
|
|
1089
|
-
<Button
|
|
1090
|
-
|
|
1089
|
+
<Button
|
|
1090
|
+
variant="outline"
|
|
1091
|
+
className="mt-4 rounded-full"
|
|
1092
|
+
render={
|
|
1093
|
+
<a
|
|
1094
|
+
href="https://github.com/duongacy/gladcn"
|
|
1095
|
+
target="_blank"
|
|
1096
|
+
rel="noreferrer"
|
|
1097
|
+
/>
|
|
1098
|
+
}
|
|
1099
|
+
>
|
|
1100
|
+
Đóng góp cùng chúng tôi
|
|
1091
1101
|
</Button>
|
|
1092
1102
|
</div>
|
|
1093
1103
|
</section>
|
|
@@ -1098,14 +1108,14 @@ export default function OverviewSection() {
|
|
|
1098
1108
|
<div className="absolute inset-0 bg-[radial-gradient(ellipse_60%_60%_at_50%_0%,rgba(var(--primary-rgb),0.15),transparent)] pointer-events-none" />
|
|
1099
1109
|
<div className="relative z-10 space-y-6 max-w-2xl mx-auto">
|
|
1100
1110
|
<h2 className="text-3xl md:text-5xl font-extrabold tracking-tight">
|
|
1101
|
-
|
|
1111
|
+
30 giây. Xong.
|
|
1102
1112
|
</h2>
|
|
1103
1113
|
<p className="text-muted-foreground text-lg leading-relaxed">
|
|
1104
|
-
|
|
1114
|
+
Toàn bộ code nằm trong{" "}
|
|
1105
1115
|
<code className="text-sm bg-primary/20 text-primary px-1.5 py-0.5 rounded">
|
|
1106
1116
|
src/
|
|
1107
1117
|
</code>{" "}
|
|
1108
|
-
của bạn. Không config
|
|
1118
|
+
của bạn. Không config rườm rà. Chạy là dùng.
|
|
1109
1119
|
</p>
|
|
1110
1120
|
<div className="flex flex-col sm:flex-row items-center justify-center gap-4 pt-2">
|
|
1111
1121
|
<button
|
|
@@ -1123,11 +1133,17 @@ export default function OverviewSection() {
|
|
|
1123
1133
|
</div>
|
|
1124
1134
|
</button>
|
|
1125
1135
|
<Button
|
|
1126
|
-
render={
|
|
1136
|
+
render={
|
|
1137
|
+
<a
|
|
1138
|
+
href="https://github.com/duongacy/gladcn"
|
|
1139
|
+
target="_blank"
|
|
1140
|
+
rel="noreferrer"
|
|
1141
|
+
/>
|
|
1142
|
+
}
|
|
1127
1143
|
variant="ghost"
|
|
1128
1144
|
className="text-muted-foreground hover:text-foreground"
|
|
1129
1145
|
>
|
|
1130
|
-
Xem
|
|
1146
|
+
Xem trên GitHub
|
|
1131
1147
|
<ArrowRightIcon className="size-4 ml-1" />
|
|
1132
1148
|
</Button>
|
|
1133
1149
|
</div>
|