@godxjp/ui 28.5.0 → 28.7.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.
Files changed (58) hide show
  1. package/dist/components/data-display/data-table.d.ts +10 -2
  2. package/dist/components/data-display/data-table.js +12 -5
  3. package/dist/components/data-display/scroll-area.js +16 -2
  4. package/dist/components/data-display/service-launcher-card.d.ts +25 -0
  5. package/dist/components/data-display/table.d.ts +38 -1
  6. package/dist/components/data-display/table.js +57 -39
  7. package/dist/components/data-entry/field.d.ts +1 -1
  8. package/dist/components/data-entry/field.js +35 -4
  9. package/dist/components/data-entry/form-field.js +29 -12
  10. package/dist/components/data-entry/input.d.ts +1 -1
  11. package/dist/components/layout/index.d.ts +1 -1
  12. package/dist/components/layout/nav-list.d.ts +9 -1
  13. package/dist/components/layout/nav-list.js +22 -11
  14. package/dist/components/layout/sidebar.d.ts +16 -2
  15. package/dist/components/layout/sidebar.js +1 -0
  16. package/dist/components/navigation/app-setting-picker.js +20 -3
  17. package/dist/components/ui/password-input.d.ts +1 -1
  18. package/dist/components/ui/table.js +1 -0
  19. package/dist/contracts/measurement.json +1 -1
  20. package/dist/i18n/messages/en.json +5 -1
  21. package/dist/i18n/messages/ja.json +5 -1
  22. package/dist/i18n/messages/vi.json +5 -1
  23. package/dist/lib/control-styles.d.ts +18 -3
  24. package/dist/lib/control-styles.js +1 -1
  25. package/dist/lib/hooks.d.ts +23 -0
  26. package/dist/lib/hooks.js +27 -0
  27. package/dist/props/components/data-display.prop.d.ts +14 -0
  28. package/dist/props/components/data-entry.prop.d.ts +36 -2
  29. package/dist/props/components/layout.prop.d.ts +16 -5
  30. package/dist/props/registry.d.ts +2 -2
  31. package/dist/props/registry.js +10 -2
  32. package/dist/styles/control.css +12 -0
  33. package/dist/styles/data-display-layout.css +25 -2
  34. package/dist/styles/dialog-layout.css +12 -0
  35. package/dist/styles/form-layout.css +22 -0
  36. package/dist/styles/layout.css +1 -2
  37. package/dist/styles/navigation-layout.css +18 -19
  38. package/dist/tokens/components/data-display.css +2 -1
  39. package/dist/tokens/components/feedback.css +2 -0
  40. package/dist/tokens/components/form.css +2 -0
  41. package/dist/tokens/components/navigation.css +2 -0
  42. package/docs/COMPOSITION-VS-COMPONENT.md +3 -0
  43. package/docs/DESIGN-AUTHORITY.md +25 -5
  44. package/docs/FRAME-COVERAGE-REPORT.md +1 -1
  45. package/docs/data-display/collapsible.tsx +5 -5
  46. package/docs/data-display/descriptions.tsx +188 -109
  47. package/docs/data-display/legend.tsx +17 -4
  48. package/docs/data-display/scroll-area.tsx +106 -5
  49. package/docs/data-display/service-launcher-card.tsx +275 -115
  50. package/docs/data-display/stat-card.tsx +319 -64
  51. package/docs/data-entry/form.tsx +700 -6
  52. package/docs/data-entry/input.tsx +663 -53
  53. package/docs/data-entry/radio-group.tsx +216 -2
  54. package/docs/data-entry/switch.tsx +210 -4
  55. package/docs/data-entry/upload-crop-dialog.tsx +24 -25
  56. package/docs/layout/nav-list.tsx +556 -35
  57. package/package.json +9 -7
  58. package/scripts/visual-audit.mjs +29 -1
@@ -1,98 +1,353 @@
1
- import { StatCard } from "@godxjp/ui/data-display";
1
+ import {
2
+ Card,
3
+ CardContent,
4
+ CardDescription,
5
+ CardHeader,
6
+ CardTitle,
7
+ Progress,
8
+ StatCard,
9
+ } from "@godxjp/ui/data-display";
10
+ import { Badge } from "@godxjp/ui/data-display";
11
+ import { CompactBarTrend } from "@godxjp/ui/charts/compact-bar-trend";
2
12
  import { Text } from "@godxjp/ui/general";
3
13
  import { Flex, PageContainer, ResponsiveGrid } from "@godxjp/ui/layout";
