@suphark/ui 0.1.0
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 +36 -0
- package/LICENSE +21 -0
- package/README.md +120 -0
- package/components.json +21 -0
- package/package.json +108 -0
- package/scripts/audit-base-ui-props.mjs +179 -0
- package/scripts/audit-tailwind-typography.mjs +100 -0
- package/src/components/design-system/design-system-showcase.tsx +138 -0
- package/src/components/design-system/sections/showcase-data-display.tsx +454 -0
- package/src/components/design-system/sections/showcase-feedback.tsx +273 -0
- package/src/components/design-system/sections/showcase-forms.tsx +373 -0
- package/src/components/design-system/sections/showcase-foundations.tsx +384 -0
- package/src/components/design-system/sections/showcase-guidelines-recipes.tsx +397 -0
- package/src/components/design-system/sections/showcase-overlays-navigation.tsx +479 -0
- package/src/components/design-system/sections/showcase-overview.tsx +368 -0
- package/src/components/design-system/sections/showcase-primitives.tsx +463 -0
- package/src/components/shared/__tests__/multi-select-combobox.test.tsx +180 -0
- package/src/components/shared/__tests__/name-id-fields.test.ts +24 -0
- package/src/components/shared/button/add-new-button.tsx +19 -0
- package/src/components/shared/button/base/action-button.tsx +134 -0
- package/src/components/shared/button/base/link-button.tsx +130 -0
- package/src/components/shared/button/cancel-button.tsx +27 -0
- package/src/components/shared/button/confirm-button.tsx +26 -0
- package/src/components/shared/button/delete-button.tsx +36 -0
- package/src/components/shared/button/floating-save-button.tsx +89 -0
- package/src/components/shared/button/index.ts +13 -0
- package/src/components/shared/button/print-button.tsx +67 -0
- package/src/components/shared/button/refresh-button.tsx +63 -0
- package/src/components/shared/button/save-button.tsx +29 -0
- package/src/components/shared/button/submit-button.tsx +58 -0
- package/src/components/shared/client-redirect.tsx +11 -0
- package/src/components/shared/combobox.tsx +116 -0
- package/src/components/shared/data-list.tsx +65 -0
- package/src/components/shared/date/date-range-picker.tsx +106 -0
- package/src/components/shared/description-list.tsx +27 -0
- package/src/components/shared/empty-row.tsx +13 -0
- package/src/components/shared/empty-state.tsx +31 -0
- package/src/components/shared/env-snippet.tsx +62 -0
- package/src/components/shared/form/__tests__/simple-select.test.tsx +72 -0
- package/src/components/shared/form/form-field-boolean.tsx +93 -0
- package/src/components/shared/form/form-field-color-select.tsx +86 -0
- package/src/components/shared/form/form-field-combobox.tsx +167 -0
- package/src/components/shared/form/form-field-date.tsx +55 -0
- package/src/components/shared/form/form-field-formatted-number.tsx +103 -0
- package/src/components/shared/form/form-field-input.tsx +372 -0
- package/src/components/shared/form/form-field-radio-cards.tsx +127 -0
- package/src/components/shared/form/form-field-radio-group.tsx +56 -0
- package/src/components/shared/form/form-field-select.tsx +312 -0
- package/src/components/shared/form/simple-select.tsx +152 -0
- package/src/components/shared/form-dialog.tsx +109 -0
- package/src/components/shared/form-message.tsx +30 -0
- package/src/components/shared/initials.tsx +33 -0
- package/src/components/shared/layout/error-state.tsx +160 -0
- package/src/components/shared/layout/page-shell.tsx +57 -0
- package/src/components/shared/link/transition-link.tsx +72 -0
- package/src/components/shared/multi-select-combobox.tsx +392 -0
- package/src/components/shared/name-id-fields.tsx +133 -0
- package/src/components/shared/navigation/page-breadcrumb.tsx +100 -0
- package/src/components/shared/notice.tsx +35 -0
- package/src/components/shared/number/formatted-number.tsx +133 -0
- package/src/components/shared/page-header.tsx +25 -0
- package/src/components/shared/page-skeleton.tsx +18 -0
- package/src/components/shared/row-actions.tsx +93 -0
- package/src/components/shared/row-menu.tsx +55 -0
- package/src/components/shared/secret-reveal.tsx +53 -0
- package/src/components/shared/section-card.tsx +44 -0
- package/src/components/shared/stat.tsx +26 -0
- package/src/components/shared/status-badge.tsx +47 -0
- package/src/components/shared/text/primary-secondary-text.tsx +186 -0
- package/src/components/shared/theme/index.ts +4 -0
- package/src/components/shared/theme/theme-menu-items.tsx +43 -0
- package/src/components/shared/theme/theme-provider.tsx +39 -0
- package/src/components/shared/theme/theme-switch.tsx +36 -0
- package/src/components/shared/theme/theme-toggle.tsx +76 -0
- package/src/components/shared/time/client-date-formatter.tsx +188 -0
- package/src/components/shared/ui-text.tsx +47 -0
- package/src/components/ui/__tests__/combobox.test.tsx +40 -0
- package/src/components/ui/__tests__/date-picker.test.tsx +53 -0
- package/src/components/ui/__tests__/slider.test.tsx +18 -0
- package/src/components/ui/__tests__/tabs.test.tsx +33 -0
- package/src/components/ui/accordion.tsx +69 -0
- package/src/components/ui/alert-dialog.tsx +161 -0
- package/src/components/ui/alert.tsx +68 -0
- package/src/components/ui/aspect-ratio.tsx +22 -0
- package/src/components/ui/attachment.tsx +194 -0
- package/src/components/ui/avatar.tsx +92 -0
- package/src/components/ui/badge.tsx +48 -0
- package/src/components/ui/breadcrumb.tsx +102 -0
- package/src/components/ui/button-group.tsx +77 -0
- package/src/components/ui/button.tsx +57 -0
- package/src/components/ui/calendar.tsx +184 -0
- package/src/components/ui/card.tsx +87 -0
- package/src/components/ui/carousel.tsx +230 -0
- package/src/components/ui/chart.tsx +338 -0
- package/src/components/ui/checkbox.tsx +27 -0
- package/src/components/ui/collapsible.tsx +17 -0
- package/src/components/ui/combobox.tsx +272 -0
- package/src/components/ui/command.tsx +180 -0
- package/src/components/ui/context-menu.tsx +244 -0
- package/src/components/ui/date-picker.tsx +308 -0
- package/src/components/ui/dialog.tsx +137 -0
- package/src/components/ui/drawer.tsx +208 -0
- package/src/components/ui/dropdown-menu.tsx +257 -0
- package/src/components/ui/empty.tsx +93 -0
- package/src/components/ui/field.tsx +223 -0
- package/src/components/ui/form.tsx +161 -0
- package/src/components/ui/hover-card.tsx +46 -0
- package/src/components/ui/input-group.tsx +145 -0
- package/src/components/ui/input-otp.tsx +85 -0
- package/src/components/ui/input.tsx +19 -0
- package/src/components/ui/item.tsx +187 -0
- package/src/components/ui/kbd.tsx +26 -0
- package/src/components/ui/label.tsx +19 -0
- package/src/components/ui/menubar.tsx +266 -0
- package/src/components/ui/navigation-menu.tsx +160 -0
- package/src/components/ui/pagination.tsx +117 -0
- package/src/components/ui/popover.tsx +76 -0
- package/src/components/ui/progress.tsx +66 -0
- package/src/components/ui/radio-group.tsx +38 -0
- package/src/components/ui/relative-date.tsx +40 -0
- package/src/components/ui/resizable.tsx +41 -0
- package/src/components/ui/scroll-area.tsx +67 -0
- package/src/components/ui/searchable-select.tsx +124 -0
- package/src/components/ui/select.tsx +189 -0
- package/src/components/ui/separator.tsx +21 -0
- package/src/components/ui/sheet.tsx +124 -0
- package/src/components/ui/sidebar.tsx +691 -0
- package/src/components/ui/skeleton.tsx +13 -0
- package/src/components/ui/slider.tsx +55 -0
- package/src/components/ui/sonner.tsx +45 -0
- package/src/components/ui/spinner.tsx +16 -0
- package/src/components/ui/switch.tsx +32 -0
- package/src/components/ui/table.tsx +95 -0
- package/src/components/ui/tabs.tsx +79 -0
- package/src/components/ui/textarea.tsx +17 -0
- package/src/components/ui/toggle-group.tsx +86 -0
- package/src/components/ui/toggle.tsx +44 -0
- package/src/components/ui/tooltip.tsx +54 -0
- package/src/hooks/use-copy-to-clipboard.ts +27 -0
- package/src/hooks/use-mobile.ts +21 -0
- package/src/index.ts +156 -0
- package/src/lib/formatters.ts +44 -0
- package/src/lib/permission.ts +75 -0
- package/src/lib/status-colors.ts +52 -0
- package/src/lib/utils.ts +6 -0
- package/src/next.ts +15 -0
- package/src/styles.css +214 -0
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Badge } from "@suphark/ui/components/ui/badge";
|
|
4
|
+
import {
|
|
5
|
+
Card,
|
|
6
|
+
CardContent,
|
|
7
|
+
CardDescription,
|
|
8
|
+
CardHeader,
|
|
9
|
+
CardTitle,
|
|
10
|
+
} from "@suphark/ui/components/ui/card";
|
|
11
|
+
import { Kbd, KbdGroup } from "@suphark/ui/components/ui/kbd";
|
|
12
|
+
import { AlignLeft, Check, Copy, Info, Palette, Type } from "lucide-react";
|
|
13
|
+
import * as React from "react";
|
|
14
|
+
|
|
15
|
+
export function ShowcaseFoundations() {
|
|
16
|
+
const [copiedToken, setCopiedToken] = React.useState<string | null>(null);
|
|
17
|
+
|
|
18
|
+
const copyToClipboard = (text: string) => {
|
|
19
|
+
navigator.clipboard.writeText(text);
|
|
20
|
+
setCopiedToken(text);
|
|
21
|
+
setTimeout(() => setCopiedToken(null), 2000);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const coreTokens = [
|
|
25
|
+
{
|
|
26
|
+
name: "Background",
|
|
27
|
+
class: "bg-background text-foreground border",
|
|
28
|
+
token: "var(--background)",
|
|
29
|
+
tailwind: "bg-background / text-foreground",
|
|
30
|
+
usage: "Canvas หลักของหน้าเว็บ และสีข้อความตั้งต้น",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: "Card",
|
|
34
|
+
class: "bg-card text-card-foreground border",
|
|
35
|
+
token: "var(--card)",
|
|
36
|
+
tailwind: "bg-card / text-card-foreground",
|
|
37
|
+
usage: "พื้นผิวของ Panels, Table Containers, และ Modal Surfaces",
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: "Primary",
|
|
41
|
+
class: "bg-primary text-primary-foreground",
|
|
42
|
+
token: "var(--primary)",
|
|
43
|
+
tailwind: "bg-primary / text-primary-foreground",
|
|
44
|
+
usage: "Primary actions, ปุ่มเน้นหลัก, Active Tab, และ Brand Accent",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "Secondary",
|
|
48
|
+
class: "bg-secondary text-secondary-foreground border",
|
|
49
|
+
token: "var(--secondary)",
|
|
50
|
+
tailwind: "bg-secondary / text-secondary-foreground",
|
|
51
|
+
usage: "Supporting actions, Secondary badges, และ Subtle highlight",
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: "Muted",
|
|
55
|
+
class: "bg-muted text-muted-foreground border",
|
|
56
|
+
token: "var(--muted)",
|
|
57
|
+
tailwind: "bg-muted / text-muted-foreground",
|
|
58
|
+
usage: "Skeleton placeholders, Subdued sections, Helper text",
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: "Destructive",
|
|
62
|
+
class: "bg-destructive text-white",
|
|
63
|
+
token: "var(--destructive)",
|
|
64
|
+
tailwind: "bg-destructive / text-destructive",
|
|
65
|
+
usage: "Irreversible actions, Delete confirmation, Error callouts",
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: "Success",
|
|
69
|
+
class: "bg-success text-success-foreground",
|
|
70
|
+
token: "var(--success)",
|
|
71
|
+
tailwind: "bg-success / text-success-foreground",
|
|
72
|
+
usage: "Approved status, Success badges, Positive rate variance",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: "Border / Input / Ring",
|
|
76
|
+
class: "bg-card text-foreground border-2 border-ring",
|
|
77
|
+
token: "var(--border) / var(--ring)",
|
|
78
|
+
tailwind: "border-border / border-input / ring-ring",
|
|
79
|
+
usage: "เส้นขอบ component, input outline, และ accessible focus rings",
|
|
80
|
+
},
|
|
81
|
+
];
|
|
82
|
+
|
|
83
|
+
const sidebarTokens = [
|
|
84
|
+
{
|
|
85
|
+
name: "Sidebar Background",
|
|
86
|
+
class: "bg-sidebar text-sidebar-foreground border",
|
|
87
|
+
token: "var(--sidebar)",
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
name: "Sidebar Primary",
|
|
91
|
+
class: "bg-sidebar-primary text-sidebar-primary-foreground",
|
|
92
|
+
token: "var(--sidebar-primary)",
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: "Sidebar Accent",
|
|
96
|
+
class: "bg-sidebar-accent text-sidebar-accent-foreground border",
|
|
97
|
+
token: "var(--sidebar-accent)",
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: "Sidebar Border",
|
|
101
|
+
class: "bg-sidebar-border h-4 w-full rounded",
|
|
102
|
+
token: "var(--sidebar-border)",
|
|
103
|
+
},
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
const chartTokens = [
|
|
107
|
+
{ name: "Chart 1 (Orange/Amber)", class: "bg-chart-1 text-white", token: "var(--chart-1)" },
|
|
108
|
+
{ name: "Chart 2 (Teal/Cyan)", class: "bg-chart-2 text-white", token: "var(--chart-2)" },
|
|
109
|
+
{ name: "Chart 3 (Slate/Blue)", class: "bg-chart-3 text-white", token: "var(--chart-3)" },
|
|
110
|
+
{ name: "Chart 4 (Yellow/Gold)", class: "bg-chart-4 text-black", token: "var(--chart-4)" },
|
|
111
|
+
{ name: "Chart 5 (Red/Rose)", class: "bg-chart-5 text-white", token: "var(--chart-5)" },
|
|
112
|
+
];
|
|
113
|
+
|
|
114
|
+
const typeScale = [
|
|
115
|
+
{
|
|
116
|
+
role: "Page Title",
|
|
117
|
+
className: "text-2xl font-bold tracking-tight",
|
|
118
|
+
sample: "Bidding Package Review & Award",
|
|
119
|
+
usage: "ชื่อหน้าหลักของแต่ละ Module ใน PageShell",
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
role: "Section Title",
|
|
123
|
+
className: "text-lg font-semibold tracking-normal",
|
|
124
|
+
sample: "Vendor Qualification & Price Breakdown",
|
|
125
|
+
usage: "หัวข้อหลักของ Card, Dialog, Sheet, หรือ Tabs panel",
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
role: "Subsection Title",
|
|
129
|
+
className: "text-base font-semibold",
|
|
130
|
+
sample: "Material Specification & BOQ Rates",
|
|
131
|
+
usage: "หัวข้อย่อยใน Form sections หรือ Card sub-blocks",
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
role: "Base Body",
|
|
135
|
+
className: "text-sm leading-normal",
|
|
136
|
+
sample: "All bids submitted before the deadline are subject to procurement committee review.",
|
|
137
|
+
usage: "เนื้อหาหลัก, Table row data, Description, Input labels",
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
role: "Caption / Metadata",
|
|
141
|
+
className: "text-xs text-muted-foreground",
|
|
142
|
+
sample: "Last modified by procurement.manager@company.com • 15 mins ago",
|
|
143
|
+
usage: "Helper text, timestamp, audit metadata, table header captions",
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
role: "Monospace / Numbers",
|
|
147
|
+
className: "font-mono text-xs text-foreground",
|
|
148
|
+
sample: "PO-2026-08-9941 / THB 14,850,200.00 / SHA-256",
|
|
149
|
+
usage: "Code identifiers, Document numbers, Financial decimals, Hashes",
|
|
150
|
+
},
|
|
151
|
+
];
|
|
152
|
+
|
|
153
|
+
const spatialRules = [
|
|
154
|
+
{
|
|
155
|
+
title: "Flex Spacing over space-x/y",
|
|
156
|
+
rule: "ใช้ flex flex-col gap-4 หรือ grid gap-4",
|
|
157
|
+
reason:
|
|
158
|
+
"Tailwind v4 และ modern layout รองรับ gap ได้ดีกว่า และไม่เจอปัญหามาร์จิ้นเพี้ยนเมื่อมี conditional children",
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
title: "Square Proportions (size-*)",
|
|
162
|
+
rule: "ใช้ size-8, size-10 แทน w-8 h-8",
|
|
163
|
+
reason: "กระชับ ชัดเจน และลดความผิดพลาดเรื่องอัตราส่วน 1:1 ของ Avatar, Icon Button และ Media boxes",
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
title: "Text Truncation & Flex Shrink",
|
|
167
|
+
rule: "ใช้ min-w-0 truncate บน flex child",
|
|
168
|
+
reason: "ป้องกันข้อความยาวล้นหน้าจอ (Text Overflow) ใน Table cell และ Toolbar",
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
title: "No Arbitrary Text Sizes",
|
|
172
|
+
rule: "ใช้ text-xs / text-sm / text-base แทน text-xs",
|
|
173
|
+
reason: "รักษา Vertical Rhythm และความสม่ำเสมอของสายตาทั้งระบบ",
|
|
174
|
+
},
|
|
175
|
+
];
|
|
176
|
+
|
|
177
|
+
return (
|
|
178
|
+
<div className="flex flex-col gap-8">
|
|
179
|
+
{/* Section Header */}
|
|
180
|
+
<div className="flex flex-col gap-1">
|
|
181
|
+
<div className="flex items-center gap-2">
|
|
182
|
+
<Badge variant="outline">Foundations</Badge>
|
|
183
|
+
<span className="text-xs text-muted-foreground">Tokens, Typography & Spatial Layout</span>
|
|
184
|
+
</div>
|
|
185
|
+
<h2 className="text-xl font-bold tracking-tight text-foreground">
|
|
186
|
+
ระบบโทเค็น ฟอนต์ และมิติพื้นฐาน
|
|
187
|
+
</h2>
|
|
188
|
+
<p className="text-sm text-muted-foreground">
|
|
189
|
+
ควบคุมธีม Light / Dark mode และความสอดคล้องของหน้าจอทั้งหมดจากศูนย์กลางที่ <code>globals.css</code>
|
|
190
|
+
</p>
|
|
191
|
+
</div>
|
|
192
|
+
|
|
193
|
+
{/* Semantic Color Tokens */}
|
|
194
|
+
<section className="flex flex-col gap-4">
|
|
195
|
+
<div className="flex items-center justify-between">
|
|
196
|
+
<div>
|
|
197
|
+
<h3 className="text-base font-semibold flex items-center gap-2">
|
|
198
|
+
<Palette className="size-4 text-primary" /> Semantic Color Tokens
|
|
199
|
+
</h3>
|
|
200
|
+
<p className="text-xs text-muted-foreground">
|
|
201
|
+
คลิกที่การ์ดเพื่อ Copy ชื่อ Tailwind utility ไปใช้งาน
|
|
202
|
+
</p>
|
|
203
|
+
</div>
|
|
204
|
+
</div>
|
|
205
|
+
|
|
206
|
+
<div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
|
|
207
|
+
{coreTokens.map((token) => (
|
|
208
|
+
<div
|
|
209
|
+
key={token.name}
|
|
210
|
+
onClick={() => copyToClipboard(token.tailwind)}
|
|
211
|
+
className="group relative flex flex-col gap-2.5 rounded-lg border bg-card p-3 shadow-2xs transition-all hover:border-primary/50 hover:shadow-xs cursor-pointer"
|
|
212
|
+
>
|
|
213
|
+
<div
|
|
214
|
+
className={`flex h-12 w-full items-center justify-between rounded-md p-3 font-medium text-xs shadow-2xs ${token.class}`}
|
|
215
|
+
>
|
|
216
|
+
<span>{token.name}</span>
|
|
217
|
+
{copiedToken === token.tailwind ? (
|
|
218
|
+
<Check className="size-3.5" />
|
|
219
|
+
) : (
|
|
220
|
+
<Copy className="size-3.5 opacity-0 transition-opacity group-hover:opacity-100" />
|
|
221
|
+
)}
|
|
222
|
+
</div>
|
|
223
|
+
<div className="flex flex-col gap-0.5">
|
|
224
|
+
<code className="text-xs font-mono font-medium text-primary">{token.tailwind}</code>
|
|
225
|
+
<p className="text-xs text-muted-foreground leading-tight pt-1">{token.usage}</p>
|
|
226
|
+
</div>
|
|
227
|
+
</div>
|
|
228
|
+
))}
|
|
229
|
+
</div>
|
|
230
|
+
</section>
|
|
231
|
+
|
|
232
|
+
{/* Sidebar & Chart Tokens */}
|
|
233
|
+
<div className="grid gap-6 lg:grid-cols-2">
|
|
234
|
+
{/* Sidebar Tokens */}
|
|
235
|
+
<Card>
|
|
236
|
+
<CardHeader className="pb-3">
|
|
237
|
+
<CardTitle className="text-base">Sidebar Palette Tokens</CardTitle>
|
|
238
|
+
<CardDescription className="text-xs">
|
|
239
|
+
โทเค็นสำหรับ Navigation Sidebar ทั้งโหมดพับและขยาย
|
|
240
|
+
</CardDescription>
|
|
241
|
+
</CardHeader>
|
|
242
|
+
<CardContent className="grid gap-2 sm:grid-cols-2">
|
|
243
|
+
{sidebarTokens.map((item) => (
|
|
244
|
+
<div
|
|
245
|
+
key={item.name}
|
|
246
|
+
className="flex flex-col gap-1.5 rounded-md border p-2.5 bg-card"
|
|
247
|
+
>
|
|
248
|
+
<div
|
|
249
|
+
className={`flex h-8 items-center justify-center rounded px-2 text-xs font-medium ${item.class}`}
|
|
250
|
+
>
|
|
251
|
+
{item.name}
|
|
252
|
+
</div>
|
|
253
|
+
<code className="text-xs text-muted-foreground font-mono">{item.token}</code>
|
|
254
|
+
</div>
|
|
255
|
+
))}
|
|
256
|
+
</CardContent>
|
|
257
|
+
</Card>
|
|
258
|
+
|
|
259
|
+
{/* Chart Tokens */}
|
|
260
|
+
<Card>
|
|
261
|
+
<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>
|
|
266
|
+
</CardHeader>
|
|
267
|
+
<CardContent className="grid gap-2 grid-cols-5">
|
|
268
|
+
{chartTokens.map((item) => (
|
|
269
|
+
<div key={item.name} className="flex flex-col items-center gap-1">
|
|
270
|
+
<div
|
|
271
|
+
className={`size-10 rounded-md flex items-center justify-center font-bold text-xs shadow-2xs ${item.class}`}
|
|
272
|
+
>
|
|
273
|
+
{item.name.slice(6, 7)}
|
|
274
|
+
</div>
|
|
275
|
+
<span className="text-xs text-muted-foreground font-mono text-center">
|
|
276
|
+
chart-{item.name.slice(6, 7)}
|
|
277
|
+
</span>
|
|
278
|
+
</div>
|
|
279
|
+
))}
|
|
280
|
+
</CardContent>
|
|
281
|
+
</Card>
|
|
282
|
+
</div>
|
|
283
|
+
|
|
284
|
+
{/* Typography Scale */}
|
|
285
|
+
<section className="flex flex-col gap-4">
|
|
286
|
+
<div className="flex flex-col gap-1">
|
|
287
|
+
<h3 className="text-base font-semibold flex items-center gap-2">
|
|
288
|
+
<Type className="size-4 text-primary" /> Typography Hierarchy (Noto Sans Thai Looped)
|
|
289
|
+
</h3>
|
|
290
|
+
<p className="text-xs text-muted-foreground">
|
|
291
|
+
ลำดับชั้นของตัวอักษรที่รองรับทั้งภาษาไทยและอังกฤษอย่างคมชัดบนทุกขนาดหน้าจอ
|
|
292
|
+
</p>
|
|
293
|
+
</div>
|
|
294
|
+
|
|
295
|
+
<Card>
|
|
296
|
+
<CardContent className="p-0 divide-y divide-border">
|
|
297
|
+
{typeScale.map((item) => (
|
|
298
|
+
<div
|
|
299
|
+
key={item.role}
|
|
300
|
+
className="flex flex-col gap-2 p-4 transition-colors hover:bg-muted/30 lg:flex-row lg:items-center lg:justify-between"
|
|
301
|
+
>
|
|
302
|
+
<div className="flex flex-col gap-1 w-full lg:w-1/3">
|
|
303
|
+
<div className="flex items-center gap-2">
|
|
304
|
+
<span className="font-semibold text-xs text-foreground">{item.role}</span>
|
|
305
|
+
<Badge variant="outline" className="text-xs font-mono py-0">
|
|
306
|
+
{item.className.split(" ")[0]}
|
|
307
|
+
</Badge>
|
|
308
|
+
</div>
|
|
309
|
+
<code className="text-xs text-muted-foreground font-mono">{item.className}</code>
|
|
310
|
+
<p className="text-xs text-muted-foreground">{item.usage}</p>
|
|
311
|
+
</div>
|
|
312
|
+
<div className="w-full lg:w-2/3 pt-1 lg:pt-0">
|
|
313
|
+
<div className={`rounded-md bg-muted/40 p-3 border ${item.className}`}>
|
|
314
|
+
{item.sample}
|
|
315
|
+
</div>
|
|
316
|
+
</div>
|
|
317
|
+
</div>
|
|
318
|
+
))}
|
|
319
|
+
</CardContent>
|
|
320
|
+
</Card>
|
|
321
|
+
</section>
|
|
322
|
+
|
|
323
|
+
{/* Spatial, Keyboard & Layout Rules */}
|
|
324
|
+
<section className="grid gap-6 lg:grid-cols-2">
|
|
325
|
+
{/* Spatial Rules */}
|
|
326
|
+
<Card>
|
|
327
|
+
<CardHeader className="pb-3">
|
|
328
|
+
<CardTitle className="text-base flex items-center gap-2">
|
|
329
|
+
<AlignLeft className="size-4 text-primary" /> Spatial & Spacing Rules
|
|
330
|
+
</CardTitle>
|
|
331
|
+
<CardDescription className="text-xs">กฎเกณฑ์การจัดช่องว่างและสัดส่วนเลย์เอาต์</CardDescription>
|
|
332
|
+
</CardHeader>
|
|
333
|
+
<CardContent className="flex flex-col gap-3">
|
|
334
|
+
{spatialRules.map((rule) => (
|
|
335
|
+
<div key={rule.title} className="flex flex-col gap-1 rounded-md border p-3 bg-card">
|
|
336
|
+
<div className="flex items-center justify-between">
|
|
337
|
+
<span className="font-semibold text-xs text-foreground">{rule.title}</span>
|
|
338
|
+
<code className="text-xs text-primary font-mono">{rule.rule}</code>
|
|
339
|
+
</div>
|
|
340
|
+
<p className="text-xs text-muted-foreground">{rule.reason}</p>
|
|
341
|
+
</div>
|
|
342
|
+
))}
|
|
343
|
+
</CardContent>
|
|
344
|
+
</Card>
|
|
345
|
+
|
|
346
|
+
{/* Keyboard Shortcuts & Kbd Primitives */}
|
|
347
|
+
<Card>
|
|
348
|
+
<CardHeader className="pb-3">
|
|
349
|
+
<CardTitle className="text-base flex items-center gap-2">
|
|
350
|
+
<Info className="size-4 text-primary" /> Keyboard Shortcuts (Kbd Primitive)
|
|
351
|
+
</CardTitle>
|
|
352
|
+
<CardDescription className="text-xs">
|
|
353
|
+
แสดงปุ่มคีย์ลัดสำหรับผู้ใช้และ Accessibility Navigation
|
|
354
|
+
</CardDescription>
|
|
355
|
+
</CardHeader>
|
|
356
|
+
<CardContent className="flex flex-col gap-3">
|
|
357
|
+
<div className="flex items-center justify-between rounded-md border p-3 bg-card">
|
|
358
|
+
<span className="text-xs text-muted-foreground">Quick Search / Global Command</span>
|
|
359
|
+
<KbdGroup>
|
|
360
|
+
<Kbd>⌘</Kbd>
|
|
361
|
+
<Kbd>K</Kbd>
|
|
362
|
+
</KbdGroup>
|
|
363
|
+
</div>
|
|
364
|
+
<div className="flex items-center justify-between rounded-md border p-3 bg-card">
|
|
365
|
+
<span className="text-xs text-muted-foreground">Save Form / Submit Package</span>
|
|
366
|
+
<KbdGroup>
|
|
367
|
+
<Kbd>Ctrl</Kbd>
|
|
368
|
+
<Kbd>S</Kbd>
|
|
369
|
+
</KbdGroup>
|
|
370
|
+
</div>
|
|
371
|
+
<div className="flex items-center justify-between rounded-md border p-3 bg-card">
|
|
372
|
+
<span className="text-xs text-muted-foreground">Close Dialog / Clear Filter</span>
|
|
373
|
+
<Kbd>Esc</Kbd>
|
|
374
|
+
</div>
|
|
375
|
+
<div className="flex items-center justify-between rounded-md border p-3 bg-card">
|
|
376
|
+
<span className="text-xs text-muted-foreground">Next Table Row / Field</span>
|
|
377
|
+
<Kbd>Tab</Kbd>
|
|
378
|
+
</div>
|
|
379
|
+
</CardContent>
|
|
380
|
+
</Card>
|
|
381
|
+
</section>
|
|
382
|
+
</div>
|
|
383
|
+
);
|
|
384
|
+
}
|