@godxjp/ui 28.5.0 → 28.6.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 (35) hide show
  1. package/dist/components/data-entry/field.d.ts +1 -1
  2. package/dist/components/data-entry/field.js +35 -4
  3. package/dist/components/data-entry/input.d.ts +1 -1
  4. package/dist/components/layout/index.d.ts +1 -1
  5. package/dist/components/layout/nav-list.d.ts +9 -1
  6. package/dist/components/layout/nav-list.js +22 -11
  7. package/dist/components/layout/sidebar.d.ts +16 -2
  8. package/dist/components/layout/sidebar.js +1 -0
  9. package/dist/components/ui/password-input.d.ts +1 -1
  10. package/dist/contracts/measurement.json +1 -1
  11. package/dist/lib/control-styles.d.ts +18 -3
  12. package/dist/lib/control-styles.js +1 -1
  13. package/dist/props/components/data-entry.prop.d.ts +36 -2
  14. package/dist/props/components/layout.prop.d.ts +16 -5
  15. package/dist/props/registry.d.ts +1 -1
  16. package/dist/props/registry.js +8 -1
  17. package/dist/styles/control.css +12 -0
  18. package/dist/styles/data-display-layout.css +25 -2
  19. package/dist/styles/dialog-layout.css +12 -0
  20. package/dist/styles/layout.css +1 -1
  21. package/dist/tokens/components/data-display.css +2 -1
  22. package/dist/tokens/components/feedback.css +2 -0
  23. package/docs/FRAME-COVERAGE-REPORT.md +1 -1
  24. package/docs/data-display/collapsible.tsx +5 -5
  25. package/docs/data-display/descriptions.tsx +188 -109
  26. package/docs/data-display/legend.tsx +17 -4
  27. package/docs/data-display/scroll-area.tsx +75 -5
  28. package/docs/data-display/stat-card.tsx +319 -64
  29. package/docs/data-entry/form.tsx +700 -6
  30. package/docs/data-entry/input.tsx +663 -53
  31. package/docs/data-entry/radio-group.tsx +216 -2
  32. package/docs/data-entry/switch.tsx +210 -4
  33. package/docs/data-entry/upload-crop-dialog.tsx +24 -25
  34. package/docs/layout/nav-list.tsx +556 -35
  35. package/package.json +7 -6
@@ -6,176 +6,255 @@ import {
6
6
  CardHeader,
7
7
  CardTitle,
8
8
  Descriptions,
9
+ Progress,
10
+ Thumbnail,
9
11
  } from "@godxjp/ui/data-display";
10
- import type { CSSProperties } from "react";
11
- import { Text } from "@godxjp/ui/general";
12
+ import { Button, Text } from "@godxjp/ui/general";
12
13
  import { Flex, PageContainer } from "@godxjp/ui/layout";
14
+ import { Download, ExternalLink, FileText } from "lucide-react";
13
15
 
14
16
  /**
15
- * Descriptions — responsive label/value grid for detail-page metadata. COMPOUND:
16
- * the value goes in Descriptions.Item children. Never hand-roll a dl/dt/dd grid.
17
- * Composed only from real @godxjp/ui components.
17
+ * Descriptions — the label/value grid every detail page is made of.
18
+ *
19
+ * WHY THIS PAGE IS LONG. It was five tidy cards of short strings, and the owner's verdict was that
20
+ * it shows nothing about whether the component holds up. That is right: a label/value grid is
21
+ * trivial when every label is four characters and every value is one line.
22
+ *
23
+ * A real detail screen is not that. It has a label that runs to three lines beside one that is two
24
+ * characters; a value that is an image, a file to download, a link, a status, a progress bar, a
25
+ * 40-character machine ID, or nothing at all; and it has to survive all of them in the same grid,
26
+ * at every breakpoint, bordered and not.
27
+ *
28
+ * So every section below is a case a real detail page hits. Where a section looks bad, the
29
+ * component owes an answer — the sample data is not there to flatter it.
18
30
  */