4
- import { CheckCircle2, Package, Ship, TrendingUp, Wallet } from "lucide-react";
14
+ import {
15
+ AlertTriangle,
16
+ CheckCircle2,
17
+ Clock,
18
+ Database,
19
+ Package,
20
+ Percent,
21
+ Ship,
22
+ TrendingUp,
23
+ Users,
24
+ Wallet,
25
+ } from "lucide-react";
5
26
 
6
27
  /**
7
- * StatCard — KPI tile. It IS already a bordered Card, so it renders DIRECTLY in
8
- * ResponsiveGrid — never wrapped in Card/CardContent (double border). Section
9
- * titles are headings, not Cards. delta is sign-aware (+green / -red; inverse
10
- * flips it). Composed only from real @godxjp/ui components.
28
+ * StatCard — KPI tile.
29
+ *
30
+ * WHY THIS PAGE IS LONG. It was 99 lines and four tidy tiles, and the owner's verdict on the
31
+ * published site was that nothing here lets you judge whether the component is any good. That is
32
+ * the correct verdict: a KPI tile is trivial with `¥8,200,000` and a `+12%` delta. It is worth
33
+ * something only when the number is a 14-digit total, the label is a three-clause Japanese noun
34
+ * phrase, the delta means the opposite of what its sign says, or the value has not arrived yet.
35
+ *
36
+ * So every section below is a case a real dashboard hits, and several of them are the cases that
37
+ * BREAK a naive tile. If a section looks ugly, that is the page doing its job — the component has
38
+ * to earn it, not the sample data.
39
+ *
40
+ * StatCard IS already a bordered Card, so it renders DIRECTLY in ResponsiveGrid — never wrapped in
41
+ * Card/CardContent, which double-borders it.
11
42
  */
