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
|
@@ -19,15 +19,12 @@ import { useDevContext } from "../../dev/components/dev-context";
|
|
|
19
19
|
import {
|
|
20
20
|
DocsP,
|
|
21
21
|
ExampleGrid,
|
|
22
|
-
|
|
22
|
+
ShowcaseExample,
|
|
23
23
|
Showcase,
|
|
24
24
|
ShowcaseDocs
|
|
25
25
|
} from "../../dev/components/showcase";
|
|
26
26
|
import { type Size } from "../../lib/types";
|
|
27
27
|
|
|
28
|
-
// ──────────────────────────────────────────────────────────
|
|
29
|
-
// RHF Form Demo (Macro)
|
|
30
|
-
// ──────────────────────────────────────────────────────────
|
|
31
28
|
const formSchema = z.object({
|
|
32
29
|
mobile: z.boolean().default(false).optional() });
|
|
33
30
|
type FormValues = z.infer<typeof formSchema>;
|
|
@@ -90,62 +87,52 @@ function CheckboxForm({ size }: { size: Size }) {
|
|
|
90
87
|
/>
|
|
91
88
|
)}
|
|
92
89
|
/>
|
|
93
|
-
<Button type="submit" size={size}>
|
|
90
|
+
<Button type="submit" size={size}>Xác nhận</Button>
|
|
94
91
|
</form>
|
|
95
92
|
);
|
|
96
93
|
}`;
|
|
97
94
|
|
|
98
|
-
// ──────────────────────────────────────────────────────────
|
|
99
|
-
// SECTION 1: Macro Content
|
|
100
|
-
// ──────────────────────────────────────────────────────────
|
|
101
95
|
function CheckboxMacroShowcase({ globalSize }: { globalSize: Size }) {
|
|
102
96
|
const [checked, setChecked] = useState(false);
|
|
103
97
|
|
|
104
98
|
return (
|
|
105
|
-
<div className="space-y-10
|
|
99
|
+
<div className="space-y-10">
|
|
106
100
|
<ExampleGrid>
|
|
107
|
-
<
|
|
108
|
-
label="Tiêu chuẩn"
|
|
109
|
-
description="Checkbox cơ bản kèm nhãn và mô tả."
|
|
110
|
-
codeString={`<CheckboxPreset
|
|
101
|
+
<ShowcaseExample title="Tiêu chuẩn" description="Checkbox cơ bản kèm nhãn và mô tả." code={`<CheckboxPreset
|
|
111
102
|
label="Đồng ý với điều khoản"
|
|
112
103
|
description="Bạn phải đồng ý với các điều khoản và điều kiện sử dụng."
|
|
113
104
|
className="w-full"
|
|
114
|
-
/>`}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
105
|
+
/>`} preview={
|
|
106
|
+
<>
|
|
107
|
+
<CheckboxPreset
|
|
108
|
+
size={globalSize}
|
|
109
|
+
label="Đồng ý với điều khoản"
|
|
110
|
+
description="Bạn phải đồng ý với các điều khoản và điều kiện sử dụng."
|
|
111
|
+
className="w-full"
|
|
112
|
+
/>
|
|
113
|
+
</>
|
|
114
|
+
} />
|
|
123
115
|
|
|
124
|
-
<
|
|
125
|
-
label="Trạng thái Lỗi (Error)"
|
|
126
|
-
description="Báo lỗi khi chưa check vào ô (thường dùng trong form)."
|
|
127
|
-
codeString={`<div className="w-full flex flex-col gap-6">
|
|
116
|
+
<ShowcaseExample title="Trạng thái Lỗi (Error)" description="Báo lỗi khi chưa check vào ô (thường dùng trong form)." code={`<div className="w-full flex flex-col gap-6">
|
|
128
117
|
<CheckboxPreset
|
|
129
118
|
label="Xác nhận đủ 18 tuổi"
|
|
130
119
|
errorMessage="Bạn phải xác nhận đủ tuổi để tiếp tục."
|
|
131
120
|
/>
|
|
132
|
-
</div>`}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
121
|
+
</div>`} preview={
|
|
122
|
+
<>
|
|
123
|
+
<div className="w-full flex flex-col gap-6">
|
|
124
|
+
<CheckboxPreset
|
|
125
|
+
size={globalSize}
|
|
126
|
+
label="Xác nhận đủ 18 tuổi"
|
|
127
|
+
errorMessage="Bạn phải xác nhận đủ tuổi để tiếp tục."
|
|
128
|
+
/>
|
|
129
|
+
</div>
|
|
130
|
+
</>
|
|
131
|
+
} />
|
|
142
132
|
</ExampleGrid>
|
|
143
133
|
|
|
144
134
|
<ExampleGrid>
|
|
145
|
-
<
|
|
146
|
-
label="Trạng thái Khóa (Disabled)"
|
|
147
|
-
description="Checkbox bị vô hiệu hóa, không thể click."
|
|
148
|
-
codeString={`<div className="w-full flex flex-col gap-6">
|
|
135
|
+
<ShowcaseExample title="Trạng thái Khóa (Disabled)" description="Checkbox bị vô hiệu hóa, không thể click." code={`<div className="w-full flex flex-col gap-6">
|
|
149
136
|
<CheckboxPreset
|
|
150
137
|
label="Đăng ký nhận bản tin"
|
|
151
138
|
description="Tính năng này đang được bảo trì."
|
|
@@ -157,29 +144,27 @@ function CheckboxMacroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
157
144
|
defaultChecked
|
|
158
145
|
disabled
|
|
159
146
|
/>
|
|
160
|
-
</div>`}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
147
|
+
</div>`} preview={
|
|
148
|
+
<>
|
|
149
|
+
<div className="w-full flex flex-col gap-6">
|
|
150
|
+
<CheckboxPreset
|
|
151
|
+
size={globalSize}
|
|
152
|
+
label="Đăng ký nhận bản tin"
|
|
153
|
+
description="Tính năng này đang được bảo trì."
|
|
154
|
+
disabled
|
|
155
|
+
/>
|
|
156
|
+
<CheckboxPreset
|
|
157
|
+
size={globalSize}
|
|
158
|
+
label="Cho phép thu thập log"
|
|
159
|
+
description="Hệ thống mặc định thu thập log bảo mật."
|
|
160
|
+
defaultChecked
|
|
161
|
+
disabled
|
|
162
|
+
/>
|
|
163
|
+
</div>
|
|
164
|
+
</>
|
|
165
|
+
} />
|
|
178
166
|
|
|
179
|
-
<
|
|
180
|
-
label="React Node Label (Custom Content)"
|
|
181
|
-
description="Label có thể chứa các component React phức tạp như Badge."
|
|
182
|
-
codeString={`<CheckboxPreset
|
|
167
|
+
<ShowcaseExample title="React Node Label (Custom Content)" description="Label có thể chứa các component React phức tạp như Badge." code={`<CheckboxPreset
|
|
183
168
|
label={
|
|
184
169
|
<span className="flex items-center gap-2">
|
|
185
170
|
Tham gia chương trình BETA{" "}
|
|
@@ -190,79 +175,70 @@ function CheckboxMacroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
190
175
|
}
|
|
191
176
|
description="Được trải nghiệm sớm các tính năng mới trước khi phát hành chính thức. Có thể xảy ra lỗi."
|
|
192
177
|
className="w-full"
|
|
193
|
-
/>`}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
178
|
+
/>`} preview={
|
|
179
|
+
<>
|
|
180
|
+
<CheckboxPreset
|
|
181
|
+
size={globalSize}
|
|
182
|
+
label={
|
|
183
|
+
<span className="flex items-center gap-2">
|
|
184
|
+
Tham gia chương trình BETA{" "}
|
|
185
|
+
<span className="rounded bg-primary/20 px-1.5 py-0.5 text-[10px] font-semibold text-primary">
|
|
186
|
+
NEW
|
|
187
|
+
</span>
|
|
188
|
+
</span>
|
|
189
|
+
}
|
|
190
|
+
description="Được trải nghiệm sớm các tính năng mới trước khi phát hành chính thức. Có thể xảy ra lỗi."
|
|
191
|
+
className="w-full"
|
|
192
|
+
/>
|
|
193
|
+
</>
|
|
194
|
+
} />
|
|
209
195
|
</ExampleGrid>
|
|
210
196
|
|
|
211
197
|
<ExampleGrid>
|
|
212
|
-
<
|
|
213
|
-
label="React State (Controlled Mode)"
|
|
214
|
-
description="Sử dụng biến state của React để điều khiển."
|
|
215
|
-
codeString={`const [checked, setChecked] = useState(false); return (
|
|
198
|
+
<ShowcaseExample title="React State (Controlled Mode)" description="Sử dụng biến state của React để điều khiển." code={`const [checked, setChecked] = useState(false); return (
|
|
216
199
|
<CheckboxPreset
|
|
217
200
|
checked={checked}
|
|
218
201
|
onCheckedChange={(c) => setChecked(!!c)}
|
|
219
202
|
label="Checkbox có kiểm soát"
|
|
220
203
|
description="React quản lý trạng thái của checkbox này."
|
|
221
204
|
/>
|
|
222
|
-
);`}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
205
|
+
);`} preview={
|
|
206
|
+
<>
|
|
207
|
+
<div className="w-full flex flex-col gap-4">
|
|
208
|
+
<CheckboxPreset
|
|
209
|
+
size={globalSize}
|
|
210
|
+
checked={checked}
|
|
211
|
+
onCheckedChange={(c) => setChecked(!!c)}
|
|
212
|
+
label="Checkbox có kiểm soát"
|
|
213
|
+
description="React quản lý trạng thái của checkbox này."
|
|
214
|
+
/>
|
|
215
|
+
<p className="text-sm text-muted-foreground">
|
|
216
|
+
Giá trị hiện tại:{" "}
|
|
217
|
+
<span className="font-mono font-bold text-foreground">
|
|
218
|
+
{checked ? "TRUE" : "FALSE"}
|
|
219
|
+
</span>
|
|
220
|
+
</p>
|
|
221
|
+
</div>
|
|
222
|
+
</>
|
|
223
|
+
} />
|
|
240
224
|
|
|
241
|
-
<
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
<CheckboxForm size={globalSize} />
|
|
247
|
-
</ExampleSection>
|
|
225
|
+
<ShowcaseExample title="Tích hợp React Hook Form" description="Dùng Controller của RHF để bọc CheckboxPreset." code={rhfCode} preview={
|
|
226
|
+
<>
|
|
227
|
+
<CheckboxForm size={globalSize} />
|
|
228
|
+
</>
|
|
229
|
+
} />
|
|
248
230
|
</ExampleGrid>
|
|
249
231
|
</div>
|
|
250
232
|
);
|
|
251
233
|
}
|
|
252
234
|
|
|
253
|
-
// ──────────────────────────────────────────────────────────
|
|
254
|
-
// SECTION 2: Micro Content
|
|
255
|
-
// ──────────────────────────────────────────────────────────
|
|
256
235
|
function CheckboxMicroShowcase({ globalSize }: { globalSize: Size }) {
|
|
257
236
|
const [checked, setChecked] = useState(false);
|
|
258
237
|
|
|
259
238
|
return (
|
|
260
|
-
<div className="space-y-10
|
|
239
|
+
<div className="space-y-10">
|
|
261
240
|
<ExampleGrid>
|
|
262
|
-
<
|
|
263
|
-
label="Cơ bản (Primitive)"
|
|
264
|
-
description="Kết nối thủ công Checkbox với thẻ Label html."
|
|
265
|
-
codeString={`<div className="flex items-center gap-3">
|
|
241
|
+
<ShowcaseExample title="Cơ bản (Primitive)" description="Kết nối thủ công Checkbox với thẻ Label html." code={`<div className="flex items-center gap-3">
|
|
266
242
|
<Checkbox id="cb-micro-default">
|
|
267
243
|
<CheckboxIndicator>
|
|
268
244
|
<CheckIcon />
|
|
@@ -274,27 +250,25 @@ function CheckboxMicroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
274
250
|
>
|
|
275
251
|
Đồng ý với điều khoản
|
|
276
252
|
</Label>
|
|
277
|
-
</div>`}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
253
|
+
</div>`} preview={
|
|
254
|
+
<>
|
|
255
|
+
<div className="flex items-center gap-3">
|
|
256
|
+
<Checkbox id="cb-micro-default" size={globalSize}>
|
|
257
|
+
<CheckboxIndicator>
|
|
258
|
+
<CheckIcon />
|
|
259
|
+
</CheckboxIndicator>
|
|
260
|
+
</Checkbox>
|
|
261
|
+
<Label
|
|
262
|
+
htmlFor="cb-micro-default"
|
|
263
|
+
className="font-normal cursor-pointer"
|
|
264
|
+
>
|
|
265
|
+
Đồng ý với điều khoản
|
|
266
|
+
</Label>
|
|
267
|
+
</div>
|
|
268
|
+
</>
|
|
269
|
+
} />
|
|
293
270
|
|
|
294
|
-
<
|
|
295
|
-
label="Icon Tuỳ Biến (Custom Icon)"
|
|
296
|
-
description="Vì dùng Composition, bạn có thể truyền bất kỳ icon nào (VD: MinusIcon) vào Indicator."
|
|
297
|
-
codeString={`<div className="flex items-center gap-3">
|
|
271
|
+
<ShowcaseExample title="Icon Tuỳ Biến (Custom Icon)" description="Vì dùng Composition, bạn có thể truyền bất kỳ icon nào (VD: MinusIcon) vào Indicator." code={`<div className="flex items-center gap-3">
|
|
298
272
|
<Checkbox id="cb-custom-icon">
|
|
299
273
|
<CheckboxIndicator>
|
|
300
274
|
<MinusIcon />
|
|
@@ -306,29 +280,27 @@ function CheckboxMicroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
306
280
|
>
|
|
307
281
|
Trạng thái vô định (Indeterminate)
|
|
308
282
|
</Label>
|
|
309
|
-
</div>`}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
283
|
+
</div>`} preview={
|
|
284
|
+
<>
|
|
285
|
+
<div className="flex items-center gap-3">
|
|
286
|
+
<Checkbox id="cb-custom-icon" size={globalSize}>
|
|
287
|
+
<CheckboxIndicator>
|
|
288
|
+
<MinusIcon />
|
|
289
|
+
</CheckboxIndicator>
|
|
290
|
+
</Checkbox>
|
|
291
|
+
<Label
|
|
292
|
+
htmlFor="cb-custom-icon"
|
|
293
|
+
className="font-normal cursor-pointer"
|
|
294
|
+
>
|
|
295
|
+
Trạng thái vô định (Indeterminate)
|
|
296
|
+
</Label>
|
|
297
|
+
</div>
|
|
298
|
+
</>
|
|
299
|
+
} />
|
|
325
300
|
</ExampleGrid>
|
|
326
301
|
|
|
327
302
|
<ExampleGrid>
|
|
328
|
-
<
|
|
329
|
-
label="Ghép nối với Field"
|
|
330
|
-
description="Lắp ráp thủ công các thành phần Field khi cần layout phức tạp."
|
|
331
|
-
codeString={`<Field className="flex items-start gap-3">
|
|
303
|
+
<ShowcaseExample title="Ghép nối với Field" description="Lắp ráp thủ công các thành phần Field khi cần layout phức tạp." code={`<Field className="flex items-start gap-3">
|
|
332
304
|
{/* 1 khoảng trắng vô hình để căn chỉnh cho Label và Checkbox thẳng hàng với nhau theo dòng chữ đầu tiên */}
|
|
333
305
|
<div className="flex items-center text-sm leading-snug group-data-[size=sm]/field:text-xs">
|
|
334
306
|
​
|
|
@@ -349,36 +321,33 @@ function CheckboxMicroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
349
321
|
Tự động đăng nhập vào lần sau.
|
|
350
322
|
</FieldDescription>
|
|
351
323
|
</div>
|
|
352
|
-
</Field>`}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
324
|
+
</Field>`} preview={
|
|
325
|
+
<>
|
|
326
|
+
<Field className="flex items-start gap-3" data-size={globalSize}>
|
|
327
|
+
<div className="flex items-center text-sm leading-snug group-data-[size=sm]/field:text-xs">
|
|
328
|
+
​
|
|
329
|
+
<Checkbox id="cb-field-micro" size={globalSize}>
|
|
330
|
+
<CheckboxIndicator>
|
|
331
|
+
<CheckIcon />
|
|
332
|
+
</CheckboxIndicator>
|
|
333
|
+
</Checkbox>
|
|
334
|
+
</div>
|
|
335
|
+
<div className="grid gap-1.5 leading-none">
|
|
336
|
+
<FieldLabel
|
|
337
|
+
htmlFor="cb-field-micro"
|
|
338
|
+
className="font-medium cursor-pointer"
|
|
339
|
+
>
|
|
340
|
+
Lưu mật khẩu
|
|
341
|
+
</FieldLabel>
|
|
342
|
+
<FieldDescription>
|
|
343
|
+
Tự động đăng nhập vào lần sau.
|
|
344
|
+
</FieldDescription>
|
|
345
|
+
</div>
|
|
346
|
+
</Field>
|
|
347
|
+
</>
|
|
348
|
+
} />
|
|
377
349
|
|
|
378
|
-
<
|
|
379
|
-
label="Trạng thái Lỗi thủ công"
|
|
380
|
-
description="Tự gắn aria-invalid vào Checkbox và dùng FieldError."
|
|
381
|
-
codeString={`<Field
|
|
350
|
+
<ShowcaseExample title="Trạng thái Lỗi thủ công" description="Tự gắn aria-invalid vào Checkbox và dùng FieldError." code={`<Field
|
|
382
351
|
className="flex flex-row items-start gap-3"
|
|
383
352
|
data-invalid={true}
|
|
384
353
|
>
|
|
@@ -399,39 +368,36 @@ function CheckboxMicroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
399
368
|
</FieldLabel>
|
|
400
369
|
<FieldError>Bắt buộc phải chọn ô này.</FieldError>
|
|
401
370
|
</div>
|
|
402
|
-
</Field>`}
|
|
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
|
-
|
|
371
|
+
</Field>`} preview={
|
|
372
|
+
<>
|
|
373
|
+
<Field
|
|
374
|
+
className="flex flex-row items-start gap-3"
|
|
375
|
+
data-invalid={true}
|
|
376
|
+
data-size={globalSize}
|
|
377
|
+
>
|
|
378
|
+
<div className="flex items-center text-sm leading-snug group-data-[size=sm]/field:text-xs">
|
|
379
|
+
​
|
|
380
|
+
<Checkbox id="cb-err-micro" size={globalSize} aria-invalid={true}>
|
|
381
|
+
<CheckboxIndicator>
|
|
382
|
+
<CheckIcon />
|
|
383
|
+
</CheckboxIndicator>
|
|
384
|
+
</Checkbox>
|
|
385
|
+
</div>
|
|
386
|
+
<div className="grid gap-1.5 leading-none">
|
|
387
|
+
<FieldLabel
|
|
388
|
+
htmlFor="cb-err-micro"
|
|
389
|
+
className="font-medium cursor-pointer"
|
|
390
|
+
>
|
|
391
|
+
Đồng ý quy định
|
|
392
|
+
</FieldLabel>
|
|
393
|
+
<FieldError>Bắt buộc phải chọn ô này.</FieldError>
|
|
394
|
+
</div>
|
|
395
|
+
</Field>
|
|
396
|
+
</>
|
|
397
|
+
} />
|
|
428
398
|
</ExampleGrid>
|
|
429
399
|
|
|
430
|
-
<
|
|
431
|
-
label="🧭 Use Case Comparison"
|
|
432
|
-
description="So sánh nhanh khi nào dùng Micro và Macro."
|
|
433
|
-
fullWidth
|
|
434
|
-
codeString={`<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
|
|
400
|
+
<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">
|
|
435
401
|
{/* Story 1: Macro wins */}
|
|
436
402
|
<div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
|
|
437
403
|
<div className="flex items-start gap-3">
|
|
@@ -533,124 +499,120 @@ function CheckboxMicroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
533
499
|
</div>
|
|
534
500
|
</div>
|
|
535
501
|
</div>
|
|
536
|
-
</div>`}
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
</div>
|
|
502
|
+
</div>`} preview={
|
|
503
|
+
<>
|
|
504
|
+
<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
|
|
505
|
+
<div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
|
|
506
|
+
<div className="flex items-start gap-3">
|
|
507
|
+
<span className="mt-0.5 shrink-0 rounded-full bg-green-500/10 p-1.5 text-green-600">
|
|
508
|
+
<svg
|
|
509
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
510
|
+
className="size-4"
|
|
511
|
+
viewBox="0 0 24 24"
|
|
512
|
+
fill="none"
|
|
513
|
+
stroke="currentColor"
|
|
514
|
+
strokeWidth="2"
|
|
515
|
+
strokeLinecap="round"
|
|
516
|
+
strokeLinejoin="round"
|
|
517
|
+
aria-hidden="true"
|
|
518
|
+
>
|
|
519
|
+
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
|
|
520
|
+
</svg>
|
|
521
|
+
</span>
|
|
522
|
+
<div>
|
|
523
|
+
<p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
|
|
524
|
+
Story 1 · Dùng Macro
|
|
525
|
+
</p>
|
|
526
|
+
<h3 className="mt-0.5 text-sm font-semibold text-foreground">
|
|
527
|
+
Checkbox trong trang Cài đặt
|
|
528
|
+
</h3>
|
|
529
|
+
</div>
|
|
530
|
+
</div>
|
|
531
|
+
<p className="text-xs text-muted-foreground leading-relaxed">
|
|
532
|
+
Form cài đặt có rất nhiều tuỳ chọn dạng "Bật / Tắt" với mô tả dài.
|
|
533
|
+
Code sẽ rất sạch và ngắn.
|
|
534
|
+
</p>
|
|
535
|
+
<div className="rounded-lg bg-muted/50 p-3 flex flex-col gap-4">
|
|
536
|
+
<CheckboxPreset
|
|
537
|
+
size="sm"
|
|
538
|
+
label="Nhận Email Marketing"
|
|
539
|
+
description="Gửi email cho bạn về các chương trình khuyến mãi hàng tuần."
|
|
540
|
+
/>
|
|
541
|
+
<CheckboxPreset
|
|
542
|
+
size="sm"
|
|
543
|
+
label="Thông báo bảo mật"
|
|
544
|
+
description="Cảnh báo khi có thiết bị lạ đăng nhập."
|
|
545
|
+
defaultChecked
|
|
546
|
+
/>
|
|
547
|
+
</div>
|
|
548
|
+
</div>
|
|
584
549
|
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
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
|
-
|
|
550
|
+
<div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
|
|
551
|
+
<div className="flex items-start gap-3">
|
|
552
|
+
<span className="mt-0.5 shrink-0 rounded-full bg-blue-500/10 p-1.5 text-blue-600">
|
|
553
|
+
<svg
|
|
554
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
555
|
+
className="size-4"
|
|
556
|
+
viewBox="0 0 24 24"
|
|
557
|
+
fill="none"
|
|
558
|
+
stroke="currentColor"
|
|
559
|
+
strokeWidth="2"
|
|
560
|
+
strokeLinecap="round"
|
|
561
|
+
strokeLinejoin="round"
|
|
562
|
+
aria-hidden="true"
|
|
563
|
+
>
|
|
564
|
+
<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" />
|
|
565
|
+
</svg>
|
|
566
|
+
</span>
|
|
567
|
+
<div>
|
|
568
|
+
<p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
|
|
569
|
+
Story 2 · Dùng Micro
|
|
570
|
+
</p>
|
|
571
|
+
<h3 className="mt-0.5 text-sm font-semibold text-foreground">
|
|
572
|
+
Table Row Selection
|
|
573
|
+
</h3>
|
|
574
|
+
</div>
|
|
575
|
+
</div>
|
|
576
|
+
<p className="text-xs text-muted-foreground leading-relaxed">
|
|
577
|
+
Bạn cần ô Checkbox ở đầu mỗi dòng trong bảng để chọn nhiều hàng. Ở
|
|
578
|
+
đây Checkbox đứng độc lập, hoàn toàn không cần Label hay
|
|
579
|
+
Description đi kèm.
|
|
580
|
+
</p>
|
|
581
|
+
<div className="rounded-lg bg-muted/50 p-3">
|
|
582
|
+
<div className="border border-border rounded-md divide-y overflow-hidden">
|
|
583
|
+
<div className="flex items-center gap-3 p-2 bg-muted">
|
|
584
|
+
<Checkbox size="sm">
|
|
585
|
+
<CheckboxIndicator>
|
|
586
|
+
<MinusIcon />
|
|
587
|
+
</CheckboxIndicator>
|
|
588
|
+
</Checkbox>
|
|
589
|
+
<span className="text-xs font-semibold">Tên nhân viên</span>
|
|
590
|
+
</div>
|
|
591
|
+
<div className="flex items-center gap-3 p-2 bg-background hover:bg-muted/50">
|
|
592
|
+
<Checkbox size="sm" defaultChecked>
|
|
593
|
+
<CheckboxIndicator>
|
|
594
|
+
<CheckIcon />
|
|
595
|
+
</CheckboxIndicator>
|
|
596
|
+
</Checkbox>
|
|
597
|
+
<span className="text-xs">John Doe</span>
|
|
598
|
+
</div>
|
|
599
|
+
</div>
|
|
600
|
+
</div>
|
|
601
|
+
</div>
|
|
602
|
+
</div>
|
|
603
|
+
</>
|
|
604
|
+
} />
|
|
640
605
|
</div>
|
|
641
606
|
);
|
|
642
607
|
}
|
|
643
608
|
|
|
644
|
-
// ──────────────────────────────────────────────────────────
|
|
645
|
-
// SECTION 3: Entry point
|
|
646
|
-
// ──────────────────────────────────────────────────────────
|
|
647
609
|
export default function CheckboxShowcase() {
|
|
648
610
|
const { size: globalSize } = useDevContext();
|
|
649
611
|
return (
|
|
650
612
|
<Showcase
|
|
651
613
|
title="Checkbox"
|
|
652
614
|
description="Thành phần cho phép người dùng chọn hoặc bỏ chọn một tuỳ chọn độc lập."
|
|
653
|
-
|
|
615
|
+
guideline={
|
|
654
616
|
<ShowcaseDocs>
|
|
655
617
|
<DocsP>
|
|
656
618
|
Dùng để thu thập đầu vào dạng đúng/sai hoặc nhiều lựa chọn độc lập
|
|
@@ -659,14 +621,8 @@ export default function CheckboxShowcase() {
|
|
|
659
621
|
</DocsP>
|
|
660
622
|
</ShowcaseDocs>
|
|
661
623
|
}
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
label: "Micro (Primitive)",
|
|
665
|
-
content: <CheckboxMicroShowcase globalSize={globalSize} /> },
|
|
666
|
-
{
|
|
667
|
-
label: "Macro (Preset)",
|
|
668
|
-
content: <CheckboxMacroShowcase globalSize={globalSize} /> },
|
|
669
|
-
]}
|
|
624
|
+
micro={{ content: <CheckboxMicroShowcase globalSize={globalSize} /> }}
|
|
625
|
+
macro={{ content: <CheckboxMacroShowcase globalSize={globalSize} /> }}
|
|
670
626
|
/>
|
|
671
627
|
);
|
|
672
628
|
}
|