@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.
@@ -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-xs text-muted-foreground">
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="text-xl font-bold tracking-tight text-foreground">
63
- ระบบการแจ้งเตือนและการตอบสนองต่อผู้ใช้ (Feedback System)
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-base">Feedback Channel Decision Matrix</CardTitle>
75
- <CardDescription className="text-xs">
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 className="text-xs">ทดสอบยิง Toast ในสถานการณ์ต่าง ๆ</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-base">3. Active Task Progress</CardTitle>
223
- <CardDescription className="text-xs">
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-base">4. FieldError & Direct Validation</CardTitle>
256
- <CardDescription className="text-xs">
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-xs text-muted-foreground">
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="text-xl font-bold tracking-tight text-foreground">
88
- ระบบฟอร์มและการจัดการข้อมูลนำเข้า (Forms & Inputs)
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-base">Field-Based Form Structure</CardTitle>
104
- <CardDescription className="text-xs">
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-base">Combobox & Multi-Select</CardTitle>
227
- <CardDescription className="text-xs">
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-base">FieldSet & Grouped Controls</CardTitle>
259
- <CardDescription className="text-xs">
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-base">Specialized Input Primitives</CardTitle>
308
- <CardDescription className="text-xs">
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-xs text-muted-foreground">Tokens, Typography & Spatial Layout</span>
183
+ <span className="text-muted-foreground text-sm">Tokens, Typography & Spatial Layout</span>
184
184
  </div>
185
- <h2 className="text-xl font-bold tracking-tight text-foreground">
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-base">Sidebar Palette Tokens</CardTitle>
238
- <CardDescription className="text-xs">
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-base">Chart Palette Tokens</CardTitle>
263
- <CardDescription className="text-xs">
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 className="text-xs">กฎเกณฑ์การจัดช่องว่างและสัดส่วนเลย์เอาต์</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 className="text-xs">
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-xs text-muted-foreground">
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="text-xl font-bold tracking-tight text-foreground">
241
- แนวปฏิบัติและแม่แบบโค้ดมาตรฐาน (Guidelines & Code Recipes)
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 className="text-xs">
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 className="text-xs">
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 className="text-xs">
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-xs text-muted-foreground">
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="text-xl font-bold tracking-tight text-foreground">
130
- หน้าต่างซ้อนและการนำทาง (Overlays & Navigation)
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 className="text-xs">
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 className="text-xs">
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-base">Tooltips, HoverCard & Popovers</CardTitle>
278
- <CardDescription className="text-xs">คำอธิบายเพิ่มเติมและเนื้อหาแบบบริบท</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-base">Menubar & Context Menu</CardTitle>
338
- <CardDescription className="text-xs">
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-base">Breadcrumbs & Pagination</CardTitle>
397
- <CardDescription className="text-xs">
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-base">Resizable Layout Panels</CardTitle>
453
- <CardDescription className="text-xs">
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: "Domain Patterns & Code Recipes", tab: "domain-patterns", icon: FileCode2 },
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 Banner */}
124
- <section className="relative overflow-hidden rounded-2xl border bg-gradient-to-br from-card via-card to-muted/40 p-6 md:p-8 shadow-xs">
125
- <div className="flex flex-col gap-4 max-w-4xl">
126
- <div className="flex flex-wrap items-center gap-2">
127
- <Badge variant="default" className="gap-1">
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-sm md:text-base text-muted-foreground leading-relaxed">
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
- <div className="flex flex-wrap items-center gap-3 pt-2">
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
- <Button
153
- variant="outline"
154
- onClick={() => onSelectTab("domain-patterns")}
155
- className="gap-2"
156
- >
157
- <Compass className="size-4" /> ตัวอย่างหน้าจอ
158
- </Button>
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 className="flex flex-wrap items-center gap-2 pt-1">
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 className="text-xs">{pillar.subtitle}</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
+ }