43
+ const trend7 = [
44
+ { d: "月", v: 42 },
45
+ { d: "火", v: 51 },
46
+ { d: "水", v: 38 },
47
+ { d: "木", v: 64 },
48
+ { d: "金", v: 72 },
49
+ { d: "土", v: 21 },
50
+ { d: "日", v: 9 },
51
+ ];
52
+
53
+ /** A section heading. Headings are headings, not Cards — a Card here would nest borders. */
54
+ function Section({
55
+ title,
56
+ why,
57
+ children,
58
+ }: {
59
+ title: string;
60
+ why: string;
61
+ children: React.ReactNode;
62
+ }) {
63
+ return (
64
+ <Flex direction="col" gap="sm">
65
+ <Text as="div" weight="medium">
66
+ {title}
67
+ </Text>
68
+ <Text as="div" size="sm" tone="muted">
69
+ {why}
70
+ </Text>
71
+ {children}
72
+ </Flex>
73
+ );
74
+ }
75
+
12
76
  export default function Demo() {
13
77
  return (
14
- <PageContainer
15
- title="StatCard"
16
- subtitle="KPI tiles · label · value · delta · hint, in a ResponsiveGrid"
17
- >
78
+ <PageContainer title="StatCard" subtitle="KPI tile — every shape a real dashboard asks for">
18
79
  <Flex direction="col" gap="lg">
19
- <Flex direction="col" gap="sm">
20
- <Text as="div" weight="medium">
21
- KPI row (stacked)
22
- </Text>
80
+ <Section
81
+ title="1 · KPI row"
82
+ why="The baseline: label, value, delta, hint. delta is sign-aware — + reads success, − reads destructive."
83
+ >
23
84
  <ResponsiveGrid columns={{ sm: 2, md: 4 }}>
24
85
  <StatCard label="月次売上" value="¥8,200,000" delta="+12%" hint="先月比" />
25
86
  <StatCard label="請求件数" value="312" delta="+4%" />
26
87
  <StatCard label="売掛金残高" value="¥1,284,500" hint="未回収 18件" />
27
88
  <StatCard label="回収率" value="96.8%" delta="+1.2%" />
28
89
  </ResponsiveGrid>
29
- </Flex>
90
+ </Section>
91
+
92
+ <Section
93
+ title="2 · inline layout, and align=end for a numeric column"
94
+ why="`inline` puts label and value on one line for a dense sidebar. `align=end` right-aligns the value so a stack of tiles reads as a column of numbers rather than ragged text."
95
+ >
96
+ <ResponsiveGrid columns={{ sm: 1, md: 2 }}>
97
+ <StatCard layout="inline" label="本日の受注" value="47" delta="+6" />
98
+ <StatCard layout="inline" align="end" label="本日の出荷" value="1,204" delta="−2%" />
99
+ <StatCard layout="inline" align="end" label="返品" value="3" delta="+1" inverse />
100
+ <StatCard layout="inline" align="end" label="在庫金額" value="¥42,880,000" />
101
+ </ResponsiveGrid>
102
+ </Section>
30
103
 
31
- <Flex direction="col" gap="sm">
32
- <Text as="div" weight="medium">
33
- icon medallion (decorative · tinted via --stat-card-icon-* tokens)
34
- </Text>
104
+ <Section
105
+ title="3 · inverse — when UP is bad"
106
+ why="A cost, an error count or a return rate rising is not good news. `inverse` flips the delta's colour so the tile agrees with the business, not with the arithmetic. Compare the two pairs: identical numbers, opposite meaning."
107
+ >
35
108
  <ResponsiveGrid columns={{ sm: 2, md: 4 }}>
36
- <StatCard icon={Package} label="処理中の注文" value="4" delta="+2" />
37
- <StatCard icon={Ship} label="輸送中" value="2" hint="日本 → ベトナム" />
38
- <StatCard icon={CheckCircle2} label="今月の配達" value="11" delta="+18%" />
39
- <StatCard icon={Wallet} label="ウォレット残高" value="¥185,000" />
109
+ <StatCard label="新規顧客" value="128" delta="+18%" hint="増えて良い" />
110
+ <StatCard label="解約数" value="128" delta="+18%" inverse hint="増えて悪い" />
111
+ <StatCard label="平均対応時間" value="4分12秒" delta="−22%" inverse hint="減って良い" />
112
+ <StatCard label="エラー率" value="0.42%" delta="+0.1pt" inverse />
40
113
  </ResponsiveGrid>
41
- </Flex>
114
+ </Section>
42
115
 
43
- <Flex direction="col" gap="sm">
44
- <Text as="div" weight="medium">
45
- Delta tone · sign-aware (inverse flips it)
46
- </Text>
47
- <ResponsiveGrid columns={{ sm: 2, md: 3 }}>
48
- <StatCard label="新規取引先" value="24" delta="+6" />
49
- <StatCard label="遅延請求書" value="7" delta="-3" />
50
- <StatCard
51
- label="平均処理コスト"
52
- value="¥1,180"
53
- delta="-15%"
116
+ <Section
117
+ title="4 · accent + icon"
118
+ why="`accent` tints the tile's mark, not its text — it groups tiles by domain (revenue / fulfilment / risk) without competing with the delta's own colour."
119
+ >
120
+ <ResponsiveGrid columns={{ sm: 2, md: 4 }}>
121
+ <StatCard accent="primary" icon={Wallet} label="入金" value="¥3,120,000" delta="+8%" />
122
+ <StatCard
123
+ accent="success"
124
+ icon={CheckCircle2}
125
+ label="検品通過"
126
+ value="1,182"
127
+ delta="+3%"
128
+ />
129
+ <StatCard
130
+ accent="warning"
131
+ icon={Clock}
132
+ label="期限間近"
133
+ value="23"
134
+ delta="+9"
54
135
  inverse
55
- hint="低いほど良い"
56
136
  />
137
+ <StatCard accent="info" icon={Ship} label="輸送中" value="58" hint="うち通関待ち 7" />
57
138
  </ResponsiveGrid>
58
- </Flex>
139
+ </Section>
59
140
 
60
- <Flex direction="col" gap="sm">
61
- <Text as="div" weight="medium">
62
- Inline layout (narrow panels)
63
- </Text>
64
- <ResponsiveGrid columns={{ sm: 1, md: 2 }}>
65
- <StatCard layout="inline" label="契約金額" value="¥4,800,000" />
66
- <StatCard layout="inline" label="消費税" value="¥480,000" hint="10%" />
141
+ <Section
142
+ title="5 · with a sparkline — the tile plus its shape over time"
143
+ why="A number says where you are; a trend says how you got here. CompactBarTrend goes in `hint`, which takes any node. `size=xs` keeps the tile the same height as a plain one, so a mixed row still lines up."
144
+ >
145
+ <ResponsiveGrid columns={{ sm: 1, md: 3 }}>
146
+ <StatCard
147
+ icon={TrendingUp}
148
+ label="週次受注"
149
+ value="297"
150
+ delta="+11%"
151
+ hint={
152
+ <CompactBarTrend
153
+ data={trend7}
154
+ categoryKey="d"
155
+ valueKey="v"
156
+ label="7日間の受注推移"
157
+ size="xs"
158
+ emphasizedIndex={4}
159
+ />
160
+ }
161
+ />
162
+ <StatCard
163
+ icon={Package}
164
+ label="出荷数"
165
+ value="1,204"
166
+ delta="−2%"
167
+ hint={
168
+ <CompactBarTrend
169
+ data={trend7}
170
+ categoryKey="d"
171
+ valueKey="v"
172
+ label="7日間の出荷推移"
173
+ size="xs"
174
+ />
175
+ }
176
+ />
177
+ <StatCard
178
+ icon={Users}
179
+ label="稼働ユーザー"
180
+ value="8,412"
181
+ delta="+240"
182
+ hint={
183
+ <CompactBarTrend
184
+ data={trend7}
185
+ categoryKey="d"
186
+ valueKey="v"
187
+ label="7日間の稼働推移"
188
+ size="xs"
189
+ showCategoryLabels
190
+ />
191
+ }
192
+ />
67
193
  </ResponsiveGrid>
68
- </Flex>
194
+ </Section>
69
195
 
70
- <Flex direction="col" gap="sm">
71
- <Text as="div" weight="medium">
72
- align=&quot;end&quot; · icon label · neutral delta
73
- </Text>
196
+ <Section
197
+ title="6 · with a ring or a bar — a number that is a proportion"
198
+ why="A count out of a total is not a delta, it is a completion. The ring carries the proportion inside the tile; the bar carries a three-way breakdown. Both go in `hint` for the same reason the sparkline does."
199
+ >
200
+ <ResponsiveGrid columns={{ sm: 1, md: 3 }}>
201
+ <StatCard
202
+ label="月次締め処理"
203
+ value="26 / 42"
204
+ hint={<Progress shape="ring" size="sm" value={62} label="26/42" />}
205
+ />
206
+ <StatCard
207
+ label="検収完了"
208
+ value="88%"
209
+ delta="+6pt"
210
+ hint={<Progress value={88} tone="success" label="検収完了 88%" />}
211
+ />
212
+ <StatCard
213
+ label="請求ステータス"
214
+ value="17 件"
215
+ hint={
216
+ <Progress
217
+ segments={[
218
+ { value: 2, tone: "destructive", label: "期限超過" },
219
+ { value: 3, tone: "warning", label: "期限間近" },
220
+ { value: 12, tone: "success", label: "対応済" },
221
+ ]}
222
+ aria-label="請求ステータス内訳"
223
+ />
224
+ }
225
+ />
226
+ </ResponsiveGrid>
227
+ </Section>
228
+
229
+ <Section
230
+ title="7 · the kinds of number a dashboard actually shows"
231
+ why="Currency, percentage, count, duration, ratio, bytes and a date each format differently and each has a different natural width. A tile that only ever holds ¥8,200,000 has not been tested."
232
+ >
74
233
  <ResponsiveGrid columns={{ sm: 2, md: 4 }}>
234
+ <StatCard icon={Wallet} label="通貨" value="¥8,214,930" delta="+12%" hint="JPY・税込" />
235
+ <StatCard
236
+ icon={Percent}
237
+ label="百分率"
238
+ value="96.8%"
239
+ delta="+1.2pt"
240
+ hint="pt と % は別物"
241
+ />
242
+ <StatCard icon={Package} label="件数" value="1,284" delta="+96" hint="単位は件" />
243
+ <StatCard icon={Clock} label="所要時間" value="4分12秒" delta="−22%" inverse />
244
+ <StatCard label="比率" value="3.4 : 1" hint="受注 : 返品" />
245
+ <StatCard
246
+ icon={Database}
247
+ label="容量"
248
+ value="812.4 GB"
249
+ delta="+4.1 GB"
250
+ inverse
251
+ hint="上限 1 TB"
252
+ />
253
+ <StatCard label="最終同期" value="3分前" hint="2026-09-21 10:02" />
254
+ <StatCard label="多通貨" value="$54,210" hint="USD・参考レート ¥147.2" />
255
+ </ResponsiveGrid>
256
+ </Section>
257
+
258
+ <Section
259
+ title="8 · the cases that break a naive tile"
260
+ why="This row is deliberately hostile, and it is the only row on this page that can tell you whether StatCard is good. A long Japanese label must wrap without shoving the value out; a 14-digit total must not collide with its delta; zero is not the same as missing; a negative balance must still read as a number and not as an error."
261
+ >
262
+ <ResponsiveGrid columns={{ sm: 1, md: 3 }}>
263
+ <StatCard
264
+ label="グローバル人事情報基盤・従業員セルフサービス利用率(アジア太平洋地域)"
265
+ value="72.4%"
266
+ delta="+3.1pt"
267
+ hint="ラベルが3行に折り返しても、値と delta は動かない"
268
+ />
75
269
  <StatCard
76
- label="当期利益"
77
- value="¥3,120,000"
78
- delta="+8%"
79
- align="end"
80
- hint="既定の密度 · 右寄せ"
270
+ label="累計取扱高"
271
+ value="¥128,400,932,517"
272
+ delta="+0.8%"
273
+ hint="14桁でも delta と衝突しない"
81
274
  />
82
- <StatCard label="年間売上" value="¥98,400,000" delta="+11%" hint="ゆとりある密度" />
275
+ <StatCard label="未処理" value="0" hint="ゼロは「無い」であって「未取得」ではない" />
276
+ <StatCard label="取得中" value="—" hint="値が来ていない。0 と区別が付くこと" />
83
277
  <StatCard
84
- label={
85
- <>
86
- <TrendingUp aria-hidden />
87
- 成長率
88
- </>
278
+ label="差引残高"
279
+ value="−¥412,880"
280
+ delta="−12%"
281
+ inverse
282
+ hint="マイナスの値そのもの"
283
+ />
284
+ <StatCard
285
+ icon={AlertTriangle}
286
+ accent="warning"
287
+ label="要確認"
288
+ value="3"
289
+ delta="+3"
290
+ inverse
291
+ hint={
292
+ <Badge tone="warning" variant="outline">
293
+ 承認待ち
294
+ </Badge>
89
295
  }
90
- value="14.2%"
91
- delta="+2.1%"
92
296
  />
93
- <StatCard label="客単価" value="¥6,400" delta="0%" hint="横ばい" />
94
297
  </ResponsiveGrid>
95
- </Flex>
298
+ </Section>
299
+
300
+ <Section
301
+ title="9 · one row, mixed shapes"
302
+ why="Dashboards do not use one variant at a time. A plain tile, a sparkline tile, a ring tile and an inline tile share a row here: if their heights or baselines disagree, it shows up here and nowhere else."
303
+ >
304
+ <ResponsiveGrid columns={{ sm: 2, md: 4 }}>
305
+ <StatCard label="売上" value="¥8,200,000" delta="+12%" />
306
+ <StatCard
307
+ label="受注"
308
+ value="297"
309
+ hint={
310
+ <CompactBarTrend
311
+ data={trend7}
312
+ categoryKey="d"
313
+ valueKey="v"
314
+ label="受注推移"
315
+ size="xs"
316
+ />
317
+ }
318
+ />
319
+ <StatCard
320
+ label="締め"
321
+ value="62%"
322
+ hint={<Progress shape="ring" size="sm" value={62} label="62%" />}
323
+ />
324
+ <StatCard layout="inline" align="end" label="返品" value="3" delta="+1" inverse />
325
+ </ResponsiveGrid>
326
+ </Section>
327
+
328
+ <Card>
329
+ <CardHeader>
330
+ <CardTitle level={2}>使い方の要点</CardTitle>
331
+ <CardDescription>この3点を外すと、上のどれかが必ず崩れます。</CardDescription>
332
+ </CardHeader>
333
+ <CardContent>
334
+ <Flex direction="col" gap="sm">
335
+ <Text as="div" size="sm">
336
+ StatCard は<strong>それ自体がカード</strong>です。ResponsiveGrid
337
+ に直接置いてください。Card/CardContent で包むと枠が二重になります。
338
+ </Text>
339
+ <Text as="div" size="sm">
340
+ delta は<strong>符号で色が決まります</strong>
341
+ 。増えて困る指標(解約・エラー・コスト)には必ず
342
+ <code>inverse</code> を付けてください。付け忘れは「悪化を緑で祝う」表示になります。
343
+ </Text>
344
+ <Text as="div" size="sm">
345
+ <code>hint</code> は ReactNode です。文字列だけでなく、上のように
346
+ CompactBarTrend・Progress・Badge をそのまま入れられます。
347
+ </Text>
348
+ </Flex>
349
+ </CardContent>
350
+ </Card>
96
351
  </Flex>
97
352
  </PageContainer>
98
353
  );