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.
- package/README.md +1 -1
- package/package.json +2 -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
|
@@ -13,15 +13,12 @@ import {
|
|
|
13
13
|
DocsH3,
|
|
14
14
|
DocsP,
|
|
15
15
|
ExampleGrid,
|
|
16
|
-
|
|
16
|
+
ShowcaseExample,
|
|
17
17
|
Showcase,
|
|
18
18
|
ShowcaseDocs
|
|
19
19
|
} from "../../dev/components/showcase";
|
|
20
20
|
import { type Size } from "../../lib/types";
|
|
21
21
|
|
|
22
|
-
// ──────────────────────────────────────────────────────────
|
|
23
|
-
// RHF Form Demo (Macro)
|
|
24
|
-
// ──────────────────────────────────────────────────────────
|
|
25
22
|
const formSchema = z.object({
|
|
26
23
|
notify: z.string().min(1, "Vui lòng chọn phương thức thông báo.") });
|
|
27
24
|
type FormValues = z.infer<typeof formSchema>;
|
|
@@ -93,17 +90,11 @@ function RadioGroupForm({ size }: { size: Size }) {
|
|
|
93
90
|
);
|
|
94
91
|
}`;
|
|
95
92
|
|
|
96
|
-
// ──────────────────────────────────────────────────────────
|
|
97
|
-
// SECTION 1: Macro Content
|
|
98
|
-
// ──────────────────────────────────────────────────────────
|
|
99
93
|
function RadioGroupMacroShowcase({ globalSize }: { globalSize: Size }) {
|
|
100
94
|
return (
|
|
101
|
-
<div className="space-y-10
|
|
95
|
+
<div className="space-y-10">
|
|
102
96
|
<ExampleGrid>
|
|
103
|
-
<
|
|
104
|
-
label="Tiêu chuẩn"
|
|
105
|
-
description="Nhóm radio cơ bản với mảng options."
|
|
106
|
-
codeString={`<RadioGroupPreset
|
|
97
|
+
<ShowcaseExample title="Tiêu chuẩn" description="Nhóm radio cơ bản với mảng options." code={`<RadioGroupPreset
|
|
107
98
|
className="w-full"
|
|
108
99
|
label="Sở thích"
|
|
109
100
|
description="Chọn một ngôn ngữ lập trình bạn yêu thích nhất."
|
|
@@ -113,26 +104,24 @@ function RadioGroupMacroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
113
104
|
{ value: "rust", label: "Rust" },
|
|
114
105
|
]}
|
|
115
106
|
defaultValue="ts"
|
|
116
|
-
/>`}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
107
|
+
/>`} preview={
|
|
108
|
+
<>
|
|
109
|
+
<RadioGroupPreset
|
|
110
|
+
className="w-full"
|
|
111
|
+
size={globalSize}
|
|
112
|
+
label="Sở thích"
|
|
113
|
+
description="Chọn một ngôn ngữ lập trình bạn yêu thích nhất."
|
|
114
|
+
options={[
|
|
115
|
+
{ value: "ts", label: "TypeScript" },
|
|
116
|
+
{ value: "go", label: "Golang" },
|
|
117
|
+
{ value: "rust", label: "Rust" },
|
|
118
|
+
]}
|
|
119
|
+
defaultValue="ts"
|
|
120
|
+
/>
|
|
121
|
+
</>
|
|
122
|
+
} />
|
|
131
123
|
|
|
132
|
-
<
|
|
133
|
-
label="Trạng thái Lỗi (Error)"
|
|
134
|
-
description="Báo lỗi khi form submit mà user chưa chọn."
|
|
135
|
-
codeString={`<div className="w-full flex flex-col gap-6">
|
|
124
|
+
<ShowcaseExample title="Trạng thái Lỗi (Error)" description="Báo lỗi khi form submit mà user chưa chọn." code={`<div className="w-full flex flex-col gap-6">
|
|
136
125
|
<RadioGroupPreset
|
|
137
126
|
label="Gói dịch vụ (Lỗi)"
|
|
138
127
|
options={[
|
|
@@ -141,27 +130,25 @@ function RadioGroupMacroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
141
130
|
]}
|
|
142
131
|
errorMessage="Vui lòng chọn một gói dịch vụ để tiếp tục."
|
|
143
132
|
/>
|
|
144
|
-
</div>`}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
133
|
+
</div>`} preview={
|
|
134
|
+
<>
|
|
135
|
+
<div className="w-full flex flex-col gap-6">
|
|
136
|
+
<RadioGroupPreset
|
|
137
|
+
size={globalSize}
|
|
138
|
+
label="Gói dịch vụ (Lỗi)"
|
|
139
|
+
options={[
|
|
140
|
+
{ value: "free", label: "Miễn phí" },
|
|
141
|
+
{ value: "pro", label: "Trả phí" },
|
|
142
|
+
]}
|
|
143
|
+
errorMessage="Vui lòng chọn một gói dịch vụ để tiếp tục."
|
|
144
|
+
/>
|
|
145
|
+
</div>
|
|
146
|
+
</>
|
|
147
|
+
} />
|
|
158
148
|
</ExampleGrid>
|
|
159
149
|
|
|
160
150
|
<ExampleGrid>
|
|
161
|
-
<
|
|
162
|
-
label="Mô tả cho từng Option"
|
|
163
|
-
description="Truyền description vào mảng options để chú thích chi tiết."
|
|
164
|
-
codeString={`<RadioGroupPreset
|
|
151
|
+
<ShowcaseExample title="Mô tả cho từng Option" description="Truyền description vào mảng options để chú thích chi tiết." code={`<RadioGroupPreset
|
|
165
152
|
className="w-full"
|
|
166
153
|
label="Giao diện (Theme)"
|
|
167
154
|
description="Chế độ Mặc định hệ thống sẽ tự động đồng bộ theo OS."
|
|
@@ -174,29 +161,27 @@ function RadioGroupMacroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
174
161
|
description: "Khuyên dùng để tiết kiệm pin" },
|
|
175
162
|
]}
|
|
176
163
|
defaultValue="system"
|
|
177
|
-
/>`}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
164
|
+
/>`} preview={
|
|
165
|
+
<>
|
|
166
|
+
<RadioGroupPreset
|
|
167
|
+
className="w-full"
|
|
168
|
+
size={globalSize}
|
|
169
|
+
label="Giao diện (Theme)"
|
|
170
|
+
description="Chế độ Mặc định hệ thống sẽ tự động đồng bộ theo OS."
|
|
171
|
+
options={[
|
|
172
|
+
{ value: "light", label: "Sáng (Light)" },
|
|
173
|
+
{ value: "dark", label: "Tối (Dark)" },
|
|
174
|
+
{
|
|
175
|
+
value: "system",
|
|
176
|
+
label: "Theo hệ thống",
|
|
177
|
+
description: "Khuyên dùng để tiết kiệm pin" },
|
|
178
|
+
]}
|
|
179
|
+
defaultValue="system"
|
|
180
|
+
/>
|
|
181
|
+
</>
|
|
182
|
+
} />
|
|
195
183
|
|
|
196
|
-
<
|
|
197
|
-
label="Khóa / Bất hoạt (Disabled)"
|
|
198
|
-
description="Người dùng không thể tương tác với form."
|
|
199
|
-
codeString={`<RadioGroupPreset
|
|
184
|
+
<ShowcaseExample title="Khóa / Bất hoạt (Disabled)" description="Người dùng không thể tương tác với form." code={`<RadioGroupPreset
|
|
200
185
|
className="w-full"
|
|
201
186
|
label="Phiên bản (Disabled)"
|
|
202
187
|
description="Bạn không thể hạ cấp phiên bản tại thời điểm này."
|
|
@@ -206,47 +191,40 @@ function RadioGroupMacroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
206
191
|
]}
|
|
207
192
|
defaultValue="v2"
|
|
208
193
|
disabled
|
|
209
|
-
/>`}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
194
|
+
/>`} preview={
|
|
195
|
+
<>
|
|
196
|
+
<RadioGroupPreset
|
|
197
|
+
className="w-full"
|
|
198
|
+
size={globalSize}
|
|
199
|
+
label="Phiên bản (Disabled)"
|
|
200
|
+
description="Bạn không thể hạ cấp phiên bản tại thời điểm này."
|
|
201
|
+
options={[
|
|
202
|
+
{ value: "v1", label: "v1.0.0 (Legacy)" },
|
|
203
|
+
{ value: "v2", label: "v2.0.0 (Current)" },
|
|
204
|
+
]}
|
|
205
|
+
defaultValue="v2"
|
|
206
|
+
disabled
|
|
207
|
+
/>
|
|
208
|
+
</>
|
|
209
|
+
} />
|
|
224
210
|
</ExampleGrid>
|
|
225
211
|
|
|
226
212
|
<ExampleGrid>
|
|
227
|
-
<
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
<RadioGroupForm size={globalSize} />
|
|
233
|
-
</ExampleSection>
|
|
213
|
+
<ShowcaseExample title="Tích hợp React Hook Form" description="Sử dụng Controller để bắt giá trị." code={rhfCode} preview={
|
|
214
|
+
<>
|
|
215
|
+
<RadioGroupForm size={globalSize} />
|
|
216
|
+
</>
|
|
217
|
+
} />
|
|
234
218
|
</ExampleGrid>
|
|
235
219
|
</div>
|
|
236
220
|
);
|
|
237
221
|
}
|
|
238
222
|
|
|
239
|
-
// ──────────────────────────────────────────────────────────
|
|
240
|
-
// SECTION 2: Micro Content
|
|
241
|
-
// ──────────────────────────────────────────────────────────
|
|
242
223
|
function RadioGroupMicroShowcase({ globalSize }: { globalSize: Size }) {
|
|
243
224
|
return (
|
|
244
|
-
<div className="space-y-10
|
|
225
|
+
<div className="space-y-10">
|
|
245
226
|
<ExampleGrid>
|
|
246
|
-
<
|
|
247
|
-
label="Cơ bản (Primitive)"
|
|
248
|
-
description="Ghép nối thủ công RadioGroupItem và Label."
|
|
249
|
-
codeString={`<RadioGroup
|
|
227
|
+
<ShowcaseExample title="Cơ bản (Primitive)" description="Ghép nối thủ công RadioGroupItem và Label." code={`<RadioGroup
|
|
250
228
|
defaultValue="comfortable"
|
|
251
229
|
className="flex flex-col gap-2 w-full"
|
|
252
230
|
>
|
|
@@ -268,35 +246,33 @@ function RadioGroupMicroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
268
246
|
Thoải mái
|
|
269
247
|
</Label>
|
|
270
248
|
</div>
|
|
271
|
-
</RadioGroup>`}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
249
|
+
</RadioGroup>`} preview={
|
|
250
|
+
<>
|
|
251
|
+
<RadioGroup
|
|
252
|
+
defaultValue="comfortable"
|
|
253
|
+
className="flex flex-col gap-2 w-full"
|
|
254
|
+
>
|
|
255
|
+
<div className="flex items-center gap-3">
|
|
256
|
+
<RadioGroupItem size={globalSize} value="default" id="rg-m-1" />
|
|
257
|
+
<Label htmlFor="rg-m-1" className="cursor-pointer font-normal">
|
|
258
|
+
Mặc định
|
|
259
|
+
</Label>
|
|
260
|
+
</div>
|
|
261
|
+
<div className="flex items-center gap-3">
|
|
262
|
+
<RadioGroupItem
|
|
263
|
+
size={globalSize}
|
|
264
|
+
value="comfortable"
|
|
265
|
+
id="rg-m-2"
|
|
266
|
+
/>
|
|
267
|
+
<Label htmlFor="rg-m-2" className="cursor-pointer font-normal">
|
|
268
|
+
Thoải mái
|
|
269
|
+
</Label>
|
|
270
|
+
</div>
|
|
271
|
+
</RadioGroup>
|
|
272
|
+
</>
|
|
273
|
+
} />
|
|
295
274
|
|
|
296
|
-
<
|
|
297
|
-
label="Bố cục Ngang (Horizontal)"
|
|
298
|
-
description="Hiển thị các tuỳ chọn trên một hàng ngang."
|
|
299
|
-
codeString={`<div className="space-y-3 w-full">
|
|
275
|
+
<ShowcaseExample title="Bố cục Ngang (Horizontal)" description="Hiển thị các tuỳ chọn trên một hàng ngang." code={`<div className="space-y-3 w-full">
|
|
300
276
|
<Label className="block text-muted-foreground">
|
|
301
277
|
Kích thước
|
|
302
278
|
</Label>
|
|
@@ -332,39 +308,37 @@ function RadioGroupMicroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
332
308
|
</Label>
|
|
333
309
|
</div>
|
|
334
310
|
</RadioGroup>
|
|
335
|
-
</div>`}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
311
|
+
</div>`} preview={
|
|
312
|
+
<>
|
|
313
|
+
<div className="space-y-3 w-full">
|
|
314
|
+
<Label className="block text-muted-foreground">Kích thước</Label>
|
|
315
|
+
<RadioGroup defaultValue="m" className="flex items-center gap-6">
|
|
316
|
+
<div className="flex items-center gap-2">
|
|
317
|
+
<RadioGroupItem size={globalSize} value="s" id="rg-s" />
|
|
318
|
+
<Label htmlFor="rg-s" className="cursor-pointer font-normal">
|
|
319
|
+
S
|
|
320
|
+
</Label>
|
|
321
|
+
</div>
|
|
322
|
+
<div className="flex items-center gap-2">
|
|
323
|
+
<RadioGroupItem size={globalSize} value="m" id="rg-m" />
|
|
324
|
+
<Label htmlFor="rg-m" className="cursor-pointer font-normal">
|
|
325
|
+
M
|
|
326
|
+
</Label>
|
|
327
|
+
</div>
|
|
328
|
+
<div className="flex items-center gap-2">
|
|
329
|
+
<RadioGroupItem size={globalSize} value="l" id="rg-l" />
|
|
330
|
+
<Label htmlFor="rg-l" className="cursor-pointer font-normal">
|
|
331
|
+
L
|
|
332
|
+
</Label>
|
|
333
|
+
</div>
|
|
334
|
+
</RadioGroup>
|
|
335
|
+
</div>
|
|
336
|
+
</>
|
|
337
|
+
} />
|
|
361
338
|
</ExampleGrid>
|
|
362
339
|
|
|
363
340
|
<ExampleGrid>
|
|
364
|
-
<
|
|
365
|
-
label="Ghép nối Field thủ công"
|
|
366
|
-
description="Tạo layout RadioGroup phức tạp với Field."
|
|
367
|
-
codeString={`<Field data-invalid={true} className="w-full gap-4">
|
|
341
|
+
<ShowcaseExample title="Ghép nối Field thủ công" description="Tạo layout RadioGroup phức tạp với Field." code={`<Field data-invalid={true} className="w-full gap-4">
|
|
368
342
|
<FieldLabel>Gói cước của bạn</FieldLabel>
|
|
369
343
|
<RadioGroup
|
|
370
344
|
defaultValue="monthly"
|
|
@@ -398,48 +372,46 @@ function RadioGroupMicroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
398
372
|
</Field>
|
|
399
373
|
</RadioGroup>
|
|
400
374
|
<FieldError>Thẻ của bạn đã bị từ chối.</FieldError>
|
|
401
|
-
</Field>`}
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
375
|
+
</Field>`} preview={
|
|
376
|
+
<>
|
|
377
|
+
<Field data-invalid={true} className="w-full gap-4">
|
|
378
|
+
<FieldLabel>Gói cước của bạn</FieldLabel>
|
|
379
|
+
<RadioGroup defaultValue="monthly" className="flex flex-col gap-2">
|
|
380
|
+
<Field orientation="horizontal" size={globalSize}>
|
|
381
|
+
<RadioGroupItem
|
|
382
|
+
size={globalSize}
|
|
383
|
+
value="monthly"
|
|
384
|
+
id="plan-1"
|
|
385
|
+
aria-invalid={true}
|
|
386
|
+
/>
|
|
387
|
+
<FieldLabel
|
|
388
|
+
htmlFor="plan-1"
|
|
389
|
+
className="font-normal cursor-pointer"
|
|
390
|
+
>
|
|
391
|
+
Thanh toán tháng ($10/mo)
|
|
392
|
+
</FieldLabel>
|
|
393
|
+
</Field>
|
|
394
|
+
<Field orientation="horizontal" size={globalSize}>
|
|
395
|
+
<RadioGroupItem
|
|
396
|
+
size={globalSize}
|
|
397
|
+
value="yearly"
|
|
398
|
+
id="plan-2"
|
|
399
|
+
aria-invalid={true}
|
|
400
|
+
/>
|
|
401
|
+
<FieldLabel
|
|
402
|
+
htmlFor="plan-2"
|
|
403
|
+
className="font-normal cursor-pointer"
|
|
404
|
+
>
|
|
405
|
+
Thanh toán năm ($100/yr)
|
|
406
|
+
</FieldLabel>
|
|
407
|
+
</Field>
|
|
408
|
+
</RadioGroup>
|
|
409
|
+
<FieldError>Thẻ của bạn đã bị từ chối.</FieldError>
|
|
410
|
+
</Field>
|
|
411
|
+
</>
|
|
412
|
+
} />
|
|
438
413
|
|
|
439
|
-
<
|
|
440
|
-
label="Card Layout (UI Nâng cao)"
|
|
441
|
-
description="Radio nhưng thiết kế dưới dạng Card để bấm."
|
|
442
|
-
codeString={`<RadioGroup
|
|
414
|
+
<ShowcaseExample title="Card Layout (UI Nâng cao)" description="Radio nhưng thiết kế dưới dạng Card để bấm." code={`<RadioGroup
|
|
443
415
|
defaultValue="card-2"
|
|
444
416
|
className="grid grid-cols-2 gap-4 w-full"
|
|
445
417
|
>
|
|
@@ -467,37 +439,34 @@ function RadioGroupMicroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
467
439
|
<div className="text-xl">🌙</div>
|
|
468
440
|
<span>Tối</span>
|
|
469
441
|
</Label>
|
|
470
|
-
</RadioGroup>`}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
442
|
+
</RadioGroup>`} preview={
|
|
443
|
+
<>
|
|
444
|
+
<RadioGroup
|
|
445
|
+
defaultValue="card-2"
|
|
446
|
+
className="grid grid-cols-2 gap-4 w-full"
|
|
447
|
+
>
|
|
448
|
+
<Label
|
|
449
|
+
htmlFor="card-1"
|
|
450
|
+
className="flex flex-col items-center justify-between rounded-md border-2 border-muted bg-popover p-4 hover:bg-accent hover:text-accent-foreground [&:has([data-state=checked])]:border-primary cursor-pointer gap-4"
|
|
451
|
+
>
|
|
452
|
+
<RadioGroupItem value="card-1" id="card-1" className="sr-only" />
|
|
453
|
+
<div className="text-xl">☀️</div>
|
|
454
|
+
<span>Sáng</span>
|
|
455
|
+
</Label>
|
|
456
|
+
<Label
|
|
457
|
+
htmlFor="card-2"
|
|
458
|
+
className="flex flex-col items-center justify-between rounded-md border-2 border-muted bg-popover p-4 hover:bg-accent hover:text-accent-foreground [&:has([data-state=checked])]:border-primary cursor-pointer gap-4"
|
|
459
|
+
>
|
|
460
|
+
<RadioGroupItem value="card-2" id="card-2" className="sr-only" />
|
|
461
|
+
<div className="text-xl">🌙</div>
|
|
462
|
+
<span>Tối</span>
|
|
463
|
+
</Label>
|
|
464
|
+
</RadioGroup>
|
|
465
|
+
</>
|
|
466
|
+
} />
|
|
494
467
|
</ExampleGrid>
|
|
495
468
|
|
|
496
|
-
<
|
|
497
|
-
label="🧭 Use Case Comparison"
|
|
498
|
-
description="So sánh nhanh khi nào dùng Micro và Macro."
|
|
499
|
-
fullWidth
|
|
500
|
-
codeString={`<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
|
|
469
|
+
<ShowcaseExample title="🧭 So sánh Use Case" description="So sánh nhanh khi nào dùng Micro và Macro." code={`<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
|
|
501
470
|
{/* Story 1: Macro wins */}
|
|
502
471
|
<div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
|
|
503
472
|
<div className="flex items-start gap-3">
|
|
@@ -569,120 +538,91 @@ function RadioGroupMicroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
569
538
|
<DocsCode>Label</DocsCode> thành 1 cái thẻ Card.
|
|
570
539
|
</p>
|
|
571
540
|
</div>
|
|
572
|
-
</div>`}
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
</div>
|
|
541
|
+
</div>`} preview={
|
|
542
|
+
<>
|
|
543
|
+
<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
|
|
544
|
+
<div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
|
|
545
|
+
<div className="flex items-start gap-3">
|
|
546
|
+
<span className="mt-0.5 shrink-0 rounded-full bg-green-500/10 p-1.5 text-green-600">
|
|
547
|
+
<svg
|
|
548
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
549
|
+
className="size-4"
|
|
550
|
+
viewBox="0 0 24 24"
|
|
551
|
+
fill="none"
|
|
552
|
+
stroke="currentColor"
|
|
553
|
+
strokeWidth="2"
|
|
554
|
+
strokeLinecap="round"
|
|
555
|
+
strokeLinejoin="round"
|
|
556
|
+
aria-hidden="true"
|
|
557
|
+
>
|
|
558
|
+
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
|
|
559
|
+
</svg>
|
|
560
|
+
</span>
|
|
561
|
+
<div>
|
|
562
|
+
<p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
|
|
563
|
+
Story 1 · Dùng Macro
|
|
564
|
+
</p>
|
|
565
|
+
<h3 className="mt-0.5 text-sm font-semibold text-foreground">
|
|
566
|
+
Câu hỏi khảo sát
|
|
567
|
+
</h3>
|
|
568
|
+
</div>
|
|
569
|
+
</div>
|
|
570
|
+
<p className="text-xs text-muted-foreground leading-relaxed">
|
|
571
|
+
Bạn cần làm một danh sách dài các tuỳ chọn dạng chữ từ trên xuống
|
|
572
|
+
dưới. Macro <DocsCode>RadioGroupPreset</DocsCode> sinh ra để xử lý
|
|
573
|
+
việc này nhanh gọn qua thuộc tính <DocsCode>options</DocsCode>.
|
|
574
|
+
</p>
|
|
575
|
+
</div>
|
|
608
576
|
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
577
|
+
<div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
|
|
578
|
+
<div className="flex items-start gap-3">
|
|
579
|
+
<span className="mt-0.5 shrink-0 rounded-full bg-blue-500/10 p-1.5 text-blue-600">
|
|
580
|
+
<svg
|
|
581
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
582
|
+
className="size-4"
|
|
583
|
+
viewBox="0 0 24 24"
|
|
584
|
+
fill="none"
|
|
585
|
+
stroke="currentColor"
|
|
586
|
+
strokeWidth="2"
|
|
587
|
+
strokeLinecap="round"
|
|
588
|
+
strokeLinejoin="round"
|
|
589
|
+
aria-hidden="true"
|
|
590
|
+
>
|
|
591
|
+
<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z" />
|
|
592
|
+
</svg>
|
|
593
|
+
</span>
|
|
594
|
+
<div>
|
|
595
|
+
<p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
|
|
596
|
+
Story 2 · Dùng Micro
|
|
597
|
+
</p>
|
|
598
|
+
<h3 className="mt-0.5 text-sm font-semibold text-foreground">
|
|
599
|
+
Radio Ẩn (Hidden Radio Card)
|
|
600
|
+
</h3>
|
|
601
|
+
</div>
|
|
602
|
+
</div>
|
|
603
|
+
<p className="text-xs text-muted-foreground leading-relaxed">
|
|
604
|
+
Bạn muốn người dùng click vào một khối Card lớn (chứa ảnh sản
|
|
605
|
+
phẩm, mô tả) thay vì click vào nút tròn. Bạn sẽ dùng Micro để ẩn
|
|
606
|
+
đi <DocsCode>RadioGroupItem</DocsCode> và style{" "}
|
|
607
|
+
<DocsCode>Label</DocsCode> thành 1 cái thẻ Card.
|
|
608
|
+
</p>
|
|
609
|
+
</div>
|
|
610
|
+
</div>
|
|
611
|
+
</>
|
|
612
|
+
} />
|
|
645
613
|
</div>
|
|
646
614
|
);
|
|
647
615
|
}
|
|
648
616
|
|
|
649
|
-
// ──────────────────────────────────────────────────────────
|
|
650
|
-
// SECTION 3: Entry point
|
|
651
|
-
// ──────────────────────────────────────────────────────────
|
|
652
617
|
export default function RadioGroupShowcase() {
|
|
653
618
|
const { size: globalSize } = useDevContext();
|
|
654
619
|
return (
|
|
655
620
|
<Showcase
|
|
656
621
|
title="Radio Group"
|
|
657
622
|
description="Tập hợp các nút chọn một tuỳ chọn duy nhất trong danh sách (Radio Buttons)."
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
<DocsP>
|
|
662
|
-
<DocsCode>RadioGroupPreset</DocsCode> đóng gói sẵn cấu trúc form
|
|
663
|
-
tiêu chuẩn: Label tổng, Description tổng, Error Message tổng và tự
|
|
664
|
-
động render danh sách các <DocsCode>options</DocsCode> thành các
|
|
665
|
-
RadioGroupItem. Dùng Macro cho 95% trường hợp làm form trắc nghiệm,
|
|
666
|
-
chọn 1 trong nhiều tuỳ chọn.
|
|
667
|
-
</DocsP>
|
|
668
|
-
<DocsH3>Khi nào nên dùng Micro</DocsH3>
|
|
669
|
-
<DocsP>
|
|
670
|
-
Dùng <DocsCode>RadioGroup</DocsCode> và{" "}
|
|
671
|
-
<DocsCode>RadioGroupItem</DocsCode> nguyên thuỷ khi bạn cần một
|
|
672
|
-
layout dị biệt (như hiển thị các radio nằm ngang thay vì dọc) hoặc
|
|
673
|
-
khi mỗi option không đơn thuần là text mà chứa layout hình ảnh phức
|
|
674
|
-
tạp (như chọn Card hình ảnh thay vì text).
|
|
675
|
-
</DocsP>
|
|
676
|
-
</ShowcaseDocs>
|
|
677
|
-
}
|
|
678
|
-
tabs={[
|
|
679
|
-
{
|
|
680
|
-
label: "Micro (Primitive)",
|
|
681
|
-
content: <RadioGroupMicroShowcase globalSize={globalSize} /> },
|
|
682
|
-
{
|
|
683
|
-
label: "Macro (Preset)",
|
|
684
|
-
content: <RadioGroupMacroShowcase globalSize={globalSize} /> },
|
|
685
|
-
]}
|
|
623
|
+
|
|
624
|
+
micro={{ content: <RadioGroupMicroShowcase globalSize={globalSize} /> }}
|
|
625
|
+
macro={{ content: <RadioGroupMacroShowcase globalSize={globalSize} /> }}
|
|
686
626
|
/>
|
|
687
627
|
);
|
|
688
628
|
}
|