@godxjp/ui 21.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/app/app-provider.js +2 -1
- package/dist/components/data-display/badge.d.ts +28 -1
- package/dist/components/data-display/badge.js +2 -0
- package/dist/components/data-display/data-table.d.ts +18 -2
- package/dist/components/data-display/data-table.js +4 -0
- package/dist/components/data-display/index.d.ts +1 -1
- package/dist/components/data-display/popover.d.ts +19 -1
- package/dist/components/data-display/popover.js +9 -1
- package/dist/components/data-display/progress.d.ts +37 -0
- package/dist/components/data-display/progress.js +57 -5
- 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/date-picker.d.ts +10 -3
- package/dist/components/data-entry/date-picker.js +503 -238
- package/dist/components/data-entry/form-field.d.ts +1 -1
- package/dist/components/data-entry/form-field.js +7 -3
- package/dist/components/data-entry/form.js +10 -1
- package/dist/components/data-entry/index.d.ts +0 -6
- package/dist/components/data-entry/index.js +0 -6
- package/dist/components/data-entry/label.d.ts +14 -1
- package/dist/components/data-entry/label.js +6 -1
- package/dist/components/data-entry/radio.d.ts +27 -6
- package/dist/components/data-entry/radio.js +89 -43
- package/dist/components/data-entry/search-select.js +226 -89
- package/dist/components/data-entry/select.d.ts +76 -14
- package/dist/components/data-entry/select.js +497 -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.d.ts +6 -3
- package/dist/components/data-entry/switch.js +36 -11
- package/dist/components/layout/mobile-shell.d.ts +1 -1
- package/dist/components/layout/mobile-shell.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/navigation/steps.d.ts +1 -1
- package/dist/components/navigation/steps.js +3 -1
- package/dist/components/navigation/tabs-scroll.d.ts +27 -0
- package/dist/components/navigation/tabs-scroll.js +52 -1
- package/dist/components/navigation/tabs.d.ts +2 -2
- package/dist/components/navigation/tabs.js +88 -23
- package/dist/components/ui/index.d.ts +0 -4
- package/dist/components/ui/index.js +0 -4
- package/dist/components/ui/input-otp.d.ts +1 -1
- package/dist/components/ui/segmented.d.ts +15 -1
- package/dist/components/ui/segmented.js +15 -6
- package/dist/components/ui/tag-input.js +3 -5
- package/dist/i18n/messages/en.json +3 -2
- package/dist/i18n/messages/ja.json +3 -2
- package/dist/i18n/messages/vi.json +3 -2
- package/dist/lib/datetime/picker-format.d.ts +18 -0
- package/dist/lib/datetime/picker-format.js +35 -1
- package/dist/lib/field-a11y.d.ts +12 -0
- package/dist/lib/field-a11y.js +14 -1
- 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 +16 -6
- package/dist/props/components/data-entry.prop.d.ts +503 -129
- package/dist/props/components/index.d.ts +2 -2
- package/dist/props/components/layout.prop.d.ts +12 -1
- package/dist/props/components/navigation.prop.d.ts +93 -1
- package/dist/props/registry.d.ts +79 -16
- package/dist/props/registry.js +85 -15
- package/dist/props/vocabulary/data.prop.d.ts +12 -0
- package/dist/props/vocabulary/index.d.ts +2 -2
- package/dist/props/vocabulary/layout.prop.d.ts +11 -0
- package/dist/styles/badge-layout.css +4 -0
- package/dist/styles/card-layout.css +6 -6
- package/dist/styles/control.css +220 -29
- package/dist/styles/data-display-layout.css +94 -23
- package/dist/styles/focus-ring.css +6 -4
- package/dist/styles/fonts.css +88 -4
- package/dist/styles/navigation-layout.css +36 -236
- package/dist/styles/shell-layout.css +149 -139
- package/dist/styles/table-layout.css +41 -3
- package/dist/tokens/components/control.css +4 -0
- package/dist/tokens/components/data-display.css +9 -5
- package/dist/tokens/components/navigation.css +9 -5
- package/dist/tokens/components/scroll-area.css +7 -0
- package/dist/tokens/components/segmented.css +0 -2
- package/dist/tokens/components/shell.css +2 -0
- package/dist/tokens/components/table.css +3 -0
- package/dist/tokens/foundation.css +7 -0
- package/docs/COMPONENTS.md +14 -14
- package/docs/CONSUMER-RULES.md +24 -1
- package/docs/CUSTOMER-THEMING.md +7 -1
- package/docs/FRAME-COVERAGE-REPORT.md +5 -11
- package/docs/TOKENS.md +65 -0
- package/docs/data-display/badge.tsx +37 -0
- package/docs/data-display/data-table/index.tsx +45 -1
- package/docs/data-display/popover.tsx +43 -5
- package/docs/data-display/progress.tsx +28 -0
- package/docs/data-display/scroll-area.tsx +51 -45
- package/docs/data-entry/calendar.tsx +2 -2
- package/docs/data-entry/date-picker.tsx +144 -5
- package/docs/data-entry/form/examples/invoice-form.tsx +2 -2
- package/docs/data-entry/form-field/examples/a11y-contract.tsx +3 -5
- package/docs/data-entry/form.tsx +4 -4
- package/docs/data-entry/input-otp.tsx +5 -2
- package/docs/data-entry/number-input.tsx +31 -0
- package/docs/data-entry/segmented.tsx +143 -2
- 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/layout/mobile-shell.tsx +5 -0
- package/docs/navigation/dropdown-menu.tsx +75 -4
- package/docs/navigation/tabs.tsx +149 -0
- package/docs/roadmap/antd-parity.md +35 -34
- package/docs/roadmap/parity-audit-data-entry.md +196 -172
- package/docs/roadmap/parity-audit-layout-navigation-general.md +304 -310
- package/docs/roadmap/parity-backlog.md +8 -10
- package/docs/showcase/acme-portal.tsx +7 -0
- package/package.json +28 -64
- package/scripts/ui-audit.mjs +18 -5
- package/scripts/visual-audit-rules.mjs +0 -7
- package/scripts/visual-audit.mjs +6 -27
- package/dist/components/data-entry/date-range-picker.d.ts +0 -11
- package/dist/components/data-entry/date-range-picker.js +0 -349
- package/dist/components/data-entry/month-picker.d.ts +0 -10
- package/dist/components/data-entry/month-picker.js +0 -241
- package/dist/components/data-entry/month-range-picker.d.ts +0 -10
- package/dist/components/data-entry/month-range-picker.js +0 -301
- 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 -21
- 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/date-range-picker.d.ts +0 -1
- package/dist/components/ui/date-range-picker.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/data-entry/date-range-picker.tsx +0 -175
- package/docs/data-entry/month-picker.tsx +0 -101
- package/docs/data-entry/month-range-picker.tsx +0 -115
- package/docs/navigation/context-menu.tsx +0 -128
- package/docs/navigation/menubar.tsx +0 -141
- package/docs/navigation/navigation-menu.tsx +0 -158
|
@@ -4,11 +4,14 @@ import { ja } from "date-fns/locale";
|
|
|
4
4
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@godxjp/ui/data-display";
|
|
5
5
|
import { DatePicker, FormField } from "@godxjp/ui/data-entry";
|
|
6
6
|
import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
7
|
+
import type { DateRange } from "react-day-picker";
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
|
-
* DatePicker —
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
* DatePicker — ONE date control. `picker` sets the granularity (day · week · month · quarter ·
|
|
11
|
+
* year), `range` turns it into a two-endpoint field, `multiple` into a set. Always give it a
|
|
12
|
+
* `name` for form submission; it emits ISO-8601 at the picker's own precision. Use
|
|
13
|
+
* `minDate`/`maxDate` to constrain what is selectable. Never hand-roll a date input + calendar,
|
|
14
|
+
* and never compose two DatePickers side-by-side to fake a range — that is `range`.
|
|
12
15
|
* Composed only from real @godxjp/ui components.
|
|
13
16
|
*/
|
|
14
17
|
export default function Demo() {
|
|
@@ -17,6 +20,11 @@ export default function Demo() {
|
|
|
17
20
|
const [closingDate, setClosingDate] = useState<Date | undefined>(undefined);
|
|
18
21
|
const [meetingDate, setMeetingDate] = useState<Date | undefined>(new Date(2026, 5, 25));
|
|
19
22
|
const [settlementDate, setSettlementDate] = useState<Date | undefined>(undefined);
|
|
23
|
+
const [period, setPeriod] = useState<DateRange | undefined>({
|
|
24
|
+
from: new Date(2026, 3, 1),
|
|
25
|
+
to: new Date(2027, 2, 31),
|
|
26
|
+
});
|
|
27
|
+
const [term, setTerm] = useState<DateRange | undefined>(undefined);
|
|
20
28
|
|
|
21
29
|
return (
|
|
22
30
|
<PageContainer
|
|
@@ -33,8 +41,7 @@ export default function Demo() {
|
|
|
33
41
|
形式に整形され、 解釈できない入力は元の値へ復帰する。
|
|
34
42
|
</CardDescription>
|
|
35
43
|
</CardHeader>
|
|
36
|
-
|
|
37
|
-
<CardContent data-axe-open>
|
|
44
|
+
<CardContent>
|
|
38
45
|
<FormField id="issue-date" label="発行日" required>
|
|
39
46
|
<DatePicker
|
|
40
47
|
id="issue-date"
|
|
@@ -271,6 +278,138 @@ export default function Demo() {
|
|
|
271
278
|
</FormField>
|
|
272
279
|
</CardContent>
|
|
273
280
|
</Card>
|
|
281
|
+
<Card>
|
|
282
|
+
<CardHeader>
|
|
283
|
+
<CardTitle level={2}>期間 (range)</CardTitle>
|
|
284
|
+
<CardDescription>
|
|
285
|
+
range を付けると値は DateRange になり、開始/終了の 2 入力を 1
|
|
286
|
+
つのコントロールにまとめる。 name="period" は period_from / period_to として
|
|
287
|
+
ISO 送信される。 開始 > 終了で入力しても order (既定 true) が昇順に正規化する。
|
|
288
|
+
</CardDescription>
|
|
289
|
+
</CardHeader>
|
|
290
|
+
<CardContent>
|
|
291
|
+
<FormField id="period" label="会計期間" required>
|
|
292
|
+
<DatePicker
|
|
293
|
+
range
|
|
294
|
+
id="period"
|
|
295
|
+
name="period"
|
|
296
|
+
value={period}
|
|
297
|
+
onValueChange={setPeriod}
|
|
298
|
+
minDate={new Date(2020, 0, 1)}
|
|
299
|
+
maxDate={new Date(2030, 11, 31)}
|
|
300
|
+
/>
|
|
301
|
+
</FormField>
|
|
302
|
+
</CardContent>
|
|
303
|
+
</Card>
|
|
304
|
+
<Card>
|
|
305
|
+
<CardHeader>
|
|
306
|
+
<CardTitle level={2}>月次の期間 (range × picker)</CardTitle>
|
|
307
|
+
<CardDescription>
|
|
308
|
+
range と picker は直交する。picker="month" の期間は月グリッドで選び、
|
|
309
|
+
term_from / term_to を ISO yyyy-MM で送信する。
|
|
310
|
+
</CardDescription>
|
|
311
|
+
</CardHeader>
|
|
312
|
+
<CardContent>
|
|
313
|
+
<FormField id="term" label="対象期間">
|
|
314
|
+
<DatePicker
|
|
315
|
+
range
|
|
316
|
+
picker="month"
|
|
317
|
+
id="term"
|
|
318
|
+
name="term"
|
|
319
|
+
value={term}
|
|
320
|
+
onValueChange={setTerm}
|
|
321
|
+
minDate={new Date(2024, 0, 1)}
|
|
322
|
+
maxDate={new Date(2027, 11, 31)}
|
|
323
|
+
/>
|
|
324
|
+
</FormField>
|
|
325
|
+
</CardContent>
|
|
326
|
+
</Card>
|
|
327
|
+
<Card>
|
|
328
|
+
<CardHeader>
|
|
329
|
+
<CardTitle level={2}>期間プリセットと確定</CardTitle>
|
|
330
|
+
<CardDescription>
|
|
331
|
+
presets · needConfirm · allowEmpty は range でも同じ綴りで効く。
|
|
332
|
+
</CardDescription>
|
|
333
|
+
</CardHeader>
|
|
334
|
+
<CardContent>
|
|
335
|
+
<FormField id="preset-range" label="集計期間">
|
|
336
|
+
<DatePicker
|
|
337
|
+
range
|
|
338
|
+
id="preset-range"
|
|
339
|
+
name="report"
|
|
340
|
+
format="yyyy/MM/dd"
|
|
341
|
+
needConfirm
|
|
342
|
+
allowEmpty={[false, true]}
|
|
343
|
+
showWeek
|
|
344
|
+
minDate={new Date(2026, 0, 1)}
|
|
345
|
+
maxDate={new Date(2026, 11, 31)}
|
|
346
|
+
presets={[
|
|
347
|
+
{
|
|
348
|
+
label: "9月",
|
|
349
|
+
value: () => ({ from: new Date(2026, 8, 1), to: new Date(2026, 8, 30) }),
|
|
350
|
+
},
|
|
351
|
+
]}
|
|
352
|
+
/>
|
|
353
|
+
</FormField>
|
|
354
|
+
</CardContent>
|
|
355
|
+
</Card>
|
|
356
|
+
<Card>
|
|
357
|
+
<CardHeader>
|
|
358
|
+
<CardTitle level={2}>パネルの初期表示 (defaultPickerValue)</CardTitle>
|
|
359
|
+
<CardDescription>
|
|
360
|
+
値とは独立に「パネルがどの期間を開くか」を指定する。会計年度の開始月で開く、
|
|
361
|
+
編集中の行の月で開く、といった要求はこれでしか表現できない。antd と同じく
|
|
362
|
+
開くたびに再適用される。
|
|
363
|
+
</CardDescription>
|
|
364
|
+
</CardHeader>
|
|
365
|
+
<CardContent>
|
|
366
|
+
<FormField id="fiscal-open" label="会計年度開始月">
|
|
367
|
+
<DatePicker
|
|
368
|
+
id="fiscal-open"
|
|
369
|
+
name="fiscal_open"
|
|
370
|
+
picker="month"
|
|
371
|
+
defaultPickerValue={new Date(2027, 3, 1)}
|
|
372
|
+
/>
|
|
373
|
+
</FormField>
|
|
374
|
+
</CardContent>
|
|
375
|
+
</Card>
|
|
376
|
+
<Card>
|
|
377
|
+
<CardHeader>
|
|
378
|
+
<CardTitle level={2}>片側だけ固定した期間</CardTitle>
|
|
379
|
+
<CardDescription>
|
|
380
|
+
range のとき disabled は [from, to] のタプルを取り、片方だけロックできる。
|
|
381
|
+
「開始日は契約で確定、終了日だけ交渉中」がこれで表現できる。
|
|
382
|
+
</CardDescription>
|
|
383
|
+
</CardHeader>
|
|
384
|
+
<CardContent>
|
|
385
|
+
<FormField id="contract-period" label="契約期間">
|
|
386
|
+
<DatePicker
|
|
387
|
+
range
|
|
388
|
+
id="contract-period"
|
|
389
|
+
name="contract_period"
|
|
390
|
+
defaultValue={{ from: new Date(2026, 3, 1), to: new Date(2027, 2, 31) }}
|
|
391
|
+
disabled={[true, false]}
|
|
392
|
+
/>
|
|
393
|
+
</FormField>
|
|
394
|
+
</CardContent>
|
|
395
|
+
</Card>
|
|
396
|
+
<Card>
|
|
397
|
+
<CardHeader>
|
|
398
|
+
<CardTitle level={2}>disabled な期間</CardTitle>
|
|
399
|
+
<CardDescription>確定済み期間や読み取り専用フィールドに使用。</CardDescription>
|
|
400
|
+
</CardHeader>
|
|
401
|
+
<CardContent>
|
|
402
|
+
<FormField id="locked-period" label="確定期間">
|
|
403
|
+
<DatePicker
|
|
404
|
+
range
|
|
405
|
+
id="locked-period"
|
|
406
|
+
name="locked_period"
|
|
407
|
+
value={{ from: new Date(2025, 3, 1), to: new Date(2026, 2, 31) }}
|
|
408
|
+
disabled
|
|
409
|
+
/>
|
|
410
|
+
</FormField>
|
|
411
|
+
</CardContent>
|
|
412
|
+
</Card>
|
|
274
413
|
</Flex>
|
|
275
414
|
</PageContainer>
|
|
276
415
|
);
|
|
@@ -3,7 +3,6 @@ import { useState } from "react";
|
|
|
3
3
|
import {
|
|
4
4
|
Cascader,
|
|
5
5
|
DatePicker,
|
|
6
|
-
DateRangePicker,
|
|
7
6
|
Field,
|
|
8
7
|
Form,
|
|
9
8
|
FormField,
|
|
@@ -294,7 +293,8 @@ export default function Demo() {
|
|
|
294
293
|
/>
|
|
295
294
|
</FormField>
|
|
296
295
|
<FormField id="iv-period" label="対象期間">
|
|
297
|
-
<
|
|
296
|
+
<DatePicker
|
|
297
|
+
range
|
|
298
298
|
id="iv-period"
|
|
299
299
|
name="period"
|
|
300
300
|
value={v.period}
|
|
@@ -5,11 +5,9 @@ import {
|
|
|
5
5
|
CheckboxGroup,
|
|
6
6
|
ColorPicker,
|
|
7
7
|
DatePicker,
|
|
8
|
-
DateRangePicker,
|
|
9
8
|
Form,
|
|
10
9
|
FormField,
|
|
11
10
|
Input,
|
|
12
|
-
MonthPicker,
|
|
13
11
|
RadioGroup,
|
|
14
12
|
SearchInput,
|
|
15
13
|
Select,
|
|
@@ -129,14 +127,14 @@ export default function Demo() {
|
|
|
129
127
|
<FormField id="ac-date" label="取引日" helper="yyyy-MM-dd">
|
|
130
128
|
<DatePicker id="ac-date" name="date" />
|
|
131
129
|
</FormField>
|
|
132
|
-
<FormField id="ac-month" label="対象月" helper="yyyy
|
|
133
|
-
<
|
|
130
|
+
<FormField id="ac-month" label="対象月" helper="yyyy-MM">
|
|
131
|
+
<DatePicker picker="month" id="ac-month" name="month" />
|
|
134
132
|
</FormField>
|
|
135
133
|
<FormField id="ac-time" label="締め時刻" helper="24時間表記">
|
|
136
134
|
<TimePicker id="ac-time" name="time" />
|
|
137
135
|
</FormField>
|
|
138
136
|
<FormField id="ac-period" label="対象期間" helper="開始日と終了日">
|
|
139
|
-
<
|
|
137
|
+
<DatePicker range id="ac-period" name="period" />
|
|
140
138
|
</FormField>
|
|
141
139
|
<FormField id="ac-color" label="タグ色" helper="16進カラー">
|
|
142
140
|
<ColorPicker id="ac-color" onValueChange={() => {}} />
|
package/docs/data-entry/form.tsx
CHANGED
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
Checkbox,
|
|
6
6
|
CheckboxGroup,
|
|
7
7
|
DatePicker,
|
|
8
|
-
DateRangePicker,
|
|
9
8
|
Field,
|
|
10
9
|
Form,
|
|
11
10
|
FormErrors,
|
|
@@ -425,7 +424,7 @@ export default function Demo() {
|
|
|
425
424
|
|
|
426
425
|
<Card>
|
|
427
426
|
<CardHeader>
|
|
428
|
-
<CardTitle level={2}>日時系 · DatePicker /
|
|
427
|
+
<CardTitle level={2}>日時系 · DatePicker / DatePicker range / TimePicker</CardTitle>
|
|
429
428
|
<CardDescription>
|
|
430
429
|
単一日付・期間・時刻。ISO-8601 / IANA タイムゾーンに準拠し locale
|
|
431
430
|
連動でフォーマットする。
|
|
@@ -483,12 +482,13 @@ export default function Demo() {
|
|
|
483
482
|
/>
|
|
484
483
|
</FormField>
|
|
485
484
|
<FormField id="f-period" label="会計期間" colSpan={2}>
|
|
486
|
-
<
|
|
485
|
+
<DatePicker
|
|
486
|
+
range
|
|
487
487
|
id="f-period"
|
|
488
488
|
name="period"
|
|
489
489
|
value={period}
|
|
490
490
|
onValueChange={setPeriod}
|
|
491
|
-
// 土日は選べない。
|
|
491
|
+
// 土日は選べない。minDate/maxDate では表せない規則。
|
|
492
492
|
disabledDate={(date) => date.getDay() === 0 || date.getDay() === 6}
|
|
493
493
|
/>
|
|
494
494
|
</FormField>
|
|
@@ -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} />
|
|
@@ -223,6 +223,37 @@ export default function Demo() {
|
|
|
223
223
|
</CardContent>
|
|
224
224
|
</Card>
|
|
225
225
|
|
|
226
|
+
{/* prefix / suffix — all THREE combinations, because the two-affix case is the only one
|
|
227
|
+
that used to be exercised and the suffix-only one is where the bug lived. */}
|
|
228
|
+
<Card>
|
|
229
|
+
<CardHeader>
|
|
230
|
+
<CardTitle level={2}>prefix · suffix · 単位つきの数値</CardTitle>
|
|
231
|
+
<CardDescription>
|
|
232
|
+
通貨記号や単位はフィールドの内側に重ねる装飾。読み上げからは外れる (aria-hidden)
|
|
233
|
+
ので、意味は必ずラベル側に置く。
|
|
234
|
+
</CardDescription>
|
|
235
|
+
</CardHeader>
|
|
236
|
+
<CardContent>
|
|
237
|
+
<Flex direction="col" gap="md" id="number-input-affixes">
|
|
238
|
+
<FormField id="ni-prefix" label="金額(前置き)">
|
|
239
|
+
<NumberInput id="ni-prefix" prefix="¥" defaultValue={1980} aria-label="金額" />
|
|
240
|
+
</FormField>
|
|
241
|
+
<FormField id="ni-suffix" label="日数(後置き)">
|
|
242
|
+
<NumberInput id="ni-suffix" suffix="日" defaultValue={7} aria-label="日数" />
|
|
243
|
+
</FormField>
|
|
244
|
+
<FormField id="ni-both" label="率(前後)">
|
|
245
|
+
<NumberInput
|
|
246
|
+
id="ni-both"
|
|
247
|
+
prefix="+"
|
|
248
|
+
suffix="%"
|
|
249
|
+
defaultValue={12}
|
|
250
|
+
aria-label="率"
|
|
251
|
+
/>
|
|
252
|
+
</FormField>
|
|
253
|
+
</Flex>
|
|
254
|
+
</CardContent>
|
|
255
|
+
</Card>
|
|
256
|
+
|
|
226
257
|
<Card>
|
|
227
258
|
<CardHeader>
|
|
228
259
|
<Heading level={2}>キーボード操作</Heading>
|
|
@@ -1,8 +1,15 @@
|
|
|
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
|
-
import { Text } from "@godxjp/ui/general";
|
|
12
|
+
import { Text, VisuallyHidden } from "@godxjp/ui/general";
|
|
6
13
|
import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
7
14
|
import { CalendarDays, Columns3, LayoutList, Monitor, Moon, Sun } from "lucide-react";
|
|
8
15
|
|
|
@@ -84,6 +91,140 @@ 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
|
+
|
|
126
|
+
<Card>
|
|
127
|
+
<CardHeader>
|
|
128
|
+
<CardTitle level={2}>size · vertical · block</CardTitle>
|
|
129
|
+
<CardDescription>
|
|
130
|
+
size は 3 段(sm / md / lg)。トラックの高さは --control-height そのもので、
|
|
131
|
+
MobileShell のようにその変数をスコープする領域では自動的にタッチ段(44px)になります。
|
|
132
|
+
vertical では 1 行ぶんが 1 コントロールの高さになります — 横 1 行のときだけトラック
|
|
133
|
+
内側の余白を引くので、積んだときは引きません。block は幅いっぱいに広げます。
|
|
134
|
+
</CardDescription>
|
|
135
|
+
</CardHeader>
|
|
136
|
+
<CardContent>
|
|
137
|
+
<Flex direction="col" gap="md" align="start">
|
|
138
|
+
<Segmented
|
|
139
|
+
aria-label="サイズ sm"
|
|
140
|
+
size="sm"
|
|
141
|
+
defaultValue="a"
|
|
142
|
+
options={[
|
|
143
|
+
{ value: "a", label: "小" },
|
|
144
|
+
{ value: "b", label: "中" },
|
|
145
|
+
{ value: "c", label: "大" },
|
|
146
|
+
]}
|
|
147
|
+
/>
|
|
148
|
+
<Segmented
|
|
149
|
+
aria-label="サイズ md"
|
|
150
|
+
defaultValue="b"
|
|
151
|
+
options={[
|
|
152
|
+
{ value: "a", label: "小" },
|
|
153
|
+
{ value: "b", label: "中" },
|
|
154
|
+
{ value: "c", label: "大" },
|
|
155
|
+
]}
|
|
156
|
+
/>
|
|
157
|
+
<Segmented
|
|
158
|
+
aria-label="サイズ lg"
|
|
159
|
+
size="lg"
|
|
160
|
+
defaultValue="c"
|
|
161
|
+
options={[
|
|
162
|
+
{ value: "a", label: "小" },
|
|
163
|
+
{ value: "b", label: "中" },
|
|
164
|
+
{ value: "c", label: "大" },
|
|
165
|
+
]}
|
|
166
|
+
/>
|
|
167
|
+
<Segmented
|
|
168
|
+
aria-label="縦積み"
|
|
169
|
+
vertical
|
|
170
|
+
block
|
|
171
|
+
defaultValue="ok"
|
|
172
|
+
options={[
|
|
173
|
+
{ value: "ok", label: "実施" },
|
|
174
|
+
{ value: "warn", label: "要改善" },
|
|
175
|
+
{ value: "none", label: "未実施" },
|
|
176
|
+
]}
|
|
177
|
+
/>
|
|
178
|
+
</Flex>
|
|
179
|
+
</CardContent>
|
|
180
|
+
</Card>
|
|
181
|
+
|
|
182
|
+
<Card>
|
|
183
|
+
<CardHeader>
|
|
184
|
+
<CardTitle level={2}>短い記号を出して、長い名前を読ませる</CardTitle>
|
|
185
|
+
<CardDescription>
|
|
186
|
+
`label` は ReactNode なので、見える記号を aria-hidden にして VisuallyHidden に
|
|
187
|
+
読み上げ名を置けます。専用の prop は要りません。○ と読み上げられても意味が伝わらない
|
|
188
|
+
ため、色や記号だけに意味を持たせないという WCAG 1.4.1 の要求そのものです。
|
|
189
|
+
</CardDescription>
|
|
190
|
+
</CardHeader>
|
|
191
|
+
<CardContent>
|
|
192
|
+
<Segmented
|
|
193
|
+
aria-label="監査結果"
|
|
194
|
+
defaultValue="ok"
|
|
195
|
+
options={[
|
|
196
|
+
{
|
|
197
|
+
value: "ok",
|
|
198
|
+
label: (
|
|
199
|
+
<>
|
|
200
|
+
<span aria-hidden="true">○</span>
|
|
201
|
+
<VisuallyHidden>実施</VisuallyHidden>
|
|
202
|
+
</>
|
|
203
|
+
),
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
value: "warn",
|
|
207
|
+
label: (
|
|
208
|
+
<>
|
|
209
|
+
<span aria-hidden="true">△</span>
|
|
210
|
+
<VisuallyHidden>要改善</VisuallyHidden>
|
|
211
|
+
</>
|
|
212
|
+
),
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
value: "none",
|
|
216
|
+
label: (
|
|
217
|
+
<>
|
|
218
|
+
<span aria-hidden="true">×</span>
|
|
219
|
+
<VisuallyHidden>未実施</VisuallyHidden>
|
|
220
|
+
</>
|
|
221
|
+
),
|
|
222
|
+
},
|
|
223
|
+
]}
|
|
224
|
+
/>
|
|
225
|
+
</CardContent>
|
|
226
|
+
</Card>
|
|
227
|
+
|
|
87
228
|
<Card>
|
|
88
229
|
<CardHeader>
|
|
89
230
|
<CardTitle level={2}>フォームの中で</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
|
);
|