@suphark/ui 0.3.2 → 0.3.3
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/CHANGELOG.md +17 -0
- package/README.md +12 -1
- package/package.json +1 -1
- package/src/components/design-system/design-system-showcase.tsx +49 -46
- package/src/components/design-system/search-index.ts +219 -0
- package/src/components/design-system/sections/hero-specimen.tsx +112 -0
- package/src/components/design-system/sections/showcase-data-display.tsx +17 -17
- package/src/components/design-system/sections/showcase-feedback.tsx +14 -20
- package/src/components/design-system/sections/showcase-forms.tsx +12 -16
- package/src/components/design-system/sections/showcase-foundations.tsx +12 -18
- package/src/components/design-system/sections/showcase-guidelines-recipes.tsx +10 -14
- package/src/components/design-system/sections/showcase-overlays-navigation.tsx +16 -20
- package/src/components/design-system/sections/showcase-overview.tsx +95 -27
- package/src/components/design-system/sections/showcase-primitives.tsx +18 -22
- package/src/components/shared/form-dialog.tsx +9 -3
- package/src/index.ts +2 -0
- package/src/styles.css +4 -0
|
@@ -55,12 +55,12 @@ export function ShowcaseFeedback() {
|
|
|
55
55
|
<div className="flex flex-col gap-1">
|
|
56
56
|
<div className="flex items-center gap-2">
|
|
57
57
|
<Badge variant="outline">Feedback & Alerts</Badge>
|
|
58
|
-
<span className="text-
|
|
58
|
+
<span className="text-muted-foreground text-sm">
|
|
59
59
|
Alerts, Sonner Toasts, Field Validation & Progress States
|
|
60
60
|
</span>
|
|
61
61
|
</div>
|
|
62
|
-
<h2 className="
|
|
63
|
-
ระบบการแจ้งเตือนและการตอบสนองต่อผู้ใช้
|
|
62
|
+
<h2 className="font-bold text-2xl text-foreground tracking-tight">
|
|
63
|
+
ระบบการแจ้งเตือนและการตอบสนองต่อผู้ใช้
|
|
64
64
|
</h2>
|
|
65
65
|
<p className="text-sm text-muted-foreground">
|
|
66
66
|
การเลือกช่องทางแจ้งเตือนที่เหมาะสมตามระดับความสำคัญ: Inline Alert, Transient Sonner Toast,
|
|
@@ -69,12 +69,10 @@ export function ShowcaseFeedback() {
|
|
|
69
69
|
</div>
|
|
70
70
|
|
|
71
71
|
{/* Feedback Channel Guidance Matrix */}
|
|
72
|
-
<Card>
|
|
72
|
+
<Card id="feedback-matrix">
|
|
73
73
|
<CardHeader>
|
|
74
|
-
<CardTitle className="text-
|
|
75
|
-
<CardDescription
|
|
76
|
-
เกณฑ์การเลือกประเภท Feedback ตามบริบทของงานในแอป Suphark
|
|
77
|
-
</CardDescription>
|
|
74
|
+
<CardTitle className="text-lg">Feedback Channel Decision Matrix</CardTitle>
|
|
75
|
+
<CardDescription>เกณฑ์การเลือกประเภท Feedback ตามบริบทของงานในแอป Suphark</CardDescription>
|
|
78
76
|
</CardHeader>
|
|
79
77
|
<CardContent className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
|
|
80
78
|
<div className="flex flex-col gap-1.5 rounded-lg border bg-card p-3">
|
|
@@ -120,7 +118,7 @@ export function ShowcaseFeedback() {
|
|
|
120
118
|
</Card>
|
|
121
119
|
|
|
122
120
|
{/* Inline Alerts */}
|
|
123
|
-
<section className="flex flex-col gap-4">
|
|
121
|
+
<section id="feedback-alert" className="flex flex-col gap-4">
|
|
124
122
|
<h3 className="text-base font-semibold">1. Inline Alerts (Alert Primitive)</h3>
|
|
125
123
|
<div className="grid gap-4 md:grid-cols-2">
|
|
126
124
|
{/* Default Info Alert */}
|
|
@@ -145,14 +143,14 @@ export function ShowcaseFeedback() {
|
|
|
145
143
|
</section>
|
|
146
144
|
|
|
147
145
|
{/* Interactive Sonner Toasts */}
|
|
148
|
-
<Card>
|
|
146
|
+
<Card id="feedback-toast">
|
|
149
147
|
<CardHeader>
|
|
150
148
|
<div className="flex items-center justify-between">
|
|
151
149
|
<div>
|
|
152
150
|
<CardTitle className="text-base flex items-center gap-2">
|
|
153
151
|
<Bell className="size-4 text-primary" /> 2. Interactive Sonner Toasts
|
|
154
152
|
</CardTitle>
|
|
155
|
-
<CardDescription
|
|
153
|
+
<CardDescription>ทดสอบยิง Toast ในสถานการณ์ต่าง ๆ</CardDescription>
|
|
156
154
|
</div>
|
|
157
155
|
<Badge variant="secondary">sonner</Badge>
|
|
158
156
|
</div>
|
|
@@ -215,14 +213,12 @@ export function ShowcaseFeedback() {
|
|
|
215
213
|
</Card>
|
|
216
214
|
|
|
217
215
|
{/* Active Task Progress & Field Error */}
|
|
218
|
-
<div className="grid gap-6 lg:grid-cols-2">
|
|
216
|
+
<div id="feedback-progress" className="grid gap-6 lg:grid-cols-2">
|
|
219
217
|
{/* Active Task Progress Simulation */}
|
|
220
218
|
<Card>
|
|
221
219
|
<CardHeader className="pb-3">
|
|
222
|
-
<CardTitle className="text-
|
|
223
|
-
<CardDescription
|
|
224
|
-
การแสดงผลขณะระบบกำลังทำงานแบบ Asynchronous
|
|
225
|
-
</CardDescription>
|
|
220
|
+
<CardTitle className="text-lg">3. Active Task Progress</CardTitle>
|
|
221
|
+
<CardDescription>การแสดงผลขณะระบบกำลังทำงานแบบ Asynchronous</CardDescription>
|
|
226
222
|
</CardHeader>
|
|
227
223
|
<CardContent className="flex flex-col gap-4">
|
|
228
224
|
{exportProgress !== null ? (
|
|
@@ -252,10 +248,8 @@ export function ShowcaseFeedback() {
|
|
|
252
248
|
{/* Input Validation State */}
|
|
253
249
|
<Card>
|
|
254
250
|
<CardHeader className="pb-3">
|
|
255
|
-
<CardTitle className="text-
|
|
256
|
-
<CardDescription
|
|
257
|
-
การระบุข้อความช่วยเหลือและข้อผิดพลาดที่ตำแหน่ง Input
|
|
258
|
-
</CardDescription>
|
|
251
|
+
<CardTitle className="text-lg">4. FieldError & Direct Validation</CardTitle>
|
|
252
|
+
<CardDescription>การระบุข้อความช่วยเหลือและข้อผิดพลาดที่ตำแหน่ง Input</CardDescription>
|
|
259
253
|
</CardHeader>
|
|
260
254
|
<CardContent>
|
|
261
255
|
<FieldGroup>
|
|
@@ -80,12 +80,12 @@ export function ShowcaseForms() {
|
|
|
80
80
|
<div className="flex flex-col gap-1">
|
|
81
81
|
<div className="flex items-center gap-2">
|
|
82
82
|
<Badge variant="outline">Form System</Badge>
|
|
83
|
-
<span className="text-
|
|
83
|
+
<span className="text-muted-foreground text-sm">
|
|
84
84
|
FieldGroup, Field, InputGroup, Combobox & Validation States
|
|
85
85
|
</span>
|
|
86
86
|
</div>
|
|
87
|
-
<h2 className="
|
|
88
|
-
ระบบฟอร์มและการจัดการข้อมูลนำเข้า
|
|
87
|
+
<h2 className="font-bold text-2xl text-foreground tracking-tight">
|
|
88
|
+
ระบบฟอร์มและการจัดการข้อมูลนำเข้า
|
|
89
89
|
</h2>
|
|
90
90
|
<p className="text-sm text-muted-foreground">
|
|
91
91
|
มาตรฐานฟอร์มแบบ Unified <code>FieldGroup</code> + <code>Field</code>{" "}
|
|
@@ -94,14 +94,14 @@ export function ShowcaseForms() {
|
|
|
94
94
|
</div>
|
|
95
95
|
|
|
96
96
|
{/* Interactive Form Controls Showcase */}
|
|
97
|
-
<div className="grid gap-6 xl:grid-cols-[1.1fr_0.9fr]">
|
|
97
|
+
<div id="forms-fields" className="grid gap-6 xl:grid-cols-[1.1fr_0.9fr]">
|
|
98
98
|
{/* Left Column: Standard Field-Based Form */}
|
|
99
99
|
<Card>
|
|
100
100
|
<CardHeader>
|
|
101
101
|
<div className="flex items-center justify-between">
|
|
102
102
|
<div>
|
|
103
|
-
<CardTitle className="text-
|
|
104
|
-
<CardDescription
|
|
103
|
+
<CardTitle className="text-lg">Field-Based Form Structure</CardTitle>
|
|
104
|
+
<CardDescription>
|
|
105
105
|
ใช้ <code>FieldGroup</code> และ <code>Field</code> เพื่อคุม Label, Description และ
|
|
106
106
|
Error
|
|
107
107
|
</CardDescription>
|
|
@@ -223,10 +223,8 @@ export function ShowcaseForms() {
|
|
|
223
223
|
{/* Combobox & MultiSelect */}
|
|
224
224
|
<Card>
|
|
225
225
|
<CardHeader className="pb-3">
|
|
226
|
-
<CardTitle className="text-
|
|
227
|
-
<CardDescription
|
|
228
|
-
การเลือกข้อมูลจากรายการขนาดใหญ่และการแท็กหลายรายการ
|
|
229
|
-
</CardDescription>
|
|
226
|
+
<CardTitle className="text-lg">Combobox & Multi-Select</CardTitle>
|
|
227
|
+
<CardDescription>การเลือกข้อมูลจากรายการขนาดใหญ่และการแท็กหลายรายการ</CardDescription>
|
|
230
228
|
</CardHeader>
|
|
231
229
|
<CardContent className="flex flex-col gap-4">
|
|
232
230
|
<Field>
|
|
@@ -255,8 +253,8 @@ export function ShowcaseForms() {
|
|
|
255
253
|
{/* Grouped FieldSet with Switches & Radios */}
|
|
256
254
|
<Card>
|
|
257
255
|
<CardHeader className="pb-3">
|
|
258
|
-
<CardTitle className="text-
|
|
259
|
-
<CardDescription
|
|
256
|
+
<CardTitle className="text-lg">FieldSet & Grouped Controls</CardTitle>
|
|
257
|
+
<CardDescription>
|
|
260
258
|
ใช้ <code>FieldSet</code> และ <code>FieldLegend</code> รวมสวิตช์และเรดิโอที่เกี่ยวข้องกัน
|
|
261
259
|
</CardDescription>
|
|
262
260
|
</CardHeader>
|
|
@@ -304,10 +302,8 @@ export function ShowcaseForms() {
|
|
|
304
302
|
{/* Specialized Controls (Date, OTP, Slider, ToggleGroup) */}
|
|
305
303
|
<Card>
|
|
306
304
|
<CardHeader className="pb-3">
|
|
307
|
-
<CardTitle className="text-
|
|
308
|
-
<CardDescription
|
|
309
|
-
Date Pickers, OTP, Sliders, และ ToggleGroup
|
|
310
|
-
</CardDescription>
|
|
305
|
+
<CardTitle className="text-lg">Specialized Input Primitives</CardTitle>
|
|
306
|
+
<CardDescription>Date Pickers, OTP, Sliders, และ ToggleGroup</CardDescription>
|
|
311
307
|
</CardHeader>
|
|
312
308
|
<CardContent className="flex flex-col gap-5">
|
|
313
309
|
{/* DatePicker */}
|
|
@@ -180,9 +180,9 @@ export function ShowcaseFoundations() {
|
|
|
180
180
|
<div className="flex flex-col gap-1">
|
|
181
181
|
<div className="flex items-center gap-2">
|
|
182
182
|
<Badge variant="outline">Foundations</Badge>
|
|
183
|
-
<span className="text-
|
|
183
|
+
<span className="text-muted-foreground text-sm">Tokens, Typography & Spatial Layout</span>
|
|
184
184
|
</div>
|
|
185
|
-
<h2 className="
|
|
185
|
+
<h2 className="font-bold text-2xl text-foreground tracking-tight">
|
|
186
186
|
ระบบโทเค็น ฟอนต์ และมิติพื้นฐาน
|
|
187
187
|
</h2>
|
|
188
188
|
<p className="text-sm text-muted-foreground">
|
|
@@ -191,7 +191,7 @@ export function ShowcaseFoundations() {
|
|
|
191
191
|
</div>
|
|
192
192
|
|
|
193
193
|
{/* Semantic Color Tokens */}
|
|
194
|
-
<section className="flex flex-col gap-4">
|
|
194
|
+
<section id="tokens-color" className="flex flex-col gap-4">
|
|
195
195
|
<div className="flex items-center justify-between">
|
|
196
196
|
<div>
|
|
197
197
|
<h3 className="text-base font-semibold flex items-center gap-2">
|
|
@@ -230,14 +230,12 @@ export function ShowcaseFoundations() {
|
|
|
230
230
|
</section>
|
|
231
231
|
|
|
232
232
|
{/* Sidebar & Chart Tokens */}
|
|
233
|
-
<div className="grid gap-6 lg:grid-cols-2">
|
|
233
|
+
<div id="tokens-sidebar-chart" className="grid gap-6 lg:grid-cols-2">
|
|
234
234
|
{/* Sidebar Tokens */}
|
|
235
235
|
<Card>
|
|
236
236
|
<CardHeader className="pb-3">
|
|
237
|
-
<CardTitle className="text-
|
|
238
|
-
<CardDescription
|
|
239
|
-
โทเค็นสำหรับ Navigation Sidebar ทั้งโหมดพับและขยาย
|
|
240
|
-
</CardDescription>
|
|
237
|
+
<CardTitle className="text-lg">Sidebar Palette Tokens</CardTitle>
|
|
238
|
+
<CardDescription>โทเค็นสำหรับ Navigation Sidebar ทั้งโหมดพับและขยาย</CardDescription>
|
|
241
239
|
</CardHeader>
|
|
242
240
|
<CardContent className="grid gap-2 sm:grid-cols-2">
|
|
243
241
|
{sidebarTokens.map((item) => (
|
|
@@ -259,10 +257,8 @@ export function ShowcaseFoundations() {
|
|
|
259
257
|
{/* Chart Tokens */}
|
|
260
258
|
<Card>
|
|
261
259
|
<CardHeader className="pb-3">
|
|
262
|
-
<CardTitle className="text-
|
|
263
|
-
<CardDescription
|
|
264
|
-
ชุดสี 5 ลำดับสำหรับกราฟ Recharts และ Data Visualizations
|
|
265
|
-
</CardDescription>
|
|
260
|
+
<CardTitle className="text-lg">Chart Palette Tokens</CardTitle>
|
|
261
|
+
<CardDescription>ชุดสี 5 ลำดับสำหรับกราฟ Recharts และ Data Visualizations</CardDescription>
|
|
266
262
|
</CardHeader>
|
|
267
263
|
<CardContent className="grid gap-2 grid-cols-5">
|
|
268
264
|
{chartTokens.map((item) => (
|
|
@@ -282,7 +278,7 @@ export function ShowcaseFoundations() {
|
|
|
282
278
|
</div>
|
|
283
279
|
|
|
284
280
|
{/* Typography Scale */}
|
|
285
|
-
<section className="flex flex-col gap-4">
|
|
281
|
+
<section id="tokens-typography" className="flex flex-col gap-4">
|
|
286
282
|
<div className="flex flex-col gap-1">
|
|
287
283
|
<h3 className="text-base font-semibold flex items-center gap-2">
|
|
288
284
|
<Type className="size-4 text-primary" /> Typography Hierarchy (Noto Sans Thai Looped)
|
|
@@ -321,14 +317,14 @@ export function ShowcaseFoundations() {
|
|
|
321
317
|
</section>
|
|
322
318
|
|
|
323
319
|
{/* Spatial, Keyboard & Layout Rules */}
|
|
324
|
-
<section className="grid gap-6 lg:grid-cols-2">
|
|
320
|
+
<section id="tokens-spacing" className="grid gap-6 lg:grid-cols-2">
|
|
325
321
|
{/* Spatial Rules */}
|
|
326
322
|
<Card>
|
|
327
323
|
<CardHeader className="pb-3">
|
|
328
324
|
<CardTitle className="text-base flex items-center gap-2">
|
|
329
325
|
<AlignLeft className="size-4 text-primary" /> Spatial & Spacing Rules
|
|
330
326
|
</CardTitle>
|
|
331
|
-
<CardDescription
|
|
327
|
+
<CardDescription>กฎเกณฑ์การจัดช่องว่างและสัดส่วนเลย์เอาต์</CardDescription>
|
|
332
328
|
</CardHeader>
|
|
333
329
|
<CardContent className="flex flex-col gap-3">
|
|
334
330
|
{spatialRules.map((rule) => (
|
|
@@ -349,9 +345,7 @@ export function ShowcaseFoundations() {
|
|
|
349
345
|
<CardTitle className="text-base flex items-center gap-2">
|
|
350
346
|
<Info className="size-4 text-primary" /> Keyboard Shortcuts (Kbd Primitive)
|
|
351
347
|
</CardTitle>
|
|
352
|
-
<CardDescription
|
|
353
|
-
แสดงปุ่มคีย์ลัดสำหรับผู้ใช้และ Accessibility Navigation
|
|
354
|
-
</CardDescription>
|
|
348
|
+
<CardDescription>แสดงปุ่มคีย์ลัดสำหรับผู้ใช้และ Accessibility Navigation</CardDescription>
|
|
355
349
|
</CardHeader>
|
|
356
350
|
<CardContent className="flex flex-col gap-3">
|
|
357
351
|
<div className="flex items-center justify-between rounded-md border p-3 bg-card">
|
|
@@ -233,12 +233,12 @@ export function ApprovePackageButton({ id }: { id: string }) {
|
|
|
233
233
|
<div className="flex flex-col gap-1">
|
|
234
234
|
<div className="flex items-center gap-2">
|
|
235
235
|
<Badge variant="outline">Rules & Recipes</Badge>
|
|
236
|
-
<span className="text-
|
|
236
|
+
<span className="text-muted-foreground text-sm">
|
|
237
237
|
Web Interface Guidelines, UX Copy Standards & Production Code Recipes
|
|
238
238
|
</span>
|
|
239
239
|
</div>
|
|
240
|
-
<h2 className="
|
|
241
|
-
แนวปฏิบัติและแม่แบบโค้ดมาตรฐาน
|
|
240
|
+
<h2 className="font-bold text-2xl text-foreground tracking-tight">
|
|
241
|
+
แนวปฏิบัติและแม่แบบโค้ดมาตรฐาน
|
|
242
242
|
</h2>
|
|
243
243
|
<p className="text-sm text-muted-foreground">
|
|
244
244
|
สรุปเกณฑ์การตรวจสอบ Accessibility, กฎการเขียน UX Copy สำหรับผู้ใช้,
|
|
@@ -247,7 +247,7 @@ export function ApprovePackageButton({ id }: { id: string }) {
|
|
|
247
247
|
</div>
|
|
248
248
|
|
|
249
249
|
{/* Web Interface Guidelines Checklist */}
|
|
250
|
-
<Card>
|
|
250
|
+
<Card id="rules-a11y">
|
|
251
251
|
<CardHeader>
|
|
252
252
|
<div className="flex items-center justify-between">
|
|
253
253
|
<div>
|
|
@@ -255,9 +255,7 @@ export function ApprovePackageButton({ id }: { id: string }) {
|
|
|
255
255
|
<Accessibility className="size-4 text-primary" /> Web Interface Guidelines
|
|
256
256
|
(Mandatory Baseline)
|
|
257
257
|
</CardTitle>
|
|
258
|
-
<CardDescription
|
|
259
|
-
เกณฑ์มาตรฐานสากลที่ทุกหน้าจอต้องผ่านการตรวจสอบ
|
|
260
|
-
</CardDescription>
|
|
258
|
+
<CardDescription>เกณฑ์มาตรฐานสากลที่ทุกหน้าจอต้องผ่านการตรวจสอบ</CardDescription>
|
|
261
259
|
</div>
|
|
262
260
|
<Badge variant="secondary">A11y Baseline</Badge>
|
|
263
261
|
</div>
|
|
@@ -280,13 +278,13 @@ export function ApprovePackageButton({ id }: { id: string }) {
|
|
|
280
278
|
</Card>
|
|
281
279
|
|
|
282
280
|
{/* UX Writing & Copy Standards */}
|
|
283
|
-
<Card>
|
|
281
|
+
<Card id="rules-ux-writing">
|
|
284
282
|
<CardHeader>
|
|
285
283
|
<CardTitle className="text-base flex items-center gap-2">
|
|
286
284
|
<MessageSquare className="size-4 text-primary" /> Frontend Design: UX Writing & Action
|
|
287
285
|
Voice
|
|
288
286
|
</CardTitle>
|
|
289
|
-
<CardDescription
|
|
287
|
+
<CardDescription>
|
|
290
288
|
การใช้ภาษาที่ชัดเจนและมุ่งเน้นสิ่งที่ผู้ใช้ควบคุมได้ (Active Voice & Cohesion)
|
|
291
289
|
</CardDescription>
|
|
292
290
|
</CardHeader>
|
|
@@ -312,15 +310,13 @@ export function ApprovePackageButton({ id }: { id: string }) {
|
|
|
312
310
|
</Card>
|
|
313
311
|
|
|
314
312
|
{/* Redesign Workflow Checklist */}
|
|
315
|
-
<Card>
|
|
313
|
+
<Card id="rules-redesign">
|
|
316
314
|
<CardHeader>
|
|
317
315
|
<CardTitle className="text-base flex items-center gap-2">
|
|
318
316
|
<RefreshCw className="size-4 text-primary" /> Redesign Safety: Behavior Preservation
|
|
319
317
|
Checklist
|
|
320
318
|
</CardTitle>
|
|
321
|
-
<CardDescription
|
|
322
|
-
เมื่อทำการ Redesign UI ต้องคงความสามารถของระบบเดิม 100%
|
|
323
|
-
</CardDescription>
|
|
319
|
+
<CardDescription>เมื่อทำการ Redesign UI ต้องคงความสามารถของระบบเดิม 100%</CardDescription>
|
|
324
320
|
</CardHeader>
|
|
325
321
|
<CardContent className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4 text-xs">
|
|
326
322
|
<div className="flex flex-col gap-1 rounded-md border p-3 bg-card">
|
|
@@ -351,7 +347,7 @@ export function ApprovePackageButton({ id }: { id: string }) {
|
|
|
351
347
|
</Card>
|
|
352
348
|
|
|
353
349
|
{/* Code Recipes */}
|
|
354
|
-
<section className="flex flex-col gap-4">
|
|
350
|
+
<section id="rules-recipes" className="flex flex-col gap-4">
|
|
355
351
|
<div className="flex items-center justify-between">
|
|
356
352
|
<div>
|
|
357
353
|
<h3 className="text-base font-semibold flex items-center gap-2">
|
|
@@ -122,12 +122,12 @@ export function ShowcaseOverlaysNavigation() {
|
|
|
122
122
|
<div className="flex flex-col gap-1">
|
|
123
123
|
<div className="flex items-center gap-2">
|
|
124
124
|
<Badge variant="outline">Overlays & Navigation</Badge>
|
|
125
|
-
<span className="text-
|
|
125
|
+
<span className="text-muted-foreground text-sm">
|
|
126
126
|
Dialogs, Sheets, Drawers, Menus, Breadcrumbs, Tabs & Resizable Panels
|
|
127
127
|
</span>
|
|
128
128
|
</div>
|
|
129
|
-
<h2 className="
|
|
130
|
-
หน้าต่างซ้อนและการนำทาง
|
|
129
|
+
<h2 className="font-bold text-2xl text-foreground tracking-tight">
|
|
130
|
+
หน้าต่างซ้อนและการนำทาง
|
|
131
131
|
</h2>
|
|
132
132
|
<p className="text-sm text-muted-foreground">
|
|
133
133
|
Modal Dialogs ที่รองรับ Screen Reader อย่างสมบูรณ์, การจัดการ Destructive Confirmation,
|
|
@@ -136,14 +136,14 @@ export function ShowcaseOverlaysNavigation() {
|
|
|
136
136
|
</div>
|
|
137
137
|
|
|
138
138
|
{/* Modal Overlays & Drawers */}
|
|
139
|
-
<div className="grid gap-6 lg:grid-cols-2">
|
|
139
|
+
<div id="overlays-dialog" className="grid gap-6 lg:grid-cols-2">
|
|
140
140
|
{/* Dialog & AlertDialog */}
|
|
141
141
|
<Card>
|
|
142
142
|
<CardHeader>
|
|
143
143
|
<CardTitle className="text-base flex items-center gap-2">
|
|
144
144
|
<ShieldAlert className="size-4 text-primary" /> Dialogs & Consequence Confirmations
|
|
145
145
|
</CardTitle>
|
|
146
|
-
<CardDescription
|
|
146
|
+
<CardDescription>
|
|
147
147
|
ใช้ <code>Dialog</code> สำหรับแบบฟอร์มแก้ไข และใช้ <code>AlertDialog</code>{" "}
|
|
148
148
|
สำหรับการยืนยันการลบ
|
|
149
149
|
</CardDescription>
|
|
@@ -205,7 +205,7 @@ export function ShowcaseOverlaysNavigation() {
|
|
|
205
205
|
<CardTitle className="text-base flex items-center gap-2">
|
|
206
206
|
<Layers className="size-4 text-primary" /> Side Sheets & Bottom Drawers
|
|
207
207
|
</CardTitle>
|
|
208
|
-
<CardDescription
|
|
208
|
+
<CardDescription>
|
|
209
209
|
ใช้ <code>Sheet</code> สำหรับแผงฟิลเตอร์ด้านข้าง และ <code>Drawer</code> สำหรับมุมมองมือถือ
|
|
210
210
|
</CardDescription>
|
|
211
211
|
</CardHeader>
|
|
@@ -270,12 +270,12 @@ export function ShowcaseOverlaysNavigation() {
|
|
|
270
270
|
</div>
|
|
271
271
|
|
|
272
272
|
{/* Popovers, Tooltips & Context Menus */}
|
|
273
|
-
<div className="grid gap-6 lg:grid-cols-2">
|
|
273
|
+
<div id="overlays-popover" className="grid gap-6 lg:grid-cols-2">
|
|
274
274
|
{/* Popover & Tooltip */}
|
|
275
275
|
<Card>
|
|
276
276
|
<CardHeader className="pb-3">
|
|
277
|
-
<CardTitle className="text-
|
|
278
|
-
<CardDescription
|
|
277
|
+
<CardTitle className="text-lg">Tooltips, HoverCard & Popovers</CardTitle>
|
|
278
|
+
<CardDescription>คำอธิบายเพิ่มเติมและเนื้อหาแบบบริบท</CardDescription>
|
|
279
279
|
</CardHeader>
|
|
280
280
|
<CardContent className="flex flex-wrap items-center gap-4">
|
|
281
281
|
{/* Tooltip */}
|
|
@@ -334,10 +334,8 @@ export function ShowcaseOverlaysNavigation() {
|
|
|
334
334
|
{/* Menubar & ContextMenu */}
|
|
335
335
|
<Card>
|
|
336
336
|
<CardHeader className="pb-3">
|
|
337
|
-
<CardTitle className="text-
|
|
338
|
-
<CardDescription
|
|
339
|
-
เมนูบาร์สำหรับระบบบริหารจัดการ และคลิกขวาในพื้นที่ตาราง
|
|
340
|
-
</CardDescription>
|
|
337
|
+
<CardTitle className="text-lg">Menubar & Context Menu</CardTitle>
|
|
338
|
+
<CardDescription>เมนูบาร์สำหรับระบบบริหารจัดการ และคลิกขวาในพื้นที่ตาราง</CardDescription>
|
|
341
339
|
</CardHeader>
|
|
342
340
|
<CardContent className="flex flex-col gap-4">
|
|
343
341
|
{/* Menubar */}
|
|
@@ -389,14 +387,12 @@ export function ShowcaseOverlaysNavigation() {
|
|
|
389
387
|
</div>
|
|
390
388
|
|
|
391
389
|
{/* Navigation & Resizable Layout */}
|
|
392
|
-
<div className="grid gap-6 lg:grid-cols-2">
|
|
390
|
+
<div id="overlays-navigation" className="grid gap-6 lg:grid-cols-2">
|
|
393
391
|
{/* Breadcrumb & Pagination */}
|
|
394
392
|
<Card>
|
|
395
393
|
<CardHeader className="pb-3">
|
|
396
|
-
<CardTitle className="text-
|
|
397
|
-
<CardDescription
|
|
398
|
-
ลำดับชั้นของหน้าและตัวแบ่งหน้าสำหรับตารางข้อมูล
|
|
399
|
-
</CardDescription>
|
|
394
|
+
<CardTitle className="text-lg">Breadcrumbs & Pagination</CardTitle>
|
|
395
|
+
<CardDescription>ลำดับชั้นของหน้าและตัวแบ่งหน้าสำหรับตารางข้อมูล</CardDescription>
|
|
400
396
|
</CardHeader>
|
|
401
397
|
<CardContent className="flex flex-col gap-6">
|
|
402
398
|
{/* Breadcrumb */}
|
|
@@ -449,8 +445,8 @@ export function ShowcaseOverlaysNavigation() {
|
|
|
449
445
|
{/* Resizable Panels */}
|
|
450
446
|
<Card>
|
|
451
447
|
<CardHeader className="pb-3">
|
|
452
|
-
<CardTitle className="text-
|
|
453
|
-
<CardDescription
|
|
448
|
+
<CardTitle className="text-lg">Resizable Layout Panels</CardTitle>
|
|
449
|
+
<CardDescription>
|
|
454
450
|
แบ่งพื้นที่หน้าจอระหว่างตารางรายการและรายละเอียดแบบลากปรับขนาดได้
|
|
455
451
|
</CardDescription>
|
|
456
452
|
</CardHeader>
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
InputGroupInput,
|
|
17
17
|
} from "@suphark/ui/components/ui/input-group";
|
|
18
18
|
import { Kbd } from "@suphark/ui/components/ui/kbd";
|
|
19
|
+
import { cn } from "@suphark/ui/lib/utils";
|
|
19
20
|
import {
|
|
20
21
|
Accessibility,
|
|
21
22
|
ArrowRight,
|
|
@@ -30,15 +31,21 @@ import {
|
|
|
30
31
|
Sparkles,
|
|
31
32
|
Zap,
|
|
32
33
|
} from "lucide-react";
|
|
34
|
+
import { searchIndex } from "../search-index";
|
|
35
|
+
import { HeroSpecimen } from "./hero-specimen";
|
|
33
36
|
|
|
34
37
|
interface ShowcaseOverviewProps {
|
|
35
38
|
onSelectTab: (tab: string) => void;
|
|
39
|
+
links?: { shell?: string };
|
|
40
|
+
onJump: (tab: string, anchor?: string) => void;
|
|
36
41
|
searchQuery: string;
|
|
37
42
|
onSearchChange: (query: string) => void;
|
|
38
43
|
}
|
|
39
44
|
|
|
40
45
|
export function ShowcaseOverview({
|
|
41
46
|
onSelectTab,
|
|
47
|
+
links,
|
|
48
|
+
onJump,
|
|
42
49
|
searchQuery,
|
|
43
50
|
onSearchChange,
|
|
44
51
|
}: ShowcaseOverviewProps) {
|
|
@@ -115,47 +122,44 @@ export function ShowcaseOverview({
|
|
|
115
122
|
{ name: "Field-based Forms & InputGroup", tab: "forms", icon: Layers },
|
|
116
123
|
{ name: "Data Tables & States", tab: "data-display", icon: Boxes },
|
|
117
124
|
{ name: "Overlays (Dialog, Sheet, Drawer)", tab: "overlays", icon: Compass },
|
|
118
|
-
{ name: "
|
|
125
|
+
{ name: "Rules & Code Recipes", tab: "guidelines-recipes", icon: FileCode2 },
|
|
119
126
|
];
|
|
120
127
|
|
|
121
128
|
return (
|
|
122
129
|
<div className="flex flex-col gap-8">
|
|
123
|
-
{/* Hero
|
|
124
|
-
<section className="
|
|
125
|
-
<div className="flex flex-col gap-
|
|
126
|
-
<
|
|
127
|
-
|
|
128
|
-
<Sparkles className="size-3" /> @suphark/ui Design System
|
|
129
|
-
</Badge>
|
|
130
|
-
<Badge variant="secondary">Next.js App Router</Badge>
|
|
131
|
-
<Badge variant="outline">Tailwind v4</Badge>
|
|
132
|
-
<Badge variant="outline">shadcn/ui</Badge>
|
|
133
|
-
<Badge variant="outline">Web Interface Guidelines</Badge>
|
|
134
|
-
</div>
|
|
135
|
-
|
|
136
|
-
<h2 className="text-2xl md:text-3xl font-bold tracking-tight text-foreground">
|
|
137
|
-
ภาพรวมระบบการออกแบบและมาตรฐาน UI ของทุกแอป
|
|
130
|
+
{/* Hero — ไม่มีกรอบ: หน้าเต็มไปด้วยการ์ดอยู่แล้ว; specimen กว้างเต็มแถวใต้ข้อความ */}
|
|
131
|
+
<section className="flex flex-col gap-5 py-2 md:py-6">
|
|
132
|
+
<div className="flex max-w-3xl flex-col gap-5">
|
|
133
|
+
<h2 className="font-bold text-3xl text-foreground tracking-tight md:text-4xl">
|
|
134
|
+
UI ชุดเดียวสำหรับทุกแอปของ Suphark
|
|
138
135
|
</h2>
|
|
139
136
|
|
|
140
|
-
<p className="text-
|
|
137
|
+
<p className="text-base text-muted-foreground leading-relaxed md:text-lg">
|
|
141
138
|
ศูนย์กลางมาตรฐานการออกแบบและการประกอบคอมโพเนนต์สำหรับทุกแอปของ Suphark (Pi Auth, DueBell, Pi
|
|
142
139
|
PDF, supplychain) เน้นความกระชับ สแกนง่าย รองรับงานประจำวันที่มีข้อมูลหนาแน่น (Operational Density)
|
|
143
140
|
ผสาน 4 เสาหลัก: <strong>Web Interface Guidelines</strong>,{" "}
|
|
144
141
|
<strong>shadcn/ui Primitives</strong>,<strong>Frontend Design & UX Copy</strong>, และ{" "}
|
|
145
142
|
<strong>Redesign Safety Workflow</strong>
|
|
146
143
|
</p>
|
|
144
|
+
</div>
|
|
145
|
+
|
|
146
|
+
<HeroSpecimen />
|
|
147
147
|
|
|
148
|
-
|
|
148
|
+
<div>
|
|
149
|
+
<div className="flex flex-wrap items-center gap-3">
|
|
149
150
|
<Button onClick={() => onSelectTab("primitives")} className="gap-2">
|
|
150
151
|
<Boxes className="size-4" /> สำรวจคอมโพเนนต์ทั้งหมด
|
|
151
152
|
</Button>
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
153
|
+
{links?.shell && (
|
|
154
|
+
<Button
|
|
155
|
+
variant="outline"
|
|
156
|
+
className="gap-2"
|
|
157
|
+
nativeButton={false}
|
|
158
|
+
render={<a href={links.shell} />}
|
|
159
|
+
>
|
|
160
|
+
<Compass className="size-4" /> ตัวอย่างหน้าจอ (AppShell)
|
|
161
|
+
</Button>
|
|
162
|
+
)}
|
|
159
163
|
<Button
|
|
160
164
|
variant="ghost"
|
|
161
165
|
onClick={() => onSelectTab("guidelines-recipes")}
|
|
@@ -190,8 +194,15 @@ export function ShowcaseOverview({
|
|
|
190
194
|
</div>
|
|
191
195
|
</div>
|
|
192
196
|
|
|
197
|
+
{/* ผลลัพธ์ค้นหา (เมื่อพิมพ์) แทนชิป Jump to */}
|
|
198
|
+
{searchQuery.trim() ? (
|
|
199
|
+
<SearchResults query={searchQuery} onJump={onJump} onClear={() => onSearchChange("")} />
|
|
200
|
+
) : null}
|
|
201
|
+
|
|
193
202
|
{/* Quick jump tags */}
|
|
194
|
-
<div
|
|
203
|
+
<div
|
|
204
|
+
className={cn("flex flex-wrap items-center gap-2 pt-1", searchQuery.trim() && "hidden")}
|
|
205
|
+
>
|
|
195
206
|
<span className="text-xs text-muted-foreground flex items-center gap-1">
|
|
196
207
|
<Kbd>Jump to</Kbd>
|
|
197
208
|
</span>
|
|
@@ -238,7 +249,7 @@ export function ShowcaseOverview({
|
|
|
238
249
|
</Badge>
|
|
239
250
|
</div>
|
|
240
251
|
<CardTitle className="text-base font-semibold pt-2">{pillar.title}</CardTitle>
|
|
241
|
-
<CardDescription
|
|
252
|
+
<CardDescription>{pillar.subtitle}</CardDescription>
|
|
242
253
|
</CardHeader>
|
|
243
254
|
|
|
244
255
|
<CardContent className="flex flex-col gap-3 pb-3">
|
|
@@ -366,3 +377,60 @@ export function ShowcaseOverview({
|
|
|
366
377
|
</div>
|
|
367
378
|
);
|
|
368
379
|
}
|
|
380
|
+
|
|
381
|
+
/** ผลการค้นหาจากดัชนี — กดแล้วสลับแท็บและเลื่อนไปหัวข้อ; ไม่พบ = บอกและชวนดูแท็บ */
|
|
382
|
+
function SearchResults({
|
|
383
|
+
query,
|
|
384
|
+
onJump,
|
|
385
|
+
onClear,
|
|
386
|
+
}: {
|
|
387
|
+
query: string;
|
|
388
|
+
onJump: (tab: string, anchor?: string) => void;
|
|
389
|
+
onClear: () => void;
|
|
390
|
+
}) {
|
|
391
|
+
const results = searchIndex(query);
|
|
392
|
+
if (results.length === 0) {
|
|
393
|
+
return (
|
|
394
|
+
<div className="flex flex-wrap items-center gap-2 rounded-lg border border-dashed px-3 py-2 text-muted-foreground text-sm">
|
|
395
|
+
<span>ไม่พบ "{query}" ในคู่มือ — ลองคำอื่น หรือดูแท็บ</span>
|
|
396
|
+
<button
|
|
397
|
+
type="button"
|
|
398
|
+
onClick={() => onJump("primitives")}
|
|
399
|
+
className="font-medium text-foreground underline underline-offset-4"
|
|
400
|
+
>
|
|
401
|
+
Primitives
|
|
402
|
+
</button>
|
|
403
|
+
<span>/</span>
|
|
404
|
+
<button
|
|
405
|
+
type="button"
|
|
406
|
+
onClick={() => onJump("forms")}
|
|
407
|
+
className="font-medium text-foreground underline underline-offset-4"
|
|
408
|
+
>
|
|
409
|
+
Forms
|
|
410
|
+
</button>
|
|
411
|
+
<button type="button" onClick={onClear} className="ml-auto underline underline-offset-4">
|
|
412
|
+
ล้างคำค้น
|
|
413
|
+
</button>
|
|
414
|
+
</div>
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
return (
|
|
418
|
+
<ul className="flex flex-col divide-y rounded-lg border bg-card" aria-label="ผลการค้นหา">
|
|
419
|
+
{results.map((r) => (
|
|
420
|
+
<li key={`${r.tab}-${r.anchor ?? r.title}`}>
|
|
421
|
+
<button
|
|
422
|
+
type="button"
|
|
423
|
+
onClick={() => onJump(r.tab, r.anchor)}
|
|
424
|
+
className="flex w-full items-center gap-3 px-3 py-2 text-left text-sm transition-colors hover:bg-accent hover:text-accent-foreground"
|
|
425
|
+
>
|
|
426
|
+
<span className="flex-1">{r.title}</span>
|
|
427
|
+
<span className="rounded-md bg-muted px-1.5 py-0.5 text-muted-foreground text-xs">
|
|
428
|
+
{r.tab}
|
|
429
|
+
</span>
|
|
430
|
+
<ArrowRight className="size-4 text-muted-foreground" />
|
|
431
|
+
</button>
|
|
432
|
+
</li>
|
|
433
|
+
))}
|
|
434
|
+
</ul>
|
|
435
|
+
);
|
|
436
|
+
}
|