@godxjp/ui 22.0.0 → 23.0.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/README.md +4 -4
- package/dist/components/data-display/scroll-area.d.ts +24 -4
- package/dist/components/data-display/scroll-area.js +34 -72
- package/dist/components/data-entry/cascader.js +8 -6
- package/dist/components/data-entry/checkbox.js +2 -0
- package/dist/components/data-entry/choice-hit-target.d.ts +24 -0
- package/dist/components/data-entry/choice-hit-target.js +12 -0
- package/dist/components/data-entry/control-surface.d.ts +8 -0
- package/dist/components/data-entry/control-surface.js +10 -1
- package/dist/components/data-entry/form-field.js +3 -2
- package/dist/components/data-entry/radio.js +3 -2
- package/dist/components/data-entry/search-select.js +225 -95
- package/dist/components/data-entry/select.d.ts +76 -14
- package/dist/components/data-entry/select.js +495 -163
- package/dist/components/data-entry/slider.d.ts +3 -11
- package/dist/components/data-entry/slider.js +582 -93
- package/dist/components/data-entry/switch.js +2 -0
- package/dist/components/navigation/dropdown-menu.d.ts +11 -3
- package/dist/components/navigation/dropdown-menu.js +190 -15
- package/dist/components/navigation/index.d.ts +0 -3
- package/dist/components/navigation/index.js +0 -78
- package/dist/components/ui/index.d.ts +0 -3
- package/dist/components/ui/index.js +0 -3
- package/dist/components/ui/input-otp.d.ts +1 -1
- package/dist/components/ui/segmented.js +3 -1
- package/dist/components/ui/tag-input.js +3 -5
- package/dist/lib/select-options.d.ts +21 -0
- package/dist/lib/select-options.js +46 -0
- package/dist/props/components/data-display.prop.d.ts +9 -6
- package/dist/props/components/data-entry.prop.d.ts +323 -30
- package/dist/props/components/index.d.ts +1 -1
- package/dist/props/components/navigation.prop.d.ts +17 -0
- package/dist/props/registry.d.ts +63 -0
- package/dist/props/registry.js +69 -0
- package/dist/styles/control.css +205 -23
- package/dist/styles/data-display-layout.css +18 -10
- package/dist/styles/focus-ring.css +2 -2
- package/dist/styles/fonts.css +88 -4
- package/dist/styles/navigation-layout.css +11 -236
- package/dist/styles/shell-layout.css +144 -139
- package/dist/styles/table-layout.css +7 -3
- package/dist/tokens/components/control.css +4 -0
- package/dist/tokens/components/data-display.css +0 -5
- package/dist/tokens/components/navigation.css +3 -5
- package/dist/tokens/components/scroll-area.css +7 -0
- package/docs/CUSTOMER-THEMING.md +7 -1
- package/docs/FRAME-COVERAGE-REPORT.md +4 -7
- package/docs/data-display/data-table/index.tsx +27 -1
- package/docs/data-display/popover.tsx +4 -6
- package/docs/data-display/scroll-area.tsx +51 -45
- package/docs/data-entry/date-picker.tsx +2 -3
- package/docs/data-entry/input-otp.tsx +5 -2
- package/docs/data-entry/segmented.tsx +40 -1
- package/docs/data-entry/select-matrix.tsx +1 -2
- package/docs/data-entry/select.tsx +108 -3
- package/docs/data-entry/slider.tsx +125 -47
- package/docs/feedback/dialog.tsx +1 -2
- package/docs/feedback/sheet.tsx +1 -2
- package/docs/layout/app-shell-states.tsx +143 -0
- package/docs/navigation/dropdown-menu.tsx +75 -4
- package/docs/roadmap/parity-audit-data-entry.md +44 -33
- package/docs/roadmap/parity-audit-layout-navigation-general.md +304 -310
- package/docs/roadmap/parity-backlog.md +2 -3
- package/package.json +20 -44
- package/scripts/ui-audit.mjs +1 -1
- package/scripts/visual-audit-rules.mjs +0 -7
- package/scripts/visual-audit.mjs +6 -27
- package/dist/components/navigation/context-menu.d.ts +0 -21
- package/dist/components/navigation/context-menu.js +0 -149
- package/dist/components/navigation/menubar.d.ts +0 -28
- package/dist/components/navigation/menubar.js +0 -136
- package/dist/components/navigation/navigation-menu.d.ts +0 -10
- package/dist/components/navigation/navigation-menu.js +0 -91
- package/dist/components/ui/context-menu.d.ts +0 -1
- package/dist/components/ui/context-menu.js +0 -2
- package/dist/components/ui/menubar.d.ts +0 -1
- package/dist/components/ui/menubar.js +0 -2
- package/dist/components/ui/navigation-menu.d.ts +0 -1
- package/dist/components/ui/navigation-menu.js +0 -2
- package/docs/FRAME-A11Y-CI.md +0 -349
- package/docs/navigation/context-menu.tsx +0 -128
- package/docs/navigation/menubar.tsx +0 -141
- package/docs/navigation/navigation-menu.tsx +0 -158
|
@@ -93,11 +93,6 @@
|
|
|
93
93
|
--qr-code-size-md: 10rem;
|
|
94
94
|
--qr-code-size-lg: 12.5rem;
|
|
95
95
|
|
|
96
|
-
--scroll-area-bar-size: 0.625rem;
|
|
97
|
-
|
|
98
|
-
--scroll-area-bar-padding: 1px;
|
|
99
|
-
--scroll-area-thumb-radius: var(--radius-pill);
|
|
100
|
-
|
|
101
96
|
--timeline-grid-hour-height: 2.5rem;
|
|
102
97
|
--timeline-grid-axis-width: 3.25rem;
|
|
103
98
|
--timeline-grid-column-min-width: 6rem;
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
--breadcrumb-font-size: var(--font-size-xs);
|
|
38
38
|
|
|
39
39
|
--breadcrumb-menu-trigger-gap: var(--space-inline-xs);
|
|
40
|
-
--
|
|
40
|
+
--menu-shortcut-font-size: var(--font-size-xs);
|
|
41
41
|
--tabs-list-max-inline-size: 100%;
|
|
42
42
|
--tabs-list-overflow: auto;
|
|
43
43
|
|
|
@@ -89,8 +89,8 @@
|
|
|
89
89
|
--tabs-tab-remove-icon-size: var(--icon-size-xs);
|
|
90
90
|
--tabs-tab-remove-space-inline-end: var(--space-1);
|
|
91
91
|
|
|
92
|
-
--
|
|
93
|
-
--
|
|
92
|
+
--menu-item-hover-background: initial;
|
|
93
|
+
--menu-item-hover-foreground: initial;
|
|
94
94
|
|
|
95
95
|
--filter-bar-sticky-offset: 0px;
|
|
96
96
|
|
|
@@ -128,8 +128,6 @@
|
|
|
128
128
|
--menu-separator-space-block: var(--space-1);
|
|
129
129
|
--menu-separator-space-inline: calc(var(--space-1) * -1);
|
|
130
130
|
|
|
131
|
-
--navigation-menu-trigger-icon-size: var(--icon-size-sm);
|
|
132
|
-
|
|
133
131
|
--steps-dot-size: 0.625rem;
|
|
134
132
|
--steps-dot-process-ring-width: var(--stroke-xl);
|
|
135
133
|
--steps-marker-border-width: var(--stroke-md);
|
package/docs/CUSTOMER-THEMING.md
CHANGED
|
@@ -56,7 +56,13 @@ overwrites `--font-sans-base` (and `--font-sans-vi`) with the bundled stack —
|
|
|
56
56
|
Noto Sans JP + Montserrat; v18.12.0–18.12.19 bundled M PLUS 2 + Noto Sans JP;
|
|
57
57
|
v18.12.20+ bundles Noto Sans JP + M PLUS 2 (product override, direct
|
|
58
58
|
instruction). If your design spec named an earlier bundle's faces, set the
|
|
59
|
-
tokens yourself rather than relying on the bundle.)
|
|
59
|
+
tokens yourself rather than relying on the bundle.) Second in that stack is
|
|
60
|
+
`"Noto Sans JP Fallback"`: local faces (Arial / Liberation Sans for Latin, the
|
|
61
|
+
platform's gothic face for Japanese) with `size-adjust` and ascent/descent
|
|
62
|
+
overrides tuned to Noto Sans JP. The bundled faces are `font-display: swap`, so
|
|
63
|
+
a cold visit paints in this fallback first; because it occupies the same line
|
|
64
|
+
boxes and nearly the same advances, the swap does not reflow the page (#475).
|
|
65
|
+
If you restate the stack yourself, keep it directly after "Noto Sans JP". Headings read
|
|
60
66
|
`--font-family-display` and body reads `--font-family-body`, both defaulting to
|
|
61
67
|
`--font-family-sans` — override them for a dual-font (display + body) brand.
|
|
62
68
|
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
> Generated by `scripts/frame-coverage.mjs` (issue #163). Do not edit by hand — run `pnpm check:frame-coverage`.
|
|
4
4
|
> Standard: [FRAME-COVERAGE-STANDARD.md](./FRAME-COVERAGE-STANDARD.md). A missing dimension is **UNTESTED**, never a pass.
|
|
5
5
|
|
|
6
|
-
- Public components: **
|
|
7
|
-
- With ≥1 frame: **
|
|
6
|
+
- Public components: **135**
|
|
7
|
+
- With ≥1 frame: **130** · zero-frame: **5**
|
|
8
8
|
- Fully covered (every contract axis declared): **0**
|
|
9
9
|
|
|
10
10
|
## UNTESTED — no `/frame/**` route
|
|
@@ -74,7 +74,7 @@ Legend: ✓ covered · N/A reasoned skip · · UNTESTED (blank cell = UNTESTED).
|
|
|
74
74
|
| Input | ✓ | ✓ | · | · | · | · | · | · | · | · |
|
|
75
75
|
| NumberInput | ✓ | ✓ | · | · | · | · | · | · | · | · |
|
|
76
76
|
| SearchInput | ✓ | ✓ | · | · | · | · | · | · | · | · |
|
|
77
|
-
| Select | ✓ |
|
|
77
|
+
| Select | ✓ | · | · | · | · | · | · | · | · | · |
|
|
78
78
|
| Switch | ✓ | ✓ | · | · | · | · | · | · | · | · |
|
|
79
79
|
| Textarea | ✓ | ✓ | · | · | · | · | · | · | · | · |
|
|
80
80
|
| Label | ✓ | N/A | N/A | N/A | · | · | · | · | · | · |
|
|
@@ -91,7 +91,7 @@ Legend: ✓ covered · N/A reasoned skip · · UNTESTED (blank cell = UNTESTED).
|
|
|
91
91
|
| Toaster | ✓ | N/A | N/A | N/A | · | · | · | · | · | · |
|
|
92
92
|
| Tabs | ✓ | ✓ | N/A | · | · | · | · | · | · | · |
|
|
93
93
|
| Pagination | ✓ | · | · | · | · | · | · | · | · | · |
|
|
94
|
-
| DropdownMenu | ✓ | N/A |
|
|
94
|
+
| DropdownMenu | ✓ | N/A | · | · | · | · | · | · | · | · |
|
|
95
95
|
| Steps | ✓ | ✓ | N/A | · | · | · | · | · | · | · |
|
|
96
96
|
| Toolbar | ✓ | N/A | · | N/A | · | · | · | · | · | · |
|
|
97
97
|
| AppProvider | ✓ | · | · | · | · | · | · | · | · | · |
|
|
@@ -128,9 +128,6 @@ Legend: ✓ covered · N/A reasoned skip · · UNTESTED (blank cell = UNTESTED).
|
|
|
128
128
|
| Rating | ✓ | N/A | · | · | · | · | · | · | · | · |
|
|
129
129
|
| Segmented | ✓ | ✓ | · | · | · | · | · | · | · | · |
|
|
130
130
|
| TagInput | ✓ | ✓ | · | · | · | · | · | · | · | · |
|
|
131
|
-
| ContextMenu | ✓ | N/A | N/A | · | · | · | · | · | · | · |
|
|
132
|
-
| Menubar | ✓ | N/A | N/A | · | · | · | · | · | · | · |
|
|
133
|
-
| NavigationMenu | ✓ | N/A | N/A | · | · | · | · | · | · | · |
|
|
134
131
|
| ResizablePanel | ✓ | N/A | · | N/A | · | · | · | · | · | · |
|
|
135
132
|
| Carousel | ✓ | N/A | N/A | · | · | · | · | · | · | · |
|
|
136
133
|
| AppSettingPicker | ✓ | N/A | · | · | · | · | · | · | · | · |
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useMemo, useState } from "react";
|
|
2
2
|
|
|
3
3
|
import { AppProvider } from "@godxjp/ui/app";
|
|
4
|
-
import { Badge, DataTable, type ColumnDef } from "@godxjp/ui/data-display";
|
|
4
|
+
import { Badge, Card, CardContent, DataTable, type ColumnDef } from "@godxjp/ui/data-display";
|
|
5
5
|
import { Button, Text } from "@godxjp/ui/general";
|
|
6
6
|
import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
7
7
|
import {
|
|
@@ -93,6 +93,16 @@ const columns: ColumnDef<Invoice>[] = [
|
|
|
93
93
|
},
|
|
94
94
|
];
|
|
95
95
|
|
|
96
|
+
/* Five 240px columns: wider than the frame at every viewport the gates sweep, and wide for a
|
|
97
|
+
* reason no font can change — the width is declared, so the overflow is deterministic in CI. */
|
|
98
|
+
const wideColumns: ColumnDef<Invoice>[] = [
|
|
99
|
+
{ key: "id", header: "請求書番号", width: "240px" },
|
|
100
|
+
{ key: "partner", header: "取引先", width: "240px" },
|
|
101
|
+
{ key: "amount", header: "金額", align: "right", width: "240px" },
|
|
102
|
+
{ key: "status", header: "状態", width: "240px" },
|
|
103
|
+
{ key: "date", header: "期限日", width: "240px" },
|
|
104
|
+
];
|
|
105
|
+
|
|
96
106
|
export default function Demo() {
|
|
97
107
|
const [selected, setSelected] = useState<Set<string>>(new Set(["INV-0311"]));
|
|
98
108
|
const [sort, setSort] = useState<SortStateProp | undefined>({
|
|
@@ -117,6 +127,22 @@ export default function Demo() {
|
|
|
117
127
|
subtitle="sortable · selectable · bulk actions · row actions · loading · clickable rows · empty state"
|
|
118
128
|
>
|
|
119
129
|
<Flex direction="col" gap="lg">
|
|
130
|
+
{/* A table WIDER than its frame, inside a flush Card — the shape a list page uses. It must
|
|
131
|
+
scroll inside its own box with the fade at the inline end, never cut its last columns
|
|
132
|
+
(WCAG 1.4.10). `check:data-table-overflow` measures this section. */}
|
|
133
|
+
<Flex direction="col" gap="sm" id="wide-overflow" className="max-w-3xl">
|
|
134
|
+
<Text weight="medium">枠より広い表(横スクロール · 列を切らない)</Text>
|
|
135
|
+
<Card>
|
|
136
|
+
<CardContent flush>
|
|
137
|
+
<DataTable
|
|
138
|
+
data={invoices}
|
|
139
|
+
columns={wideColumns}
|
|
140
|
+
getRowId={(row) => row.id}
|
|
141
|
+
selectable
|
|
142
|
+
/>
|
|
143
|
+
</CardContent>
|
|
144
|
+
</Card>
|
|
145
|
+
</Flex>
|
|
120
146
|
<Flex direction="col" gap="sm" id="text-action-width">
|
|
121
147
|
<Text weight="medium">日本語の行アクション</Text>
|
|
122
148
|
<DataTable
|
|
@@ -135,10 +135,7 @@ export default function Demo() {
|
|
|
135
135
|
<Flex direction="row" wrap gap="sm">
|
|
136
136
|
<Popover>
|
|
137
137
|
<PopoverTrigger asChild>
|
|
138
|
-
|
|
139
|
-
<Button data-axe-open variant="outline">
|
|
140
|
-
side=top
|
|
141
|
-
</Button>
|
|
138
|
+
<Button variant="outline">side=top</Button>
|
|
142
139
|
</PopoverTrigger>
|
|
143
140
|
<PopoverContent side="top" aria-label="上側の配置例">
|
|
144
141
|
<PopoverDescription>上に開きます。</PopoverDescription>
|
|
@@ -215,8 +212,9 @@ export default function Demo() {
|
|
|
215
212
|
<CardDescription>
|
|
216
213
|
既定の panel は --popover-width(18rem)。auto は中身に測らせます — 自前の幅を持つもの
|
|
217
214
|
(Calendar、チャート、固定幅のプレビュー)はこれ以外に正解がありません。trigger
|
|
218
|
-
はアンカーに合わせます。className に w-*
|
|
219
|
-
retune できません。flush が padding
|
|
215
|
+
はアンカーに合わせます。className に w-*
|
|
216
|
+
を書くのは呼び出し側の定数で、どのテーマからも retune できません。flush が padding
|
|
217
|
+
側で避けているのと同じ話です。
|
|
220
218
|
</CardDescription>
|
|
221
219
|
</CardHeader>
|
|
222
220
|
<CardContent>
|
|
@@ -14,10 +14,10 @@ import { Button, Text } from "@godxjp/ui/general";
|
|
|
14
14
|
import { Flex, PageContainer, ResponsiveGrid } from "@godxjp/ui/layout";
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
* ScrollArea —
|
|
18
|
-
* (vertical) or width (horizontal)
|
|
19
|
-
* `
|
|
20
|
-
*
|
|
17
|
+
* ScrollArea — a native scrolling box. ALWAYS give it an explicit height/max-height
|
|
18
|
+
* (vertical) or width (horizontal), or nothing ever overflows and no scrollbar appears.
|
|
19
|
+
* `orientation` decides which axes may scroll; the browser draws the bar, styled from
|
|
20
|
+
* the --scroll-area-* tokens. Composed only from real @godxjp/ui components.
|
|
21
21
|
*/
|
|
22
22
|
const entries = Array.from(
|
|
23
23
|
{ length: 18 },
|
|
@@ -97,7 +97,7 @@ export default function Demo() {
|
|
|
97
97
|
return (
|
|
98
98
|
<PageContainer
|
|
99
99
|
title="ScrollArea"
|
|
100
|
-
subtitle="
|
|
100
|
+
subtitle="Native scrolling, token-styled scrollbar · needs an explicit height"
|
|
101
101
|
>
|
|
102
102
|
<Flex direction="col" gap="lg">
|
|
103
103
|
<Card>
|
|
@@ -115,7 +115,6 @@ export default function Demo() {
|
|
|
115
115
|
anchor="bottom"
|
|
116
116
|
viewportRef={streamViewport}
|
|
117
117
|
onAnchoredChange={setAnchored}
|
|
118
|
-
type="always"
|
|
119
118
|
>
|
|
120
119
|
<CardContent>
|
|
121
120
|
<Flex direction="col">
|
|
@@ -173,7 +172,7 @@ export default function Demo() {
|
|
|
173
172
|
<CardContent>
|
|
174
173
|
<Card variant="outline" className="h-40 w-full">
|
|
175
174
|
<CardContent flush>
|
|
176
|
-
<ScrollArea anchor="bottom" anchorOffset={0}
|
|
175
|
+
<ScrollArea anchor="bottom" anchorOffset={0}>
|
|
177
176
|
<CardContent>
|
|
178
177
|
<Flex direction="col" gap="xs">
|
|
179
178
|
{entries.map((e) => (
|
|
@@ -215,40 +214,13 @@ export default function Demo() {
|
|
|
215
214
|
</CardContent>
|
|
216
215
|
</Card>
|
|
217
216
|
|
|
218
|
-
<Card>
|
|
219
|
-
<CardHeader>
|
|
220
|
-
<CardTitle level={2}>type="always"(バーを常時表示)</CardTitle>
|
|
221
|
-
<CardDescription>
|
|
222
|
-
既定の hover はホバー時のみバーを表示します。always
|
|
223
|
-
は内容が溢れる限りバーを常に表示します。
|
|
224
|
-
</CardDescription>
|
|
225
|
-
</CardHeader>
|
|
226
|
-
<CardContent>
|
|
227
|
-
<Card variant="outline" className="h-56 w-full">
|
|
228
|
-
<CardContent flush>
|
|
229
|
-
<ScrollArea type="always">
|
|
230
|
-
<CardContent>
|
|
231
|
-
<Flex direction="col" gap="xs">
|
|
232
|
-
{entries.map((e) => (
|
|
233
|
-
<div key={e} className="text-sm tabular-nums">
|
|
234
|
-
{e}
|
|
235
|
-
</div>
|
|
236
|
-
))}
|
|
237
|
-
</Flex>
|
|
238
|
-
</CardContent>
|
|
239
|
-
</ScrollArea>
|
|
240
|
-
</CardContent>
|
|
241
|
-
</Card>
|
|
242
|
-
</CardContent>
|
|
243
|
-
</Card>
|
|
244
|
-
|
|
245
217
|
<Card>
|
|
246
218
|
<CardHeader>
|
|
247
219
|
<CardTitle level={2}>ScrollArea</CardTitle>
|
|
248
220
|
<CardDescription>orientation="horizontal"</CardDescription>
|
|
249
221
|
</CardHeader>
|
|
250
222
|
<CardContent>
|
|
251
|
-
<ScrollArea orientation="horizontal"
|
|
223
|
+
<ScrollArea orientation="horizontal">
|
|
252
224
|
<ResponsiveGrid flow="columns">
|
|
253
225
|
{columns.map((column) => (
|
|
254
226
|
<Card key={column}>
|
|
@@ -264,17 +236,51 @@ export default function Demo() {
|
|
|
264
236
|
|
|
265
237
|
<Card>
|
|
266
238
|
<CardHeader>
|
|
267
|
-
<CardTitle level={2}
|
|
239
|
+
<CardTitle level={2}>ScrollBar は何も描画しない(非推奨)</CardTitle>
|
|
240
|
+
<CardDescription>
|
|
241
|
+
v22 まではこの要素を置くことが軸を開く方法だったが、スクロールがブラウザ本来のものに
|
|
242
|
+
なったので ScrollBar は何も描画しない。下のカードには ScrollBar
|
|
243
|
+
が置いてあるが、横に動くのは orientation="both" のおかげで、ScrollBar
|
|
244
|
+
のおかげではない。残っている <ScrollBar> は消して、軸は orientation で宣言する。
|
|
245
|
+
</CardDescription>
|
|
246
|
+
</CardHeader>
|
|
247
|
+
<CardContent>
|
|
248
|
+
<Card variant="outline" className="h-24 w-full">
|
|
249
|
+
<CardContent flush>
|
|
250
|
+
<ScrollArea orientation="both">
|
|
251
|
+
<ResponsiveGrid flow="columns">
|
|
252
|
+
{columns.map((column) => (
|
|
253
|
+
<Text key={column}>{column}</Text>
|
|
254
|
+
))}
|
|
255
|
+
</ResponsiveGrid>
|
|
256
|
+
<ScrollBar orientation="horizontal" />
|
|
257
|
+
</ScrollArea>
|
|
258
|
+
</CardContent>
|
|
259
|
+
</Card>
|
|
260
|
+
</CardContent>
|
|
261
|
+
</Card>
|
|
262
|
+
|
|
263
|
+
<Card>
|
|
264
|
+
<CardHeader>
|
|
265
|
+
<CardTitle level={2}>両方向スクロール(orientation="both")</CardTitle>
|
|
266
|
+
<CardDescription>
|
|
267
|
+
縦にも横にも溢れうる面は orientation="both"。以前は縦の ScrollArea に
|
|
268
|
+
ScrollBar を足して横軸を開けていたが、スクロールはブラウザ本来のものになったので、
|
|
269
|
+
軸を決めるのは orientation だけになった。
|
|
270
|
+
</CardDescription>
|
|
268
271
|
</CardHeader>
|
|
269
272
|
<CardContent>
|
|
270
|
-
<
|
|
271
|
-
<
|
|
272
|
-
|
|
273
|
-
<
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
273
|
+
<Card variant="outline" className="h-32 w-full">
|
|
274
|
+
<CardContent flush>
|
|
275
|
+
<ScrollArea orientation="both">
|
|
276
|
+
<ResponsiveGrid flow="columns">
|
|
277
|
+
{columns.map((column) => (
|
|
278
|
+
<Text key={column}>{column}</Text>
|
|
279
|
+
))}
|
|
280
|
+
</ResponsiveGrid>
|
|
281
|
+
</ScrollArea>
|
|
282
|
+
</CardContent>
|
|
283
|
+
</Card>
|
|
278
284
|
</CardContent>
|
|
279
285
|
</Card>
|
|
280
286
|
|
|
@@ -288,7 +294,7 @@ export default function Demo() {
|
|
|
288
294
|
<CardContent>
|
|
289
295
|
<Card variant="outline" className="h-56 w-full">
|
|
290
296
|
<CardContent flush>
|
|
291
|
-
<ScrollArea
|
|
297
|
+
<ScrollArea>
|
|
292
298
|
<CardContent>
|
|
293
299
|
<Flex direction="col" gap="xs">
|
|
294
300
|
{shortEntries.map((e) => (
|
|
@@ -41,8 +41,7 @@ export default function Demo() {
|
|
|
41
41
|
形式に整形され、 解釈できない入力は元の値へ復帰する。
|
|
42
42
|
</CardDescription>
|
|
43
43
|
</CardHeader>
|
|
44
|
-
|
|
45
|
-
<CardContent data-axe-open>
|
|
44
|
+
<CardContent>
|
|
46
45
|
<FormField id="issue-date" label="発行日" required>
|
|
47
46
|
<DatePicker
|
|
48
47
|
id="issue-date"
|
|
@@ -288,7 +287,7 @@ export default function Demo() {
|
|
|
288
287
|
ISO 送信される。 開始 > 終了で入力しても order (既定 true) が昇順に正規化する。
|
|
289
288
|
</CardDescription>
|
|
290
289
|
</CardHeader>
|
|
291
|
-
<CardContent
|
|
290
|
+
<CardContent>
|
|
292
291
|
<FormField id="period" label="会計期間" required>
|
|
293
292
|
<DatePicker
|
|
294
293
|
range
|
|
@@ -38,8 +38,11 @@ export default function Demo() {
|
|
|
38
38
|
<CardDescription>6スロット 1グループ · ペースト・矢印キー操作に対応。</CardDescription>
|
|
39
39
|
</CardHeader>
|
|
40
40
|
<CardContent>
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
{/* この行の id は FIELD ではなく CONTROL 側にある。FormField はその id をそのまま
|
|
42
|
+
使い、ラベルのクリックもその id を見る(gh#477:以前は FormField 自身の id を
|
|
43
|
+
見ていたので、両者が食い違った瞬間にラベルがどこも指さなくなった)。 */}
|
|
44
|
+
<FormField label="認証コード" required>
|
|
45
|
+
<InputOTP id="email-otp" maxLength={6} value={emailCode} onChange={setEmailCode}>
|
|
43
46
|
<InputOTPGroup>
|
|
44
47
|
<InputOTPSlot index={0} />
|
|
45
48
|
<InputOTPSlot index={1} />
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { useState } from "react";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
Badge,
|
|
5
|
+
Card,
|
|
6
|
+
CardContent,
|
|
7
|
+
CardDescription,
|
|
8
|
+
CardHeader,
|
|
9
|
+
CardTitle,
|
|
10
|
+
} from "@godxjp/ui/data-display";
|
|
4
11
|
import { FormField, Segmented } from "@godxjp/ui/data-entry";
|
|
5
12
|
import { Text, VisuallyHidden } from "@godxjp/ui/general";
|
|
6
13
|
import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
@@ -84,6 +91,38 @@ export default function Demo() {
|
|
|
84
91
|
</CardContent>
|
|
85
92
|
</Card>
|
|
86
93
|
|
|
94
|
+
<Card id="four-with-counts">
|
|
95
|
+
<CardHeader>
|
|
96
|
+
<CardTitle level={2}>4 択 + 件数(スマホ幅では折り返す)</CardTitle>
|
|
97
|
+
<CardDescription>
|
|
98
|
+
一覧の上の状態フィルター。4 つが 1 行に収まらない幅では、トラックが 2 行目に折り返し
|
|
99
|
+
ます — ラベルも件数も切り詰めません。`check:segmented-wrap` がこのカードを測ります。
|
|
100
|
+
</CardDescription>
|
|
101
|
+
</CardHeader>
|
|
102
|
+
<CardContent>
|
|
103
|
+
<Segmented
|
|
104
|
+
aria-label="状態"
|
|
105
|
+
defaultValue="all"
|
|
106
|
+
options={[
|
|
107
|
+
{ value: "all", label: "すべて", count: 128 },
|
|
108
|
+
{ value: "active", label: "実習中", count: 96 },
|
|
109
|
+
{ value: "pending", label: "申請中", count: 12 },
|
|
110
|
+
{ value: "gone", label: "失踪・帰国", count: 0 },
|
|
111
|
+
].map(({ value, label, count }) => ({
|
|
112
|
+
value,
|
|
113
|
+
label: (
|
|
114
|
+
<>
|
|
115
|
+
{label}
|
|
116
|
+
<Badge as="span" variant="secondary">
|
|
117
|
+
{count}
|
|
118
|
+
</Badge>
|
|
119
|
+
</>
|
|
120
|
+
),
|
|
121
|
+
}))}
|
|
122
|
+
/>
|
|
123
|
+
</CardContent>
|
|
124
|
+
</Card>
|
|
125
|
+
|
|
87
126
|
<Card>
|
|
88
127
|
<CardHeader>
|
|
89
128
|
<CardTitle level={2}>size · vertical · block</CardTitle>
|
|
@@ -142,8 +142,7 @@ export default function Demo() {
|
|
|
142
142
|
references. The internal search textbox has its own visible-purpose accessible name.
|
|
143
143
|
</CardDescription>
|
|
144
144
|
</CardHeader>
|
|
145
|
-
|
|
146
|
-
<CardContent data-axe-open>
|
|
145
|
+
<CardContent>
|
|
147
146
|
<FormField
|
|
148
147
|
id="searchable-invalid"
|
|
149
148
|
label="担当拠点"
|
|
@@ -21,7 +21,9 @@ import {
|
|
|
21
21
|
SelectTrigger,
|
|
22
22
|
SelectValue,
|
|
23
23
|
} from "@godxjp/ui/data-entry";
|
|
24
|
+
import { Button } from "@godxjp/ui/general";
|
|
24
25
|
import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
26
|
+
import { X } from "lucide-react";
|
|
25
27
|
|
|
26
28
|
/**
|
|
27
29
|
* Select — the single-select control. Prefer the data-driven `options` API
|
|
@@ -38,6 +40,12 @@ export default function Demo() {
|
|
|
38
40
|
const [reviewerAsync, setReviewerAsync] = useState("tanaka");
|
|
39
41
|
const [reviewerCustom, setReviewerCustom] = useState("tanaka");
|
|
40
42
|
const [reviewerLabel, setReviewerLabel] = useState("tanaka");
|
|
43
|
+
const [prefixed, setPrefixed] = useState("JPY");
|
|
44
|
+
const [tags, setTags] = useState<string[]>(["至急", "社内便"]);
|
|
45
|
+
// antd `labelInValue`: the record arrives carrying its own label, before any option list loads.
|
|
46
|
+
const [assignedTo, setAssignedTo] = useState<
|
|
47
|
+
{ value: string; label: React.ReactNode } | undefined
|
|
48
|
+
>({ value: "52", label: "東京本社" });
|
|
41
49
|
|
|
42
50
|
const people = [
|
|
43
51
|
{ value: "tanaka", label: "田中 太郎", sublabel: "tanaka@example.com" },
|
|
@@ -82,9 +90,7 @@ export default function Demo() {
|
|
|
82
90
|
Pass an options array; name= submits the value with the form.
|
|
83
91
|
</CardDescription>
|
|
84
92
|
</CardHeader>
|
|
85
|
-
|
|
86
|
-
overlay-open a11y state is measured. See docs/FRAME-A11Y-CI.md. */}
|
|
87
|
-
<CardContent data-axe-open>
|
|
93
|
+
<CardContent>
|
|
88
94
|
<FormField id="status" label="状態">
|
|
89
95
|
<Select
|
|
90
96
|
id="status"
|
|
@@ -392,6 +398,105 @@ export default function Demo() {
|
|
|
392
398
|
</FormField>
|
|
393
399
|
</CardContent>
|
|
394
400
|
</Card>
|
|
401
|
+
<Card>
|
|
402
|
+
<CardHeader>
|
|
403
|
+
<CardTitle level={2}>
|
|
404
|
+
Ant Design 6 · prefix・suffixIcon・placement・listHeight
|
|
405
|
+
</CardTitle>
|
|
406
|
+
<CardDescription>
|
|
407
|
+
グループは options のネスト({`{ label, options }`})でも、行の group
|
|
408
|
+
でも同じ一覧になります。
|
|
409
|
+
</CardDescription>
|
|
410
|
+
</CardHeader>
|
|
411
|
+
<CardContent>
|
|
412
|
+
<FormField id="prefixed" label="通貨">
|
|
413
|
+
<Select
|
|
414
|
+
id="prefixed"
|
|
415
|
+
name="currency_prefixed"
|
|
416
|
+
value={prefixed}
|
|
417
|
+
onValueChange={setPrefixed}
|
|
418
|
+
prefix={<Badge tone="muted">¥</Badge>}
|
|
419
|
+
placement="bottomEnd"
|
|
420
|
+
listHeight={220}
|
|
421
|
+
options={[
|
|
422
|
+
{
|
|
423
|
+
label: "アジア",
|
|
424
|
+
options: [
|
|
425
|
+
{ value: "JPY", label: "日本円" },
|
|
426
|
+
{ value: "VND", label: "ベトナムドン" },
|
|
427
|
+
],
|
|
428
|
+
},
|
|
429
|
+
{
|
|
430
|
+
label: "ヨーロッパ",
|
|
431
|
+
options: [{ value: "EUR", label: "ユーロ" }],
|
|
432
|
+
},
|
|
433
|
+
]}
|
|
434
|
+
/>
|
|
435
|
+
</FormField>
|
|
436
|
+
</CardContent>
|
|
437
|
+
</Card>
|
|
438
|
+
|
|
439
|
+
<Card>
|
|
440
|
+
<CardHeader>
|
|
441
|
+
<CardTitle level={2}>mode="tags" · tokenSeparators・tagRender</CardTitle>
|
|
442
|
+
<CardDescription>
|
|
443
|
+
一覧にない値も入力できます。カンマ区切りの貼り付けは一度にまとめて確定します。
|
|
444
|
+
</CardDescription>
|
|
445
|
+
</CardHeader>
|
|
446
|
+
<CardContent>
|
|
447
|
+
<FormField id="tags" label="ラベル">
|
|
448
|
+
<Select
|
|
449
|
+
id="tags"
|
|
450
|
+
name="labels[]"
|
|
451
|
+
mode="tags"
|
|
452
|
+
value={tags}
|
|
453
|
+
onValueChange={setTags}
|
|
454
|
+
tokenSeparators={[",", "\n"]}
|
|
455
|
+
maxTagTextLength={6}
|
|
456
|
+
options={[
|
|
457
|
+
{ value: "至急", label: "至急" },
|
|
458
|
+
{ value: "要確認", label: "要確認" },
|
|
459
|
+
]}
|
|
460
|
+
tagRender={({ label, onClose }) => (
|
|
461
|
+
<Badge tone="info">
|
|
462
|
+
{label}
|
|
463
|
+
<Button
|
|
464
|
+
variant="ghost"
|
|
465
|
+
size="icon-xs"
|
|
466
|
+
aria-label={`${String(label)} を外す`}
|
|
467
|
+
onClick={onClose}
|
|
468
|
+
>
|
|
469
|
+
<X aria-hidden="true" />
|
|
470
|
+
</Button>
|
|
471
|
+
</Badge>
|
|
472
|
+
)}
|
|
473
|
+
/>
|
|
474
|
+
</FormField>
|
|
475
|
+
</CardContent>
|
|
476
|
+
</Card>
|
|
477
|
+
|
|
478
|
+
<Card>
|
|
479
|
+
<CardHeader>
|
|
480
|
+
<CardTitle level={2}>labelInValue · 読み込み前でも名前が出る</CardTitle>
|
|
481
|
+
<CardDescription>
|
|
482
|
+
値が {`{ value, label }`} を持つので、選択肢がまだ届いていなくても ID
|
|
483
|
+
ではなく名前を表示できます。
|
|
484
|
+
</CardDescription>
|
|
485
|
+
</CardHeader>
|
|
486
|
+
<CardContent>
|
|
487
|
+
<FormField id="assigned" label="担当拠点">
|
|
488
|
+
<Select
|
|
489
|
+
id="assigned"
|
|
490
|
+
name="office_id"
|
|
491
|
+
labelInValue
|
|
492
|
+
value={assignedTo}
|
|
493
|
+
onValueChange={setAssignedTo}
|
|
494
|
+
notFoundContent="拠点を読み込み中"
|
|
495
|
+
options={[]}
|
|
496
|
+
/>
|
|
497
|
+
</FormField>
|
|
498
|
+
</CardContent>
|
|
499
|
+
</Card>
|
|
395
500
|
</Flex>
|
|
396
501
|
</PageContainer>
|
|
397
502
|
);
|