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
|
@@ -14,15 +14,12 @@ import {
|
|
|
14
14
|
DocsH3,
|
|
15
15
|
DocsP,
|
|
16
16
|
ExampleGrid,
|
|
17
|
-
|
|
17
|
+
ShowcaseExample,
|
|
18
18
|
Showcase,
|
|
19
19
|
ShowcaseDocs
|
|
20
20
|
} from "../../dev/components/showcase";
|
|
21
21
|
import { type Size } from "../../lib/types";
|
|
22
22
|
|
|
23
|
-
// ──────────────────────────────────────────────────────────
|
|
24
|
-
// RHF Form Demo (Macro)
|
|
25
|
-
// ──────────────────────────────────────────────────────────
|
|
26
23
|
const formSchema = z.object({
|
|
27
24
|
marketing: z.boolean().default(false).optional() });
|
|
28
25
|
type FormValues = z.infer<typeof formSchema>;
|
|
@@ -85,57 +82,47 @@ function SwitchForm({ size }: { size: Size }) {
|
|
|
85
82
|
);
|
|
86
83
|
}`;
|
|
87
84
|
|
|
88
|
-
// ──────────────────────────────────────────────────────────
|
|
89
|
-
// SECTION 1: Macro Content
|
|
90
|
-
// ──────────────────────────────────────────────────────────
|
|
91
85
|
function SwitchMacroShowcase({ globalSize }: { globalSize: Size }) {
|
|
92
86
|
const [checked, setChecked] = useState(false);
|
|
93
87
|
|
|
94
88
|
return (
|
|
95
|
-
<div className="space-y-10
|
|
89
|
+
<div className="space-y-10">
|
|
96
90
|
<ExampleGrid>
|
|
97
|
-
<
|
|
98
|
-
label="Tiêu chuẩn"
|
|
99
|
-
description="Công tắc cơ bản có nhãn và mô tả."
|
|
100
|
-
codeString={`<SwitchPreset
|
|
91
|
+
<ShowcaseExample title="Tiêu chuẩn" description="Công tắc cơ bản có nhãn và mô tả." code={`<SwitchPreset
|
|
101
92
|
className="w-full"
|
|
102
93
|
label="Chế độ máy bay"
|
|
103
94
|
description="Vô hiệu hóa tất cả các kết nối không dây."
|
|
104
|
-
/>`}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
95
|
+
/>`} preview={
|
|
96
|
+
<>
|
|
97
|
+
<SwitchPreset
|
|
98
|
+
className="w-full"
|
|
99
|
+
size={globalSize}
|
|
100
|
+
label="Chế độ máy bay"
|
|
101
|
+
description="Vô hiệu hóa tất cả các kết nối không dây."
|
|
102
|
+
/>
|
|
103
|
+
</>
|
|
104
|
+
} />
|
|
113
105
|
|
|
114
|
-
<
|
|
115
|
-
label="Trạng thái Lỗi (Error)"
|
|
116
|
-
description="Báo lỗi khi bật/tắt thất bại."
|
|
117
|
-
codeString={`<div className="w-full flex flex-col gap-6">
|
|
106
|
+
<ShowcaseExample title="Trạng thái Lỗi (Error)" description="Báo lỗi khi bật/tắt thất bại." code={`<div className="w-full flex flex-col gap-6">
|
|
118
107
|
<SwitchPreset
|
|
119
108
|
label="Kết nối mạng (Lỗi)"
|
|
120
109
|
errorMessage="Mất kết nối mạng. Không thể lưu cài đặt."
|
|
121
110
|
/>
|
|
122
|
-
</div>`}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
111
|
+
</div>`} preview={
|
|
112
|
+
<>
|
|
113
|
+
<div className="w-full flex flex-col gap-6">
|
|
114
|
+
<SwitchPreset
|
|
115
|
+
size={globalSize}
|
|
116
|
+
label="Kết nối mạng (Lỗi)"
|
|
117
|
+
errorMessage="Mất kết nối mạng. Không thể lưu cài đặt."
|
|
118
|
+
/>
|
|
119
|
+
</div>
|
|
120
|
+
</>
|
|
121
|
+
} />
|
|
132
122
|
</ExampleGrid>
|
|
133
123
|
|
|
134
124
|
<ExampleGrid>
|
|
135
|
-
<
|
|
136
|
-
label="Khóa / Bất hoạt (Disabled)"
|
|
137
|
-
description="Người dùng không thể tương tác với công tắc."
|
|
138
|
-
codeString={`<div className="w-full flex flex-col gap-6">
|
|
125
|
+
<ShowcaseExample title="Khóa / Bất hoạt (Disabled)" description="Người dùng không thể tương tác với công tắc." code={`<div className="w-full flex flex-col gap-6">
|
|
139
126
|
<SwitchPreset
|
|
140
127
|
label="Đồng bộ danh bạ"
|
|
141
128
|
description="Yêu cầu cấp quyền truy cập vào danh bạ."
|
|
@@ -147,29 +134,27 @@ function SwitchMacroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
147
134
|
defaultChecked
|
|
148
135
|
disabled
|
|
149
136
|
/>
|
|
150
|
-
</div>`}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
137
|
+
</div>`} preview={
|
|
138
|
+
<>
|
|
139
|
+
<div className="w-full flex flex-col gap-6">
|
|
140
|
+
<SwitchPreset
|
|
141
|
+
size={globalSize}
|
|
142
|
+
label="Đồng bộ danh bạ"
|
|
143
|
+
description="Yêu cầu cấp quyền truy cập vào danh bạ."
|
|
144
|
+
disabled
|
|
145
|
+
/>
|
|
146
|
+
<SwitchPreset
|
|
147
|
+
size={globalSize}
|
|
148
|
+
label="Dữ liệu di động"
|
|
149
|
+
description="Dữ liệu di động đang bị tắt trên toàn cầu."
|
|
150
|
+
defaultChecked
|
|
151
|
+
disabled
|
|
152
|
+
/>
|
|
153
|
+
</div>
|
|
154
|
+
</>
|
|
155
|
+
} />
|
|
168
156
|
|
|
169
|
-
<
|
|
170
|
-
label="Nhãn phức tạp (Custom Content)"
|
|
171
|
-
description="Truyền React Node vào Label để tạo giao diện phong phú."
|
|
172
|
-
codeString={`<SwitchPreset
|
|
157
|
+
<ShowcaseExample title="Nhãn phức tạp (Custom Content)" description="Truyền React Node vào Label để tạo giao diện phong phú." code={`<SwitchPreset
|
|
173
158
|
label={
|
|
174
159
|
<span className="flex items-center gap-2">
|
|
175
160
|
Xác thực 2 bước (2FA)
|
|
@@ -179,75 +164,66 @@ function SwitchMacroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
179
164
|
</span>
|
|
180
165
|
}
|
|
181
166
|
description="Thêm một lớp bảo mật bổ sung cho tài khoản của bạn. Chúng tôi sẽ yêu cầu mã xác nhận mỗi khi bạn đăng nhập từ thiết bị mới."
|
|
182
|
-
/>`}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
167
|
+
/>`} preview={
|
|
168
|
+
<>
|
|
169
|
+
<SwitchPreset
|
|
170
|
+
size={globalSize}
|
|
171
|
+
label={
|
|
172
|
+
<span className="flex items-center gap-2">
|
|
173
|
+
Xác thực 2 bước (2FA)
|
|
174
|
+
<span className="rounded bg-success/20 px-1.5 py-0.5 text-[10px] font-semibold text-success">
|
|
175
|
+
KHUYÊN DÙNG
|
|
176
|
+
</span>
|
|
177
|
+
</span>
|
|
178
|
+
}
|
|
179
|
+
description="Thêm một lớp bảo mật bổ sung cho tài khoản của bạn. Chúng tôi sẽ yêu cầu mã xác nhận mỗi khi bạn đăng nhập từ thiết bị mới."
|
|
180
|
+
/>
|
|
181
|
+
</>
|
|
182
|
+
} />
|
|
197
183
|
</ExampleGrid>
|
|
198
184
|
|
|
199
185
|
<ExampleGrid>
|
|
200
|
-
<
|
|
201
|
-
label="React State (Controlled Mode)"
|
|
202
|
-
description="Sử dụng biến state của React để điều khiển."
|
|
203
|
-
codeString={`const [checked, setChecked] = useState(false); return (
|
|
186
|
+
<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 (
|
|
204
187
|
<SwitchPreset
|
|
205
188
|
checked={checked}
|
|
206
189
|
onCheckedChange={(c) => setChecked(!!c)}
|
|
207
190
|
label="Chế độ nhà phát triển"
|
|
208
191
|
/>
|
|
209
|
-
);`}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
192
|
+
);`} preview={
|
|
193
|
+
<>
|
|
194
|
+
<div className="w-full flex flex-col gap-4">
|
|
195
|
+
<SwitchPreset
|
|
196
|
+
size={globalSize}
|
|
197
|
+
checked={checked}
|
|
198
|
+
onCheckedChange={(c) => setChecked(!!c)}
|
|
199
|
+
label="Chế độ nhà phát triển"
|
|
200
|
+
description="Bật các tính năng thử nghiệm nội bộ."
|
|
201
|
+
/>
|
|
202
|
+
<p className="text-sm text-muted-foreground">
|
|
203
|
+
Trạng thái:{" "}
|
|
204
|
+
<span className="font-mono font-bold text-foreground">
|
|
205
|
+
{checked ? "BẬT" : "TẮT"}
|
|
206
|
+
</span>
|
|
207
|
+
</p>
|
|
208
|
+
</div>
|
|
209
|
+
</>
|
|
210
|
+
} />
|
|
227
211
|
|
|
228
|
-
<
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
<SwitchForm size={globalSize} />
|
|
234
|
-
</ExampleSection>
|
|
212
|
+
<ShowcaseExample title="Tích hợp React Hook Form" description="Dùng Controller của RHF để bọc SwitchPreset." code={rhfCode} preview={
|
|
213
|
+
<>
|
|
214
|
+
<SwitchForm size={globalSize} />
|
|
215
|
+
</>
|
|
216
|
+
} />
|
|
235
217
|
</ExampleGrid>
|
|
236
218
|
</div>
|
|
237
219
|
);
|
|
238
220
|
}
|
|
239
221
|
|
|
240
|
-
// ──────────────────────────────────────────────────────────
|
|
241
|
-
// SECTION 2: Micro Content
|
|
242
|
-
// ──────────────────────────────────────────────────────────
|
|
243
222
|
function SwitchMicroShowcase({ globalSize }: { globalSize: Size }) {
|
|
244
223
|
return (
|
|
245
|
-
<div className="space-y-10
|
|
224
|
+
<div className="space-y-10">
|
|
246
225
|
<ExampleGrid>
|
|
247
|
-
<
|
|
248
|
-
label="Cơ bản (Primitive)"
|
|
249
|
-
description="Kết nối thủ công Switch và SwitchThumb."
|
|
250
|
-
codeString={`<div className="flex items-center gap-4">
|
|
226
|
+
<ShowcaseExample title="Cơ bản (Primitive)" description="Kết nối thủ công Switch và SwitchThumb." code={`<div className="flex items-center gap-4">
|
|
251
227
|
<Switch id="sw-micro">
|
|
252
228
|
<SwitchThumb />
|
|
253
229
|
</Switch>
|
|
@@ -257,22 +233,20 @@ function SwitchMicroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
257
233
|
>
|
|
258
234
|
Công tắc đơn trần
|
|
259
235
|
</label>
|
|
260
|
-
</div>`}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
236
|
+
</div>`} preview={
|
|
237
|
+
<>
|
|
238
|
+
<div className="flex items-center gap-4">
|
|
239
|
+
<Switch size={globalSize} id="sw-micro">
|
|
240
|
+
<SwitchThumb />
|
|
241
|
+
</Switch>
|
|
242
|
+
<label htmlFor="sw-micro" className="text-sm cursor-pointer">
|
|
243
|
+
Công tắc đơn trần
|
|
244
|
+
</label>
|
|
245
|
+
</div>
|
|
246
|
+
</>
|
|
247
|
+
} />
|
|
271
248
|
|
|
272
|
-
<
|
|
273
|
-
label="Layout Đảo ngược (Reverse)"
|
|
274
|
-
description="Dùng Field với orientation='horizontal' để đẩy Switch sang bên phải."
|
|
275
|
-
codeString={`<div className="w-full space-y-4">
|
|
249
|
+
<ShowcaseExample title="Layout Đảo ngược (Reverse)" description="Dùng Field với orientation='horizontal' để đẩy Switch sang bên phải." code={`<div className="w-full space-y-4">
|
|
276
250
|
<Field
|
|
277
251
|
orientation="horizontal"
|
|
278
252
|
className="justify-between"
|
|
@@ -301,48 +275,46 @@ function SwitchMicroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
301
275
|
<SwitchThumb />
|
|
302
276
|
</Switch>
|
|
303
277
|
</Field>
|
|
304
|
-
</div>`}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
278
|
+
</div>`} preview={
|
|
279
|
+
<>
|
|
280
|
+
<div className="w-full space-y-4">
|
|
281
|
+
<Field
|
|
282
|
+
orientation="horizontal"
|
|
283
|
+
size={globalSize}
|
|
284
|
+
className="justify-between"
|
|
285
|
+
>
|
|
286
|
+
<FieldLabel
|
|
287
|
+
htmlFor="switch-notif"
|
|
288
|
+
className="font-normal cursor-pointer"
|
|
289
|
+
>
|
|
290
|
+
Thông báo đẩy
|
|
291
|
+
</FieldLabel>
|
|
292
|
+
<Switch id="switch-notif" size={globalSize} defaultChecked>
|
|
293
|
+
<SwitchThumb />
|
|
294
|
+
</Switch>
|
|
295
|
+
</Field>
|
|
296
|
+
<Field
|
|
297
|
+
orientation="horizontal"
|
|
298
|
+
size={globalSize}
|
|
299
|
+
className="justify-between"
|
|
300
|
+
>
|
|
301
|
+
<FieldLabel
|
|
302
|
+
htmlFor="switch-dark"
|
|
303
|
+
className="font-normal cursor-pointer"
|
|
304
|
+
>
|
|
305
|
+
Chế độ tối (Dark Mode)
|
|
306
|
+
</FieldLabel>
|
|
307
|
+
<Switch id="switch-dark" size={globalSize}>
|
|
308
|
+
<SwitchThumb />
|
|
309
|
+
</Switch>
|
|
310
|
+
</Field>
|
|
311
|
+
</div>
|
|
312
|
+
</>
|
|
313
|
+
} />
|
|
339
314
|
</ExampleGrid>
|
|
340
315
|
|
|
341
316
|
<ExampleGrid>
|
|
342
|
-
<
|
|
343
|
-
label="Khóa (Disabled)"
|
|
344
|
-
description="Các công tắc đảo ngược nhưng bị vô hiệu hoá."
|
|
345
|
-
codeString={`<div className="w-full space-y-4">
|
|
317
|
+
<ShowcaseExample title="Khóa (Disabled)" description="Các công tắc đảo ngược nhưng bị vô hiệu hoá." code={`<div className="w-full space-y-4">
|
|
346
318
|
<Field
|
|
347
319
|
orientation="horizontal"
|
|
348
320
|
className="justify-between"
|
|
@@ -371,46 +343,44 @@ function SwitchMicroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
371
343
|
<SwitchThumb />
|
|
372
344
|
</Switch>
|
|
373
345
|
</Field>
|
|
374
|
-
</div>`}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
346
|
+
</div>`} preview={
|
|
347
|
+
<>
|
|
348
|
+
<div className="w-full space-y-4">
|
|
349
|
+
<Field
|
|
350
|
+
orientation="horizontal"
|
|
351
|
+
size={globalSize}
|
|
352
|
+
className="justify-between"
|
|
353
|
+
>
|
|
354
|
+
<FieldLabel
|
|
355
|
+
htmlFor="switch-d1"
|
|
356
|
+
className="font-normal text-muted-foreground"
|
|
357
|
+
>
|
|
358
|
+
Bluetooth
|
|
359
|
+
</FieldLabel>
|
|
360
|
+
<Switch id="switch-d1" disabled size={globalSize} defaultChecked>
|
|
361
|
+
<SwitchThumb />
|
|
362
|
+
</Switch>
|
|
363
|
+
</Field>
|
|
364
|
+
<Field
|
|
365
|
+
orientation="horizontal"
|
|
366
|
+
size={globalSize}
|
|
367
|
+
className="justify-between"
|
|
368
|
+
>
|
|
369
|
+
<FieldLabel
|
|
370
|
+
htmlFor="switch-d2"
|
|
371
|
+
className="font-normal text-muted-foreground"
|
|
372
|
+
>
|
|
373
|
+
Vị trí (GPS)
|
|
374
|
+
</FieldLabel>
|
|
375
|
+
<Switch id="switch-d2" disabled size={globalSize}>
|
|
376
|
+
<SwitchThumb />
|
|
377
|
+
</Switch>
|
|
378
|
+
</Field>
|
|
379
|
+
</div>
|
|
380
|
+
</>
|
|
381
|
+
} />
|
|
409
382
|
|
|
410
|
-
<
|
|
411
|
-
label="Trạng thái Lỗi thủ công"
|
|
412
|
-
description="Tự gắn aria-invalid vào Switch."
|
|
413
|
-
codeString={`<Field
|
|
383
|
+
<ShowcaseExample title="Trạng thái Lỗi thủ công" description="Tự gắn aria-invalid vào Switch." code={`<Field
|
|
414
384
|
orientation="horizontal"
|
|
415
385
|
data-invalid={true}
|
|
416
386
|
className="justify-between items-start"
|
|
@@ -431,40 +401,37 @@ function SwitchMicroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
431
401
|
>
|
|
432
402
|
<SwitchThumb />
|
|
433
403
|
</Switch>
|
|
434
|
-
</Field>`}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
404
|
+
</Field>`} preview={
|
|
405
|
+
<>
|
|
406
|
+
<Field
|
|
407
|
+
orientation="horizontal"
|
|
408
|
+
data-invalid={true}
|
|
409
|
+
size={globalSize}
|
|
410
|
+
className="justify-between items-start"
|
|
411
|
+
>
|
|
412
|
+
<div className="grid gap-1.5">
|
|
413
|
+
<FieldLabel
|
|
414
|
+
htmlFor="switch-err"
|
|
415
|
+
className="font-normal cursor-pointer"
|
|
416
|
+
>
|
|
417
|
+
Tự động sao lưu
|
|
418
|
+
</FieldLabel>
|
|
419
|
+
<FieldError>Máy chủ sao lưu đang offline.</FieldError>
|
|
420
|
+
</div>
|
|
421
|
+
<Switch
|
|
422
|
+
id="switch-err"
|
|
423
|
+
size={globalSize}
|
|
424
|
+
aria-invalid={true}
|
|
425
|
+
defaultChecked
|
|
426
|
+
>
|
|
427
|
+
<SwitchThumb />
|
|
428
|
+
</Switch>
|
|
429
|
+
</Field>
|
|
430
|
+
</>
|
|
431
|
+
} />
|
|
461
432
|
</ExampleGrid>
|
|
462
433
|
|
|
463
|
-
<
|
|
464
|
-
label="🧭 Use Case Comparison"
|
|
465
|
-
description="So sánh nhanh khi nào dùng Micro và Macro."
|
|
466
|
-
fullWidth
|
|
467
|
-
codeString={`<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
|
|
434
|
+
<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">
|
|
468
435
|
{/* Story 1: Macro wins */}
|
|
469
436
|
<div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
|
|
470
437
|
<div className="flex items-start gap-3">
|
|
@@ -554,141 +521,110 @@ function SwitchMicroShowcase({ globalSize }: { globalSize: Size }) {
|
|
|
554
521
|
</div>
|
|
555
522
|
</div>
|
|
556
523
|
</div>
|
|
557
|
-
</div>`}
|
|
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
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
</div>
|
|
524
|
+
</div>`} preview={
|
|
525
|
+
<>
|
|
526
|
+
<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
|
|
527
|
+
<div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
|
|
528
|
+
<div className="flex items-start gap-3">
|
|
529
|
+
<span className="mt-0.5 shrink-0 rounded-full bg-green-500/10 p-1.5 text-green-600">
|
|
530
|
+
<svg
|
|
531
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
532
|
+
className="size-4"
|
|
533
|
+
viewBox="0 0 24 24"
|
|
534
|
+
fill="none"
|
|
535
|
+
stroke="currentColor"
|
|
536
|
+
strokeWidth="2"
|
|
537
|
+
strokeLinecap="round"
|
|
538
|
+
strokeLinejoin="round"
|
|
539
|
+
aria-hidden="true"
|
|
540
|
+
>
|
|
541
|
+
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
|
|
542
|
+
</svg>
|
|
543
|
+
</span>
|
|
544
|
+
<div>
|
|
545
|
+
<p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
|
|
546
|
+
Story 1 · Dùng Macro
|
|
547
|
+
</p>
|
|
548
|
+
<h3 className="mt-0.5 text-sm font-semibold text-foreground">
|
|
549
|
+
Form thông thường
|
|
550
|
+
</h3>
|
|
551
|
+
</div>
|
|
552
|
+
</div>
|
|
553
|
+
<p className="text-xs text-muted-foreground leading-relaxed">
|
|
554
|
+
Bạn cần một Switch giống như Checkbox (công tắc ở bên trái, chữ
|
|
555
|
+
bên phải). Dùng Preset cho nhanh gọn.
|
|
556
|
+
</p>
|
|
557
|
+
<div className="rounded-lg bg-muted/50 p-3">
|
|
558
|
+
<SwitchPreset
|
|
559
|
+
size="sm"
|
|
560
|
+
label="Đồng ý điều khoản"
|
|
561
|
+
description="Bật để tiếp tục."
|
|
562
|
+
/>
|
|
563
|
+
</div>
|
|
564
|
+
</div>
|
|
599
565
|
|
|
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
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
566
|
+
<div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
|
|
567
|
+
<div className="flex items-start gap-3">
|
|
568
|
+
<span className="mt-0.5 shrink-0 rounded-full bg-blue-500/10 p-1.5 text-blue-600">
|
|
569
|
+
<svg
|
|
570
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
571
|
+
className="size-4"
|
|
572
|
+
viewBox="0 0 24 24"
|
|
573
|
+
fill="none"
|
|
574
|
+
stroke="currentColor"
|
|
575
|
+
strokeWidth="2"
|
|
576
|
+
strokeLinecap="round"
|
|
577
|
+
strokeLinejoin="round"
|
|
578
|
+
aria-hidden="true"
|
|
579
|
+
>
|
|
580
|
+
<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" />
|
|
581
|
+
</svg>
|
|
582
|
+
</span>
|
|
583
|
+
<div>
|
|
584
|
+
<p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
|
|
585
|
+
Story 2 · Dùng Micro
|
|
586
|
+
</p>
|
|
587
|
+
<h3 className="mt-0.5 text-sm font-semibold text-foreground">
|
|
588
|
+
Menu Cài đặt (iOS Style)
|
|
589
|
+
</h3>
|
|
590
|
+
</div>
|
|
591
|
+
</div>
|
|
592
|
+
<p className="text-xs text-muted-foreground leading-relaxed">
|
|
593
|
+
Giống như iPhone, chữ nằm bên trái và Công tắc nằm tít bên phải
|
|
594
|
+
của dòng. Macro không hỗ trợ layout này nên bạn dùng cấu trúc
|
|
595
|
+
Field + Micro.
|
|
596
|
+
</p>
|
|
597
|
+
<div className="rounded-lg bg-muted/50 p-3 border border-border divide-y">
|
|
598
|
+
<div className="p-2 flex justify-between items-center">
|
|
599
|
+
<span className="text-sm font-medium">Wi-Fi</span>
|
|
600
|
+
<Switch size="sm" defaultChecked>
|
|
601
|
+
<SwitchThumb />
|
|
602
|
+
</Switch>
|
|
603
|
+
</div>
|
|
604
|
+
<div className="p-2 flex justify-between items-center">
|
|
605
|
+
<span className="text-sm font-medium">Bluetooth</span>
|
|
606
|
+
<Switch size="sm">
|
|
607
|
+
<SwitchThumb />
|
|
608
|
+
</Switch>
|
|
609
|
+
</div>
|
|
610
|
+
</div>
|
|
611
|
+
</div>
|
|
612
|
+
</div>
|
|
613
|
+
</>
|
|
614
|
+
} />
|
|
649
615
|
</div>
|
|
650
616
|
);
|
|
651
617
|
}
|
|
652
618
|
|
|
653
|
-
// ──────────────────────────────────────────────────────────
|
|
654
|
-
// SECTION 3: Entry point
|
|
655
|
-
// ──────────────────────────────────────────────────────────
|
|
656
619
|
export default function SwitchShowcase() {
|
|
657
620
|
const { size: globalSize } = useDevContext();
|
|
658
621
|
return (
|
|
659
622
|
<Showcase
|
|
660
623
|
title="Switch"
|
|
661
624
|
description="Thành phần điều khiển cho phép người dùng chuyển đổi qua lại giữa 2 trạng thái Bật / Tắt."
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
<DocsH3>Khi nào nên dùng Macro</DocsH3>
|
|
666
|
-
<DocsP>
|
|
667
|
-
<DocsCode>SwitchPreset</DocsCode> đóng gói Switch + Label +
|
|
668
|
-
Description + Error Message. Nó tự động căn chỉnh khoảng cách và
|
|
669
|
-
liên kết ID. Dùng trong 95% trường hợp làm màn hình cài đặt
|
|
670
|
-
(Settings) hoặc form yêu cầu bật/tắt tính năng.
|
|
671
|
-
</DocsP>
|
|
672
|
-
</ShowcaseDocs>
|
|
673
|
-
<ShowcaseDocs>
|
|
674
|
-
<DocsH3>Khi nào nên dùng Micro</DocsH3>
|
|
675
|
-
<DocsP>
|
|
676
|
-
Dùng <DocsCode>Switch</DocsCode> và{" "}
|
|
677
|
-
<DocsCode>SwitchThumb</DocsCode> nguyên thuỷ khi bạn cần một
|
|
678
|
-
layout không theo chuẩn <DocsCode>SwitchPreset</DocsCode> (ví dụ:
|
|
679
|
-
Switch nằm bên phải Label thay vì nằm bên trái).
|
|
680
|
-
</DocsP>
|
|
681
|
-
</ShowcaseDocs>
|
|
682
|
-
</div>
|
|
683
|
-
}
|
|
684
|
-
tabs={[
|
|
685
|
-
{
|
|
686
|
-
label: "Micro (Primitive)",
|
|
687
|
-
content: <SwitchMicroShowcase globalSize={globalSize} /> },
|
|
688
|
-
{
|
|
689
|
-
label: "Macro (Preset)",
|
|
690
|
-
content: <SwitchMacroShowcase globalSize={globalSize} /> },
|
|
691
|
-
]}
|
|
625
|
+
|
|
626
|
+
micro={{ content: <SwitchMicroShowcase globalSize={globalSize} /> }}
|
|
627
|
+
macro={{ content: <SwitchMacroShowcase globalSize={globalSize} /> }}
|
|
692
628
|
/>
|
|
693
629
|
);
|
|
694
630
|
}
|