31
+ const ID = "01JBQ9X7M4K2R8VT3NZ6YHF0PA";
32
+
19
33
  export default function Demo() {
20
34
  return (
21
- <PageContainer title="Descriptions" subtitle="Label / value metadata grid for detail pages">
35
+ <PageContainer
36
+ title="Descriptions"
37
+ subtitle="label/value grid — every shape a detail page asks for"
38
+ >
22
39
  <Flex direction="col" gap="lg">
23
- {/* Default columns=2 — the canonical 2-column metadata grid.
24
- mono for the ID; span=2 + a long URL value shows full-row + break-all overflow. */}
25
40
  <Card>
26
41
  <CardHeader>
27
- <CardTitle level={2}>請求書の詳細</CardTitle>
42
+ <CardTitle level={2}>1 · columns × bordered × layout — the three axes</CardTitle>
28
43
  <CardDescription>
29
- 既定は
30
- columns=2。値は任意のノード(テキスト・Badge・金額)。狭い画面では1列に折り返します。
44
+ Every combination changes where the label sits and how the grid divides. These are the
45
+ four a project actually picks between.
31
46
  </CardDescription>
32
47
  </CardHeader>
33
48
  <CardContent>
34
- <Descriptions>
35
- <Descriptions.Item label="請求書番号" mono>
36
- INV-2024-0312
37
- </Descriptions.Item>
38
- <Descriptions.Item label="取引先">株式会社ベトヤ</Descriptions.Item>
39
- <Descriptions.Item label="状態">
40
- <Badge status="active" />
41
- </Descriptions.Item>
42
- <Descriptions.Item label="発行日">2024-04-12</Descriptions.Item>
43
- <Descriptions.Item label="小計">
44
- <Text tabular>¥438,182</Text>
45
- </Descriptions.Item>
46
- <Descriptions.Item label="消費税 (10%)">
47
- <Text tabular>¥43,818</Text>
48
- </Descriptions.Item>
49
- <Descriptions.Item label="合計">
50
- <Text weight="medium" tabular>
51
- ¥482,000
49
+ <Flex direction="col" gap="lg">
50
+ <Flex direction="col" gap="xs">
51
+ <Text size="sm" tone="muted">
52
+ columns=3 · bordered · horizontal — the dense admin default
52
53
  </Text>
54
+ <Descriptions columns={3} bordered layout="horizontal">
55
+ <Descriptions.Item label="取引先">株式会社山田製作所</Descriptions.Item>
56
+ <Descriptions.Item label="担当">佐藤 玲</Descriptions.Item>
57
+ <Descriptions.Item label="状態">
58
+ <Badge tone="success">有効</Badge>
59
+ </Descriptions.Item>
60
+ <Descriptions.Item label="登録日">2024-04-01</Descriptions.Item>
61
+ <Descriptions.Item label="与信枠">¥12,000,000</Descriptions.Item>
62
+ <Descriptions.Item label="支払条件">月末締め翌月末払い</Descriptions.Item>
63
+ </Descriptions>
64
+ </Flex>
65
+
66
+ <Flex direction="col" gap="xs">
67
+ <Text size="sm" tone="muted">
68
+ columns=2 · no border · vertical — the reading layout, label above value
69
+ </Text>
70
+ <Descriptions columns={2} layout="vertical">
71
+ <Descriptions.Item label="取引先">株式会社山田製作所</Descriptions.Item>
72
+ <Descriptions.Item label="担当">佐藤 玲</Descriptions.Item>
73
+ <Descriptions.Item label="与信枠">¥12,000,000</Descriptions.Item>
74
+ <Descriptions.Item label="支払条件">月末締め翌月末払い</Descriptions.Item>
75
+ </Descriptions>
76
+ </Flex>
77
+
78
+ <Flex direction="col" gap="xs">
79
+ <Text size="sm" tone="muted">
80
+ columns=1 · bordered — a narrow column or a phone
81
+ </Text>
82
+ <Descriptions columns={1} bordered>
83
+ <Descriptions.Item label="取引先">株式会社山田製作所</Descriptions.Item>
84
+ <Descriptions.Item label="状態">
85
+ <Badge tone="success">有効</Badge>
86
+ </Descriptions.Item>
87
+ </Descriptions>
88
+ </Flex>
89
+
90
+ <Flex direction="col" gap="xs">
91
+ <Text size="sm" tone="muted">
92
+ labelAlign=end — right-aligned labels, so the values start on one line
93
+ </Text>
94
+ <Descriptions columns={2} bordered labelAlign="end">
95
+ <Descriptions.Item label="ID">{ID}</Descriptions.Item>
96
+ <Descriptions.Item label="状態">
97
+ <Badge tone="success">有効</Badge>
98
+ </Descriptions.Item>
99
+ </Descriptions>
100
+ </Flex>
101
+ </Flex>
102
+ </CardContent>
103
+ </Card>
104
+
105
+ <Card>
106
+ <CardHeader>
107
+ <CardTitle level={2}>2 · responsive columns</CardTitle>
108
+ <CardDescription>
109
+ `columns` takes a breakpoint object. Narrow this frame with the Dimensions control: 1
110
+ column on a phone, 2 on a tablet, 3 on a desktop — the same markup throughout.
111
+ </CardDescription>
112
+ </CardHeader>
113
+ <CardContent>
114
+ <Descriptions columns={{ sm: 1, md: 2, lg: 3 }} bordered>
115
+ <Descriptions.Item label="会社名">株式会社山田製作所</Descriptions.Item>
116
+ <Descriptions.Item label="法人番号" mono>
117
+ 7010001071491
53
118
  </Descriptions.Item>
54
- <Descriptions.Item label="PDF リンク" mono span={2}>
55
- https://invoices.vetoya.example.co.jp/2024/04/INV-2024-0312-rev2.pdf
56
- </Descriptions.Item>
119
+ <Descriptions.Item label="業種">精密機器製造</Descriptions.Item>
120
+ <Descriptions.Item label="代表">山田 太郎</Descriptions.Item>
121
+ <Descriptions.Item label="従業員数">248 名</Descriptions.Item>
122
+ <Descriptions.Item label="設立">1974-06-12</Descriptions.Item>
57
123
  </Descriptions>
58
124
  </CardContent>
59
125
  </Card>
60
126
 
61
- {/* layout="horizontal" — label BESIDE value (token-aligned label column), like <Form layout>.
62
- Default layout is "vertical" (label over value, the cards above). */}
63
127
  <Card>
64
128
  <CardHeader>
65
- <CardTitle level={2}>横並び (layout=&quot;horizontal&quot;)</CardTitle>
129
+ <CardTitle level={2}>3 · the value is not a string</CardTitle>
66
130
  <CardDescription>
67
- ラベルを値の左に揃える。`--descriptions-label-width` でラベル列幅を調整。既定は
68
- layout=&quot;vertical&quot;(ラベルを上に積む、上のカード)。
131
+ The value slot takes any node. These are the ones a detail page actually puts there —
132
+ an image, a file, a link, a status, a proportion, a secret, money, a long memo.
69
133
  </CardDescription>
70
134
  </CardHeader>
71
135
  <CardContent>
72
- <Descriptions columns={1} layout="horizontal">
73
- <Descriptions.Item label="請求書番号" mono>
74
- INV-2024-0312
136
+ <Descriptions columns={{ sm: 1, md: 2 }} bordered>
137
+ <Descriptions.Item label="製品画像">
138
+ <Thumbnail src="/godxjp-ui/favicon.svg" alt="製品サムネイル" size="md" />
75
139
  </Descriptions.Item>
76
- <Descriptions.Item label="取引先">株式会社ベトヤ</Descriptions.Item>
77
140
  <Descriptions.Item label="状態">
78
- <Badge status="active" />
141
+ <Flex direction="row" gap="xs" wrap>
142
+ <Badge tone="success">出荷可</Badge>
143
+ <Badge tone="warning" variant="outline">
144
+ 在庫僅少
145
+ </Badge>
146
+ </Flex>
79
147
  </Descriptions.Item>
80
- <Descriptions.Item label="合計">
81
- <Text weight="medium" tabular>
82
- ¥482,000
83
- </Text>
148
+ <Descriptions.Item label="仕様書">
149
+ <Button variant="outline" size="sm">
150
+ <FileText className="size-4" />
151
+ 仕様書_v4.2.pdf
152
+ </Button>
153
+ </Descriptions.Item>
154
+ <Descriptions.Item label="検査成績書">
155
+ <Button variant="ghost" size="sm">
156
+ <Download className="size-4" />
157
+ ダウンロード(2.4 MB)
158
+ </Button>
159
+ </Descriptions.Item>
160
+ <Descriptions.Item label="外部リンク">
161
+ <Button variant="link" size="sm">
162
+ <ExternalLink className="size-4" />
163
+ サプライヤーポータル
164
+ </Button>
165
+ </Descriptions.Item>
166
+ <Descriptions.Item label="検収進捗">
167
+ <Progress value={72} tone="success" label="検収進捗 72%" />
168
+ </Descriptions.Item>
169
+ <Descriptions.Item label="単価">¥128,400</Descriptions.Item>
170
+ <Descriptions.Item label="ロットID" mono>
171
+ {ID}
84
172
  </Descriptions.Item>
85
173
  </Descriptions>
86
174
  </CardContent>
87
175
  </Card>
88
176
 
89
- {/* columns=1 — stacked detail panel: every item on its own row. */}
90
177
  <Card>
91
178
  <CardHeader>
92
- <CardTitle level={2}>取引先の詳細</CardTitle>
93
- <CardDescription>columns=1。各項目を縦積みにする詳細パネル向けの構成。</CardDescription>
179
+ <CardTitle level={2}>4 · span — a value that needs the whole row</CardTitle>
180
+ <CardDescription>
181
+ An address, a memo or a JSON blob does not belong in a one-third cell. `span` widens
182
+ the item; `span=&quot;filled&quot;` takes whatever is left on the row, so the grid
183
+ stays aligned instead of leaving a hole.
184
+ </CardDescription>
94
185
  </CardHeader>
95
186
  <CardContent>
96
- <Descriptions columns={1}>
97
- <Descriptions.Item label="会社名">株式会社ベトヤ</Descriptions.Item>
98
- <Descriptions.Item label="法人番号" mono>
99
- 1180001052731
187
+ <Descriptions columns={3} bordered>
188
+ <Descriptions.Item label="取引先">株式会社山田製作所</Descriptions.Item>
189
+ <Descriptions.Item label="担当">佐藤 玲</Descriptions.Item>
190
+ <Descriptions.Item label="電話">03-5555-0198</Descriptions.Item>
191
+ <Descriptions.Item label="本社所在地" span={3}>
192
+ 〒105-0011 東京都港区芝公園四丁目2番8号 東京タワー内 グローバルビジネスセンター 23F
193
+ 株式会社山田製作所 東日本統括本部
100
194
  </Descriptions.Item>
101
- <Descriptions.Item label="住所">
102
- 東京都渋谷区神宮前5-52-2 青山オーバルビル7F
195
+ <Descriptions.Item label="備考" span="filled">
196
+ 検収は毎月第2・第4火曜のみ。祝日と重なる場合は翌営業日に振替。先方の受入窓口は
197
+ 資材部・資材管理課(内線
198
+ 4821)。2026年4月以降は電子取引のみとなるため、紙の納品書は不可。
103
199
  </Descriptions.Item>
104
- <Descriptions.Item label="担当者">山田 太郎(経理部)</Descriptions.Item>
200
+ <Descriptions.Item label="与信枠">¥12,000,000</Descriptions.Item>
201
+ <Descriptions.Item label="使用中">¥8,214,930</Descriptions.Item>
105
202
  </Descriptions>
106
203
  </CardContent>
107
204
  </Card>
108
205
 
109
- {/* columns=3 — dense metadata grid; span=3 makes the JSON value occupy the full width. */}
110
206
  <Card>
111
207
  <CardHeader>
112
- <CardTitle level={2}>システムメタデータ</CardTitle>
208
+ <CardTitle level={2}>5 · the cases that break a label/value grid</CardTitle>
113
209
  <CardDescription>
114
- columns=3。識別子の多い密なメタデータ向け。mono と span でIDやJSONを整列。
210
+ This is the only section on the page that can tell you whether Descriptions is any
211
+ good. If a row here looks wrong, the component owes an answer — not the data.
115
212
  </CardDescription>
116
213
  </CardHeader>
117
214
  <CardContent>
118
- <Descriptions columns={3}>
119
- <Descriptions.Item label="リソースID" mono>
120
- inv_8f3a21c0
215
+ <Descriptions columns={{ sm: 1, md: 2, lg: 3 }} bordered>
216
+ <Descriptions.Item label="グローバル人事情報基盤・従業員セルフサービスポータル(アジア太平洋地域)連携ステータス">
217
+ <Badge tone="success">連携済</Badge>
121
218
  </Descriptions.Item>
122
- <Descriptions.Item label="リビジョン" mono>
123
- v3
219
+ <Descriptions.Item label="率">96.8%</Descriptions.Item>
220
+ <Descriptions.Item label="ID" mono>
221
+ urn:godx:entitlement:ap-northeast-1:7010001071491:workforce/identity/administration/v4
124
222
  </Descriptions.Item>
125
- <Descriptions.Item label="状態">
126
- <Badge status="active" />
127
- </Descriptions.Item>
128
- <Descriptions.Item label="作成日時" mono>
129
- 2024-04-12T09:31:00+09:00
130
- </Descriptions.Item>
131
- <Descriptions.Item label="更新日時" mono>
132
- 2024-04-12T14:07:55+09:00
223
+ <Descriptions.Item label="未設定">
224
+ <Text tone="muted">—</Text>
133
225
  </Descriptions.Item>
134
- <Descriptions.Item label="作成者">山田 太郎</Descriptions.Item>
135
- <Descriptions.Item label="メタデータ" mono span={3}>
136
- {'{ "channel": "web", "tax_rate": 0.1, "currency": "JPY" }'}
226
+ <Descriptions.Item label="空文字">{""}</Descriptions.Item>
227
+ <Descriptions.Item label="ゼロ">0</Descriptions.Item>
228
+ <Descriptions.Item label="累計取扱高">¥128,400,932,517</Descriptions.Item>
229
+ <Descriptions.Item label="差引">−¥412,880</Descriptions.Item>
230
+ <Descriptions.Item label="長い英数字" mono>
231
+ AKIAIOSFODNN7EXAMPLEWJALRXUTNFEMIK7MDENGBPXRFICYEXAMPLEKEY
137
232
  </Descriptions.Item>
138
233
  </Descriptions>
139
234
  </CardContent>
140
235
  </Card>
141
236
 
142
- {/* ── The RULED property panel (gh#414) ─────────────────────────────
143
- Two token knobs, both OFF by default, turn a horizontal Descriptions into the ruled
144
- panel a detail page usually wants. They exist so a service stops hand-rolling a
145
- `<Flex className="min-h-10 border-b">` row: the label column, the gaps and the value
146
- type step were already Descriptions'; only the rule and the band height were missing.
147
- The row gap goes to 0 in the same declaration — the gap is the space BETWEEN rules, so
148
- leaving it would draw detached hairlines instead of a ruled list. */}
149
237
  <Card>
150
238
  <CardHeader>
151
- <CardTitle level={2}>案件の詳細 · ruled rows</CardTitle>
152
- <CardDescription>
153
- 一行ごとに罫線を引いた属性パネル。--descriptions-row-border と
154
- --descriptions-row-min-height をテーマで一度設定するだけで、コンポーネントは同じです。
155
- </CardDescription>
239
+ <CardTitle level={2}>使い方の要点</CardTitle>
240
+ <CardDescription>この3点で、上のほとんどが決まります。</CardDescription>
156
241
  </CardHeader>
157
- {/* The knobs are declared on the CARD BODY, not on the grid: custom properties inherit,
158
- so one scope re-tunes every Descriptions inside it — which is how a service theme
159
- would set them (once, globally), not per call site. */}
160
- <CardContent
161
- style={
162
- {
163
- "--descriptions-row-border": "1px solid hsl(var(--border))",
164
- "--descriptions-row-min-height": "var(--band-height-lg)",
165
- "--descriptions-row-gap": "0px",
166
- } as CSSProperties
167
- }
168
- >
169
- <Descriptions columns={1} layout="horizontal">
170
- <Descriptions.Item label="案件名">2026年度 基幹システム更改</Descriptions.Item>
171
- <Descriptions.Item label="担当">山田 太郎</Descriptions.Item>
172
- <Descriptions.Item label="状態">
173
- <Badge status="active" />
174
- </Descriptions.Item>
175
- <Descriptions.Item label="契約ID" mono>
176
- CT-2026-0088
177
- </Descriptions.Item>
178
- </Descriptions>
242
+ <CardContent>
243
+ <Flex direction="col" gap="sm">
244
+ <Text as="div" size="sm">
245
+ 直下の子は <code>Descriptions.Item</code> だけです。生の <code>&lt;div&gt;</code> や
246
+ <code>&lt;dt&gt;/&lt;dd&gt;</code> を混ぜるとグリッドが崩れます。
247
+ </Text>
248
+ <Text as="div" size="sm">
249
+ 機械可読な値(ID・パス・鍵・通貨コード)には <code>mono</code> を付けてください。
250
+ 等幅になるだけでなく <code>break-all</code> が効き、上の 57
251
+ 文字の鍵がセルを突き破らずに折り返します。
252
+ </Text>
253
+ <Text as="div" size="sm">
254
+ 住所・備考・JSON のような長い値には <code>span</code> を。 1/3
255
+ セルに押し込むと、その行だけ高さが跳ねて表全体が読みにくくなります。
256
+ </Text>
257
+ </Flex>
179
258
  </CardContent>
180
259
  </Card>
181
260
  </Flex>
@@ -61,7 +61,20 @@ export default function Demo() {
61
61
  aria-label={row.name}
62
62
  />
63
63
  </Flex>
64
- <Flex width={150} justify="end" align="center" gapRaw={12}>
64
+ {/* A COLUMN OF NUMBERS NEEDS COLUMNS, not a row of shrink-to-fit boxes.
65
+ `tabular` makes DIGITS equal-width inside one Text; it cannot align two Texts
66
+ with different digit COUNTS. Laid out as a flex row and right-aligned as a
67
+ group, a row ending in "9" sat 8px right of one ending in "21" — measured on
68
+ the published site, and the reason this readout looked crooked. Fixed tracks
69
+ give each value its own cell, so every row lines up whatever the digits. */}
70
+ <div
71
+ className="grid items-center"
72
+ style={{
73
+ gridTemplateColumns: "2.5rem 2.5rem 2.5rem 4.5rem",
74
+ justifyItems: "end",
75
+ columnGap: "var(--space-2)",
76
+ }}
77
+ >
65
78
  <Text tone="destructive" weight="semibold" tabular>
66
79
  {row.over}
67
80
  </Text>
@@ -74,7 +87,7 @@ export default function Demo() {
74
87
  <Text tone="muted" tabular>
75
88
  計 {row.over + row.near + row.done}
76
89
  </Text>
77
- </Flex>
90
+ </div>
78
91
  </Flex>
79
92
  ))}
80
93
  </Flex>
@@ -108,8 +121,8 @@ export default function Demo() {
108
121
  <CardHeader>
109
122
  <CardTitle level={2}>Named legend</CardTitle>
110
123
  <CardDescription>
111
- aria-label を渡すと、その凡例が「何のキーか」を読み上げます。項目は list /
112
- listitem として並びます。
124
+ aria-label を渡すと、その凡例が「何のキーか」を読み上げます。項目は list / listitem
125
+ として並びます。
113
126
  </CardDescription>
114
127
  </CardHeader>
115
128
  <CardContent>
@@ -116,6 +116,7 @@ export default function Demo() {
116
116
  <Card variant="outline" className="h-64 w-full">
117
117
  <CardContent flush>
118
118
  <ScrollArea
119
+ className="h-72"
119
120
  anchor="bottom"
120
121
  viewportRef={streamViewport}
121
122
  onAnchoredChange={setAnchored}
@@ -176,7 +177,7 @@ export default function Demo() {
176
177
  <CardContent>
177
178
  <Card variant="outline" className="h-40 w-full">
178
179
  <CardContent flush>
179
- <ScrollArea anchor="bottom" anchorOffset={0}>
180
+ <ScrollArea className="h-40" anchor="bottom" anchorOffset={0}>
180
181
  <CardContent>
181
182
  <Flex direction="col" gap="xs">
182
183
  {entries.map((e) => (
@@ -192,6 +193,67 @@ export default function Demo() {
192
193
  </CardContent>
193
194
  </Card>
194
195
 
196
+ <Card>
197
+ <CardHeader>
198
+ <CardTitle level={2}>
199
+ scrollbar=&quot;always&quot; — 「スクロールバーが見えない」の答え
200
+ </CardTitle>
201
+ <CardDescription>
202
+ 既定の <code>auto</code> はプラットフォームに任せます。macOS / iPadOS
203
+ のシステム既定「スクロール中にのみ表示」では、それは
204
+ <strong>オーバーレイのバー</strong>
205
+ です。つまり、すでにスクロールしている間しか存在しません。止まっている状態では、
206
+ この面がスクロールできることが一切わかりません(gh#798)。
207
+ 下の2つは中身も高さも同一で、違うのは <code>scrollbar</code> だけです。
208
+ </CardDescription>
209
+ </CardHeader>
210
+ <CardContent>
211
+ <ResponsiveGrid columns={{ sm: 1, md: 2 }}>
212
+ <Flex direction="col" gap="xs">
213
+ <Text size="sm" tone="muted">
214
+ scrollbar=&quot;auto&quot;(既定)— macOS では静止時にバーが出ない
215
+ </Text>
216
+ <Card variant="outline" className="w-full">
217
+ <CardContent flush>
218
+ <ScrollArea className="h-40">
219
+ <CardContent>
220
+ <Flex direction="col" gap="xs">
221
+ {entries.map((e) => (
222
+ <div key={`auto-${e}`} className="text-sm tabular-nums">
223
+ {e}
224
+ </div>
225
+ ))}
226
+ </Flex>
227
+ </CardContent>
228
+ </ScrollArea>
229
+ </CardContent>
230
+ </Card>
231
+ </Flex>
232
+
233
+ <Flex direction="col" gap="xs">
234
+ <Text size="sm" tone="muted">
235
+ scrollbar=&quot;always&quot; — レイアウトを占める古典的なバー
236
+ </Text>
237
+ <Card variant="outline" className="w-full">
238
+ <CardContent flush>
239
+ <ScrollArea className="h-40" scrollbar="always">
240
+ <CardContent>
241
+ <Flex direction="col" gap="xs">
242
+ {entries.map((e) => (
243
+ <div key={`always-${e}`} className="text-sm tabular-nums">
244
+ {e}
245
+ </div>
246
+ ))}
247
+ </Flex>
248
+ </CardContent>
249
+ </ScrollArea>
250
+ </CardContent>
251
+ </Card>
252
+ </Flex>
253
+ </ResponsiveGrid>
254
+ </CardContent>
255
+ </Card>
256
+
195
257
  <Card>
196
258
  <CardHeader>
197
259
  <CardTitle level={2}>固定高さのリスト(縦スクロール)</CardTitle>
@@ -200,9 +262,14 @@ export default function Demo() {
200
262
  </CardDescription>
201
263
  </CardHeader>
202
264
  <CardContent>
203
- <Card variant="outline" className="h-56 w-full">
265
+ {/* THE HEIGHT GOES ON THE SCROLLAREA, not on an ancestor. It was on the outer Card,
266
+ and neither CardContent nor ScrollArea inherits a height from it — so the
267
+ ScrollArea grew to its content, `scrollHeight === clientHeight`, and the demo for
268
+ a scrolling component did not scroll. Measured on the published site before this
269
+ change. The page header says this rule outright; the example broke it. */}
270
+ <Card variant="outline" className="w-full">
204
271
  <CardContent flush>
205
- <ScrollArea>
272
+ <ScrollArea className="h-56">
206
273
  <CardContent>
207
274
  <Flex direction="col" gap="xs">
208
275
  {entries.map((e) => (
@@ -296,9 +363,12 @@ export default function Demo() {
296
363
  </CardDescription>
297
364
  </CardHeader>
298
365
  <CardContent>
299
- <Card variant="outline" className="h-56 w-full">
366
+ {/* Same h-56 as above, DELIBERATELY not overflowing: `shortEntries` fits, so no bar
367
+ appears. This is the control case — it is only meaningful next to one that does
368
+ overflow, which is why the demo above had to be fixed first. */}
369
+ <Card variant="outline" className="w-full">
300
370
  <CardContent flush>
301
- <ScrollArea>
371
+ <ScrollArea className="h-56">
302
372
  <CardContent>
303
373
  <Flex direction="col" gap="xs">
304
374
  {shortEntries.map((e) => (