@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.
- package/dist/components/data-display/data-table.d.ts +10 -2
- package/dist/components/data-display/data-table.js +12 -5
- package/dist/components/data-display/scroll-area.js +16 -2
- package/dist/components/data-display/service-launcher-card.d.ts +25 -0
- package/dist/components/data-display/table.d.ts +38 -1
- package/dist/components/data-display/table.js +57 -39
- package/dist/components/data-entry/field.d.ts +1 -1
- package/dist/components/data-entry/field.js +35 -4
- package/dist/components/data-entry/form-field.js +29 -12
- package/dist/components/data-entry/input.d.ts +1 -1
- package/dist/components/layout/index.d.ts +1 -1
- package/dist/components/layout/nav-list.d.ts +9 -1
- package/dist/components/layout/nav-list.js +22 -11
- package/dist/components/layout/sidebar.d.ts +16 -2
- package/dist/components/layout/sidebar.js +1 -0
- package/dist/components/navigation/app-setting-picker.js +20 -3
- package/dist/components/ui/password-input.d.ts +1 -1
- package/dist/components/ui/table.js +1 -0
- package/dist/contracts/measurement.json +1 -1
- package/dist/i18n/messages/en.json +5 -1
- package/dist/i18n/messages/ja.json +5 -1
- package/dist/i18n/messages/vi.json +5 -1
- package/dist/lib/control-styles.d.ts +18 -3
- package/dist/lib/control-styles.js +1 -1
- package/dist/lib/hooks.d.ts +23 -0
- package/dist/lib/hooks.js +27 -0
- package/dist/props/components/data-display.prop.d.ts +14 -0
- package/dist/props/components/data-entry.prop.d.ts +36 -2
- package/dist/props/components/layout.prop.d.ts +16 -5
- package/dist/props/registry.d.ts +2 -2
- package/dist/props/registry.js +10 -2
- package/dist/styles/control.css +12 -0
- package/dist/styles/data-display-layout.css +25 -2
- package/dist/styles/dialog-layout.css +12 -0
- package/dist/styles/form-layout.css +22 -0
- package/dist/styles/layout.css +1 -2
- package/dist/styles/navigation-layout.css +18 -19
- package/dist/tokens/components/data-display.css +2 -1
- package/dist/tokens/components/feedback.css +2 -0
- package/dist/tokens/components/form.css +2 -0
- package/dist/tokens/components/navigation.css +2 -0
- package/docs/COMPOSITION-VS-COMPONENT.md +3 -0
- package/docs/DESIGN-AUTHORITY.md +25 -5
- package/docs/FRAME-COVERAGE-REPORT.md +1 -1
- package/docs/data-display/collapsible.tsx +5 -5
- package/docs/data-display/descriptions.tsx +188 -109
- package/docs/data-display/legend.tsx +17 -4
- package/docs/data-display/scroll-area.tsx +106 -5
- package/docs/data-display/service-launcher-card.tsx +275 -115
- package/docs/data-display/stat-card.tsx +319 -64
- package/docs/data-entry/form.tsx +700 -6
- package/docs/data-entry/input.tsx +663 -53
- package/docs/data-entry/radio-group.tsx +216 -2
- package/docs/data-entry/switch.tsx +210 -4
- package/docs/data-entry/upload-crop-dialog.tsx +24 -25
- package/docs/layout/nav-list.tsx +556 -35
- package/package.json +9 -7
- package/scripts/visual-audit.mjs +29 -1
|
@@ -187,6 +187,8 @@
|
|
|
187
187
|
--app-setting-picker-density-width: 10rem;
|
|
188
188
|
--app-setting-picker-font-size-width: 9rem;
|
|
189
189
|
|
|
190
|
+
--app-setting-picker-trigger-width: auto;
|
|
191
|
+
|
|
190
192
|
--app-setting-picker-width-breakpoint: 40rem;
|
|
191
193
|
--app-setting-picker-bar-border-width: 0;
|
|
192
194
|
--app-setting-picker-bar-shadow: none;
|
|
@@ -77,6 +77,7 @@ new UI need
|
|
|
77
77
|
| `Select` (incl. search/async) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | **Framework component** |
|
|
78
78
|
| `DataTable`, `Dialog`, `Calendar`, `Switch`, `Combobox` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | **Framework component** |
|
|
79
79
|
| `StatCard` (+ `icon`) | ✅ | ➖ | ✅ | ✅ | ✅ | ✅ | ✅ | **Framework component** (a reusable KPI tile with a stable API + tokens) |
|
|
80
|
+
| `ServiceLauncherCard` | ➖ | ❌ | ❌ | ✅ | ✅ | ➖ | ➖ | **Composition by the test — RETAINED as a recorded exception** (gh#814) |
|
|
80
81
|
| Marketing **Hero** | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | **Composition** — section, static, composable, brand-specific |
|
|
81
82
|
| **Navbar** / **Footer** | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | **Composition** — layout of `Text`/`Button`/`Flex` |
|
|
82
83
|
| **PricingTable** / feature grid | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | **Composition** — `ResponsiveGrid` + `Card` |
|
|
@@ -85,6 +86,8 @@ new UI need
|
|
|
85
86
|
|
|
86
87
|
`✅ pass · ❌ fail · ➖ borderline`. **StatCard** is the instructive borderline: C2 is weak (it owns little behavior), but it is a universal KPI tile with a controlled API, fully tokenized, broadly reused — so it earns its place. A **Hero** fails six of seven; it is unambiguously a composition.
|
|
87
88
|
|
|
89
|
+
**ServiceLauncherCard is the ONE recorded exception, and it is recorded so that it stays one.** It shipped before the test was run against it, and when the test was run it came back with two hard FAILs: **C2** — no state, no keyboard handling, no focus management, its only ARIA three static attributes — and **C3** — its own imports are `Card` + `CardContent` + `Badge` + a Lucide glyph, so "could I build this right now from primitives?" is yes. By §2 that makes it a composition pattern. It is kept anyway because `src/components/layout/app-launcher.tsx` consumes it: it is an internal building block of a component that **does** pass, so the question was never "should it exist" but "should it be PUBLIC", and removing a public export is breaking. Keeping it public was the cheaper call and the ledger lives on gh#814 and at the top of `src/components/data-display/service-launcher-card.tsx`. **Consumers should compose `Card` + `Badge` for a service tile** — reach for `ServiceLauncherCard` only to match `AppLauncher`'s own tiles — and this row is not precedent for adding another static tile to `src/components/`.
|
|
90
|
+
|
|
88
91
|
---
|
|
89
92
|
|
|
90
93
|
## 4. How to build a composition pattern correctly
|
package/docs/DESIGN-AUTHORITY.md
CHANGED
|
@@ -648,11 +648,31 @@ because removing it would break the contents anchor.
|
|
|
648
648
|
|
|
649
649
|
**Every other focusable non-interactive element in this library is a genuinely scrollable region**
|
|
650
650
|
— `.app-main`, `.ui-mobile-shell-main`, `.ui-timeline-grid`, `.ui-code-block` when it overflows,
|
|
651
|
-
MasterDetail's bounded master, the DataTable and Table scroll containers
|
|
652
|
-
BranchScopePicker list. Each carries `tabIndex={0}` for axe
|
|
653
|
-
stay reachable, so each keeps BOTH halves rather than
|
|
654
|
-
ring (`--region-focus-ring-width`, off by default) now
|
|
655
|
-
service that opts it in still cannot paint while the
|
|
651
|
+
MasterDetail's bounded master, the DataTable and Table scroll containers when they overflow,
|
|
652
|
+
ScrollArea, and the BranchScopePicker list. Each carries `tabIndex={0}` for axe
|
|
653
|
+
`scrollable-region-focusable` and must stay reachable, so each keeps BOTH halves rather than
|
|
654
|
+
becoming focusable-but-unpainted. The region ring (`--region-focus-ring-width`, off by default) now
|
|
655
|
+
also multiplies by `--focus-outline`, so a service that opts it in still cannot paint while the
|
|
656
|
+
library-wide switch is off.
|
|
657
|
+
|
|
658
|
+
### A focusable scroll region is ROLED and NAMED, and only exists while it scrolls (gh#817)
|
|
659
|
+
|
|
660
|
+
Reaching the overflow is half the contract; knowing what you reached is the other half. A stop with
|
|
661
|
+
no role and no accessible name announces nothing at all, which is why `godx-jp/id` found `Table`'s
|
|
662
|
+
wrapper sitting at tab stop 27 as a bare `<div tabindex="0">`. So the Table and DataTable scroll
|
|
663
|
+
containers carry `role="group"` plus a name that defaults to the localized `dataTable.scrollRegion`
|
|
664
|
+
— a consumer is never forced to invent one per table, and `label` overrides it per instance.
|
|
665
|
+
|
|
666
|
+
`group`, not `region`: a NAMED `region` is a landmark, so a page with three tables would ship three
|
|
667
|
+
identically-named landmarks and fail axe `landmark-unique`. That collision is the reason the role
|
|
668
|
+
was left off in the first place; `group` is announced, takes a name, and is not a landmark.
|
|
669
|
+
|
|
670
|
+
And all three attributes are withheld until the box provably overflows (`useScrollsHorizontally`,
|
|
671
|
+
`src/lib/hooks.ts`) — a focus stop that scrolls nothing is noise. The measurement may only ever
|
|
672
|
+
REMOVE the stop: an unlaid-out box reports `clientWidth === 0` (SSR, jsdom, a `display:none`
|
|
673
|
+
ancestor), and reading that as "nothing overflows" would strand the overflow from every keyboard
|
|
674
|
+
user, a worse failure than the extra stop. Gated by
|
|
675
|
+
`src/components/data-display/__tests__/table-scroll-region-a11y-817.test.tsx`.
|
|
656
676
|
|
|
657
677
|
## How a decision gets made from here
|
|
658
678
|
|
|
@@ -173,7 +173,7 @@ Legend: ✓ covered · N/A reasoned skip · · UNTESTED (blank cell = UNTESTED).
|
|
|
173
173
|
| Carousel | ✓ | N/A | N/A | · | · | · | · | · | · | · |
|
|
174
174
|
| AppSettingPicker | ✓ | N/A | · | · | · | · | · | · | · | · |
|
|
175
175
|
| AppSettingToggle | ✓ | N/A | · | · | · | · | · | · | · | · |
|
|
176
|
-
| Field | ✓ | N/A |
|
|
176
|
+
| Field | ✓ | N/A | · | N/A | · | · | · | · | · | · |
|
|
177
177
|
| LineChart | ✓ | ✓ | N/A | N/A | · | · | · | · | · | · |
|
|
178
178
|
| BarChart | ✓ | ✓ | N/A | N/A | · | · | · | · | · | · |
|
|
179
179
|
| CompactBarTrend | ✓ | ✓ | N/A | N/A | · | · | · | · | · | · |
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from "@godxjp/ui/data-display";
|
|
11
11
|
import { Button, Text } from "@godxjp/ui/general";
|
|
12
12
|
import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
13
|
-
import {
|
|
13
|
+
import { ChevronDown } from "lucide-react";
|
|
14
14
|
import { useState } from "react";
|
|
15
15
|
|
|
16
16
|
/**
|
|
@@ -43,7 +43,7 @@ export default function Demo() {
|
|
|
43
43
|
aria-label="開閉"
|
|
44
44
|
className="transition-transform data-[state=open]:rotate-180"
|
|
45
45
|
>
|
|
46
|
-
<
|
|
46
|
+
<ChevronDown className="ui-disclosure-chevron" />
|
|
47
47
|
</Button>
|
|
48
48
|
</CollapsibleTrigger>
|
|
49
49
|
</Flex>
|
|
@@ -74,7 +74,7 @@ export default function Demo() {
|
|
|
74
74
|
aria-label="開閉"
|
|
75
75
|
className="transition-transform data-[state=open]:rotate-180"
|
|
76
76
|
>
|
|
77
|
-
<
|
|
77
|
+
<ChevronDown className="ui-disclosure-chevron" />
|
|
78
78
|
</Button>
|
|
79
79
|
</CollapsibleTrigger>
|
|
80
80
|
</Flex>
|
|
@@ -112,7 +112,7 @@ export default function Demo() {
|
|
|
112
112
|
aria-label="開閉"
|
|
113
113
|
className="transition-transform data-[state=open]:rotate-180"
|
|
114
114
|
>
|
|
115
|
-
<
|
|
115
|
+
<ChevronDown className="ui-disclosure-chevron" />
|
|
116
116
|
</Button>
|
|
117
117
|
</CollapsibleTrigger>
|
|
118
118
|
</Flex>
|
|
@@ -144,7 +144,7 @@ export default function Demo() {
|
|
|
144
144
|
aria-label="開閉"
|
|
145
145
|
className="transition-transform data-[state=open]:rotate-180"
|
|
146
146
|
>
|
|
147
|
-
<
|
|
147
|
+
<ChevronDown className="ui-disclosure-chevron" />
|
|
148
148
|
</Button>
|
|
149
149
|
</CollapsibleTrigger>
|
|
150
150
|
</Flex>
|
|
@@ -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
|
|
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 —
|
|
16
|
-
*
|
|
17
|
-
*
|
|
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
|
|
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}
|
|
42
|
+
<CardTitle level={2}>1 · columns × bordered × layout — the three axes</CardTitle>
|
|
28
43
|
<CardDescription>
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
<
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
|
|
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="
|
|
55
|
-
|
|
56
|
-
|
|
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}
|
|
129
|
+
<CardTitle level={2}>3 · the value is not a string</CardTitle>
|
|
66
130
|
<CardDescription>
|
|
67
|
-
|
|
68
|
-
|
|
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}
|
|
73
|
-
<Descriptions.Item label="
|
|
74
|
-
|
|
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
|
-
<
|
|
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
|
-
<
|
|
82
|
-
|
|
83
|
-
|
|
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}
|
|
93
|
-
<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="filled"` 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={
|
|
97
|
-
<Descriptions.Item label="
|
|
98
|
-
<Descriptions.Item label="
|
|
99
|
-
|
|
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
|
-
|
|
195
|
+
<Descriptions.Item label="備考" span="filled">
|
|
196
|
+
検収は毎月第2・第4火曜のみ。祝日と重なる場合は翌営業日に振替。先方の受入窓口は
|
|
197
|
+
資材部・資材管理課(内線
|
|
198
|
+
4821)。2026年4月以降は電子取引のみとなるため、紙の納品書は不可。
|
|
103
199
|
</Descriptions.Item>
|
|
104
|
-
<Descriptions.Item label="
|
|
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}
|
|
208
|
+
<CardTitle level={2}>5 · the cases that break a label/value grid</CardTitle>
|
|
113
209
|
<CardDescription>
|
|
114
|
-
|
|
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="
|
|
120
|
-
|
|
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="
|
|
123
|
-
|
|
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
|
-
<
|
|
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="
|
|
135
|
-
<Descriptions.Item label="
|
|
136
|
-
|
|
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}
|
|
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
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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><div></code> や
|
|
246
|
+
<code><dt>/<dd></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
|
-
|
|
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
|
-
</
|
|
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
|
-
|
|
124
|
+
aria-label を渡すと、その凡例が「何のキーか」を読み上げます。項目は list / listitem
|
|
125
|
+
として並びます。
|
|
113
126
|
</CardDescription>
|
|
114
127
|
</CardHeader>
|
|
115
128
|
<CardContent>
|