@godxjp/ui 22.0.0 → 23.1.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/date-format-labels.d.ts +14 -2
- package/dist/app/date-format-labels.js +1 -1
- package/dist/app/date-formats.d.ts +14 -2
- package/dist/app/date-formats.js +9 -2
- package/dist/components/data-display/data-table.d.ts +8 -1
- package/dist/components/data-display/data-table.js +9 -2
- 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 +3 -1
- 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 +5 -4
- package/dist/components/data-entry/input.js +1 -1
- package/dist/components/data-entry/number-input.js +27 -6
- package/dist/components/data-entry/radio.js +4 -3
- 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 +3 -1
- package/dist/components/feedback/dialog.js +2 -2
- package/dist/components/feedback/sheet.js +2 -22
- package/dist/components/navigation/dropdown-menu.d.ts +11 -3
- package/dist/components/navigation/dropdown-menu.js +190 -15
- package/dist/components/navigation/filter-bar.js +2 -1
- package/dist/components/navigation/index.d.ts +0 -3
- package/dist/components/navigation/index.js +0 -78
- package/dist/components/navigation/tabs.js +16 -4
- 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/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/breakpoint-token.d.ts +8 -0
- package/dist/lib/breakpoint-token.js +29 -0
- 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 +17 -7
- 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 +25 -1
- package/dist/props/registry.d.ts +69 -1
- package/dist/props/registry.js +75 -0
- package/dist/props/vocabulary/data.prop.d.ts +5 -0
- package/dist/props/vocabulary/index.d.ts +1 -1
- package/dist/styles/control.css +246 -28
- package/dist/styles/data-display-layout.css +18 -10
- package/dist/styles/focus-ring.css +28 -0
- package/dist/styles/fonts.css +88 -4
- package/dist/styles/form-layout.css +4 -0
- package/dist/styles/layout.css +2 -1
- package/dist/styles/navigation-layout.css +24 -238
- package/dist/styles/shell-layout.css +148 -139
- package/dist/styles/table-layout.css +12 -5
- package/dist/tokens/components/control.css +12 -3
- package/dist/tokens/components/data-display.css +0 -5
- package/dist/tokens/components/navigation.css +5 -5
- package/dist/tokens/components/scroll-area.css +7 -0
- package/docs/CONSUMER-RULES.md +7 -2
- package/docs/CUSTOMER-THEMING.md +25 -9
- package/docs/DATETIME.md +11 -2
- package/docs/FRAME-COVERAGE-REPORT.md +4 -7
- package/docs/SPACING.md +35 -5
- package/docs/TOKENS.md +1 -1
- package/docs/data-display/data-table/index.tsx +44 -3
- package/docs/data-display/popover.tsx +4 -6
- package/docs/data-display/scroll-area.tsx +51 -45
- package/docs/data-display/table.tsx +1 -1
- package/docs/data-entry/date-picker.tsx +2 -3
- package/docs/data-entry/input-otp.tsx +5 -2
- package/docs/data-entry/segmented-in-filter-row.tsx +77 -0
- 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 +77 -6
- package/docs/navigation/tabs.tsx +72 -0
- package/docs/roadmap/ai-chat-components.md +1 -2
- 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/docs/roadmap/tree-components.md +0 -1
- package/package.json +25 -55
- package/scripts/_agent-setup.mjs +18 -0
- package/scripts/guinea-pig-skill.md +12 -6
- package/scripts/ui-audit.mjs +185 -7
- 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
|
@@ -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
|
);
|
|
@@ -2,82 +2,111 @@ import { useState } from "react";
|
|
|
2
2
|
|
|
3
3
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@godxjp/ui/data-display";
|
|
4
4
|
import { FormField, Slider } from "@godxjp/ui/data-entry";
|
|
5
|
-
import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
5
|
+
import { Flex, PageContainer, ResponsiveGrid } from "@godxjp/ui/layout";
|
|
6
|
+
import { Text } from "@godxjp/ui/general";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
|
-
* Slider —
|
|
9
|
-
* number
|
|
10
|
-
*
|
|
9
|
+
* Slider — react-aria-components underneath, the antd 6 API on top.
|
|
10
|
+
* `value` is a plain number for one thumb and an array for a `range`; the Radix-era
|
|
11
|
+
* `number[]` + `onValueChange` spelling still compiles and still works.
|
|
12
|
+
* Use `onChange` for live UI and `onChangeComplete` for the expensive work.
|
|
11
13
|
* Composed only from real @godxjp/ui components.
|
|
12
14
|
*/
|
|
13
|
-
const yen = (
|
|
14
|
-
new Intl.NumberFormat("ja-JP", { style: "currency", currency: "JPY" }).format(
|
|
15
|
+
const yen = (value: number) =>
|
|
16
|
+
new Intl.NumberFormat("ja-JP", { style: "currency", currency: "JPY" }).format(value);
|
|
15
17
|
|
|
16
18
|
export default function Demo() {
|
|
17
|
-
const [taxRate, setTaxRate] = useState
|
|
19
|
+
const [taxRate, setTaxRate] = useState(10);
|
|
18
20
|
const [amountRange, setAmountRange] = useState<number[]>([50000, 300000]);
|
|
21
|
+
const [committedRange, setCommittedRange] = useState<number[]>([50000, 300000]);
|
|
22
|
+
const [plan, setPlan] = useState(30);
|
|
19
23
|
const [allocation, setAllocation] = useState<number[]>([40]);
|
|
24
|
+
const [bands, setBands] = useState<number[]>([25, 60]);
|
|
25
|
+
const [volume, setVolume] = useState(60);
|
|
20
26
|
|
|
21
27
|
return (
|
|
22
28
|
<PageContainer
|
|
23
29
|
title="Slider"
|
|
24
|
-
subtitle="
|
|
30
|
+
subtitle="数値スライダー · 単一は number、range は [number, number] · onChange は逐次、onChangeComplete は確定時"
|
|
25
31
|
>
|
|
26
32
|
<Flex direction="col" gap="lg">
|
|
27
33
|
<Card>
|
|
28
34
|
<CardHeader>
|
|
29
35
|
<CardTitle level={2}>単一スライダー · 税率設定</CardTitle>
|
|
30
36
|
<CardDescription>
|
|
31
|
-
|
|
32
|
-
|
|
37
|
+
antd と同じ書き味: value に数値を渡し、onChange が数値を返す。tooltip.formatter は
|
|
38
|
+
吹き出しの表記であると同時に読み上げ (aria-valuetext) にもなる。
|
|
39
|
+
</CardDescription>
|
|
40
|
+
</CardHeader>
|
|
41
|
+
<CardContent>
|
|
42
|
+
<FormField id="tax-rate" label={`消費税率: ${taxRate}%`} helper="0% / 2% 刻みで選択">
|
|
43
|
+
<Slider
|
|
44
|
+
value={taxRate}
|
|
45
|
+
onChange={setTaxRate}
|
|
46
|
+
min={0}
|
|
47
|
+
max={10}
|
|
48
|
+
step={2}
|
|
49
|
+
name="tax_rate"
|
|
50
|
+
tooltip={{ formatter: (value) => `${value}%` }}
|
|
51
|
+
/>
|
|
52
|
+
</FormField>
|
|
53
|
+
</CardContent>
|
|
54
|
+
</Card>
|
|
55
|
+
|
|
56
|
+
<Card>
|
|
57
|
+
<CardHeader>
|
|
58
|
+
<CardTitle level={2}>レンジスライダー · 請求金額フィルタ</CardTitle>
|
|
59
|
+
<CardDescription>
|
|
60
|
+
range を明示すると、値が未到着でも [min, max] の 2 つのつまみで描画される。
|
|
61
|
+
再取得のような重い処理は onChangeComplete に置く。
|
|
33
62
|
</CardDescription>
|
|
34
63
|
</CardHeader>
|
|
35
64
|
<CardContent>
|
|
36
65
|
<Flex direction="col" gap="md">
|
|
37
66
|
<FormField
|
|
38
|
-
id="
|
|
39
|
-
label={
|
|
40
|
-
helper="0% / 8% (軽減税率) / 10% から選択"
|
|
67
|
+
id="amount-range"
|
|
68
|
+
label={`請求金額: ${yen(amountRange[0])} 〜 ${yen(amountRange[1])}`}
|
|
41
69
|
>
|
|
42
70
|
<Slider
|
|
43
|
-
|
|
44
|
-
|
|
71
|
+
range
|
|
72
|
+
value={amountRange}
|
|
73
|
+
onChange={setAmountRange}
|
|
74
|
+
onChangeComplete={setCommittedRange}
|
|
45
75
|
min={0}
|
|
46
|
-
max={
|
|
47
|
-
step={
|
|
48
|
-
|
|
49
|
-
|
|
76
|
+
max={1000000}
|
|
77
|
+
step={10000}
|
|
78
|
+
minStepsBetweenThumbs={1}
|
|
79
|
+
tooltip={{ formatter: yen }}
|
|
50
80
|
/>
|
|
51
81
|
</FormField>
|
|
82
|
+
<Text tone="muted" size="sm">
|
|
83
|
+
確定値 (onChangeComplete): {yen(committedRange[0])} 〜 {yen(committedRange[1])}
|
|
84
|
+
</Text>
|
|
52
85
|
</Flex>
|
|
53
86
|
</CardContent>
|
|
54
87
|
</Card>
|
|
55
88
|
|
|
56
89
|
<Card>
|
|
57
90
|
<CardHeader>
|
|
58
|
-
<CardTitle level={2}
|
|
91
|
+
<CardTitle level={2}>目盛りだけを値にする · step={"{null}"}</CardTitle>
|
|
59
92
|
<CardDescription>
|
|
60
|
-
|
|
61
|
-
|
|
93
|
+
marks と step={"{null}"} を組み合わせると、つまみは目盛り・min・max にしか止まらない。
|
|
94
|
+
dots は目盛りごとの点で、included の範囲内だけが濃くなる。
|
|
62
95
|
</CardDescription>
|
|
63
96
|
</CardHeader>
|
|
64
97
|
<CardContent>
|
|
65
|
-
<FormField
|
|
66
|
-
id="amount-range"
|
|
67
|
-
label={`請求金額: ${yen(amountRange[0])} 〜 ${yen(amountRange[1])}`}
|
|
68
|
-
>
|
|
98
|
+
<FormField id="plan" label={`料金プラン: ${plan}`} helper="無料 / 標準 / 上位 / 特別">
|
|
69
99
|
<Slider
|
|
70
|
-
value={
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
100
|
+
value={plan}
|
|
101
|
+
onChange={setPlan}
|
|
102
|
+
step={null}
|
|
103
|
+
dots
|
|
104
|
+
marks={{
|
|
105
|
+
0: "無料",
|
|
106
|
+
30: "標準",
|
|
107
|
+
70: "上位",
|
|
108
|
+
100: { style: { fontWeight: 700 }, label: "特別" },
|
|
75
109
|
}}
|
|
76
|
-
min={0}
|
|
77
|
-
max={1000000}
|
|
78
|
-
step={10000}
|
|
79
|
-
minStepsBetweenThumbs={1}
|
|
80
|
-
aria-label="請求金額範囲"
|
|
81
110
|
/>
|
|
82
111
|
</FormField>
|
|
83
112
|
</CardContent>
|
|
@@ -85,17 +114,17 @@ export default function Demo() {
|
|
|
85
114
|
|
|
86
115
|
<Card>
|
|
87
116
|
<CardHeader>
|
|
88
|
-
<CardTitle level={2}
|
|
117
|
+
<CardTitle level={2}>予算配分 · Radix 時代の書き方も有効</CardTitle>
|
|
89
118
|
<CardDescription>
|
|
90
|
-
|
|
91
|
-
|
|
119
|
+
number[] の value と onValueChange / onValueCommit はそのまま動く。name を付ければ
|
|
120
|
+
JavaScript なしでフォーム送信できる (つまみが複数なら name[])。
|
|
92
121
|
</CardDescription>
|
|
93
122
|
</CardHeader>
|
|
94
123
|
<CardContent>
|
|
95
124
|
<FormField
|
|
96
125
|
id="allocation"
|
|
97
126
|
label={`広告費配分: ${allocation[0]}%`}
|
|
98
|
-
helper=
|
|
127
|
+
helper={`残り ${100 - allocation[0]}% が運転資金へ充当されます`}
|
|
99
128
|
>
|
|
100
129
|
<Slider
|
|
101
130
|
value={allocation}
|
|
@@ -104,7 +133,7 @@ export default function Demo() {
|
|
|
104
133
|
max={100}
|
|
105
134
|
step={5}
|
|
106
135
|
name="ad_allocation"
|
|
107
|
-
|
|
136
|
+
marks={{ 0: "0%", 50: "50%", 100: "100%" }}
|
|
108
137
|
/>
|
|
109
138
|
</FormField>
|
|
110
139
|
</CardContent>
|
|
@@ -112,16 +141,65 @@ export default function Demo() {
|
|
|
112
141
|
|
|
113
142
|
<Card>
|
|
114
143
|
<CardHeader>
|
|
115
|
-
<CardTitle level={2}
|
|
144
|
+
<CardTitle level={2}>編集できるレンジ · range={"{{ editable: true }}"}</CardTitle>
|
|
116
145
|
<CardDescription>
|
|
117
|
-
|
|
118
|
-
|
|
146
|
+
レール上を押すとつまみが増え、Delete / Backspace で減る (minCount 〜 maxCount)。
|
|
147
|
+
included=false は「ここまで」を塗らない目盛り専用のレール。
|
|
119
148
|
</CardDescription>
|
|
120
149
|
</CardHeader>
|
|
121
150
|
<CardContent>
|
|
122
|
-
<
|
|
123
|
-
<
|
|
124
|
-
|
|
151
|
+
<ResponsiveGrid columns={{ base: 1, md: 2 }} gap="lg">
|
|
152
|
+
<FormField id="bands" label={`区切り: ${bands.join(" / ")}`}>
|
|
153
|
+
<Slider
|
|
154
|
+
range={{ editable: true, minCount: 1, maxCount: 4, draggableTrack: false }}
|
|
155
|
+
value={bands}
|
|
156
|
+
onChange={setBands}
|
|
157
|
+
step={5}
|
|
158
|
+
/>
|
|
159
|
+
</FormField>
|
|
160
|
+
<FormField id="scale" label="評価スケール (included={false})">
|
|
161
|
+
<Slider
|
|
162
|
+
defaultValue={50}
|
|
163
|
+
included={false}
|
|
164
|
+
marks={{ 0: "低", 50: "中", 100: "高" }}
|
|
165
|
+
/>
|
|
166
|
+
</FormField>
|
|
167
|
+
</ResponsiveGrid>
|
|
168
|
+
</CardContent>
|
|
169
|
+
</Card>
|
|
170
|
+
|
|
171
|
+
<Card>
|
|
172
|
+
<CardHeader>
|
|
173
|
+
<CardTitle level={2}>縦・逆向き・無効</CardTitle>
|
|
174
|
+
<CardDescription>
|
|
175
|
+
vertical は下が min、reverse は向きを入れ替える (矢印キーも一緒に反転)。 disabled
|
|
176
|
+
は配列でつまみ単位にもできる。
|
|
177
|
+
</CardDescription>
|
|
178
|
+
</CardHeader>
|
|
179
|
+
<CardContent>
|
|
180
|
+
<ResponsiveGrid columns={{ base: 1, md: 3 }} gap="lg">
|
|
181
|
+
<FormField id="volume-vertical" label={`音量 (縦): ${volume}`}>
|
|
182
|
+
<Slider
|
|
183
|
+
vertical
|
|
184
|
+
value={volume}
|
|
185
|
+
onChange={setVolume}
|
|
186
|
+
marks={{ 0: "0", 50: "50", 100: "100" }}
|
|
187
|
+
tooltip
|
|
188
|
+
/>
|
|
189
|
+
</FormField>
|
|
190
|
+
<FormField id="countdown" label="残り日数 (reverse)">
|
|
191
|
+
<Slider
|
|
192
|
+
reverse
|
|
193
|
+
defaultValue={30}
|
|
194
|
+
max={60}
|
|
195
|
+
step={5}
|
|
196
|
+
marks={{ 0: "0日", 30: "30日", 60: "60日" }}
|
|
197
|
+
/>
|
|
198
|
+
</FormField>
|
|
199
|
+
<FormField id="locked-rate" label="確定済み税率 (変更不可)">
|
|
200
|
+
<Slider value={10} disabled min={0} max={20} step={1} />
|
|
201
|
+
</FormField>
|
|
202
|
+
</ResponsiveGrid>
|
|
125
203
|
</CardContent>
|
|
126
204
|
</Card>
|
|
127
205
|
</Flex>
|
package/docs/feedback/dialog.tsx
CHANGED
|
@@ -109,8 +109,7 @@ export default function Demo() {
|
|
|
109
109
|
<CardContent>
|
|
110
110
|
<Dialog open={detailOpen} onOpenChange={setDetailOpen}>
|
|
111
111
|
<DialogTrigger asChild>
|
|
112
|
-
|
|
113
|
-
<Button data-axe-open variant="outline" size="sm">
|
|
112
|
+
<Button variant="outline" size="sm">
|
|
114
113
|
取引詳細を見る
|
|
115
114
|
</Button>
|
|
116
115
|
</DialogTrigger>
|
package/docs/feedback/sheet.tsx
CHANGED
|
@@ -213,8 +213,7 @@ export default function Demo() {
|
|
|
213
213
|
<CardContent>
|
|
214
214
|
<Sheet open={editOpen} onOpenChange={setEditOpen}>
|
|
215
215
|
<SheetTrigger asChild>
|
|
216
|
-
|
|
217
|
-
<Button data-axe-open variant="ghost" size="sm">
|
|
216
|
+
<Button variant="ghost" size="sm">
|
|
218
217
|
取引先を編集
|
|
219
218
|
</Button>
|
|
220
219
|
</SheetTrigger>
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { AppShell, Flex, PageContainer, Sidebar, Topbar } from "@godxjp/ui/layout";
|
|
3
|
+
import type { SidebarSectionProp } from "@godxjp/ui/layout";
|
|
4
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@godxjp/ui/data-display";
|
|
5
|
+
import { Button, Text } from "@godxjp/ui/general";
|
|
6
|
+
import {
|
|
7
|
+
Bell,
|
|
8
|
+
Building2,
|
|
9
|
+
FileText,
|
|
10
|
+
LayoutDashboard,
|
|
11
|
+
MessageSquare,
|
|
12
|
+
Plus,
|
|
13
|
+
Receipt,
|
|
14
|
+
Users,
|
|
15
|
+
} from "lucide-react";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* AppShell · grid states, one per URL.
|
|
19
|
+
*
|
|
20
|
+
* The shell's grid is keyed on four attributes — `data-sidebar`, `data-nav-rail(-position)`,
|
|
21
|
+
* `data-collapsed` and `data-topbar-span` — and every combination is a real product shape. This
|
|
22
|
+
* frame renders ONE AppShell in whichever state the query names, so a browser gate can walk all of
|
|
23
|
+
* them (`scripts/check-app-shell-narrow-grid.mjs`) without stacking several `main` landmarks on a
|
|
24
|
+
* single page:
|
|
25
|
+
*
|
|
26
|
+
* ?topbarSpan=content|full ?navRail=start|end|top|bottom ?collapsed=1 ?sidebar=none
|
|
27
|
+
* ?responsive=docked
|
|
28
|
+
*
|
|
29
|
+
* With no query it is `topbarSpan="full"` without a rail — the state gh#474 found collapsing
|
|
30
|
+
* `main` into a 170px implicit track below 900px, with the page actions laid out past the edge.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
const SECTIONS: SidebarSectionProp[] = [
|
|
34
|
+
{
|
|
35
|
+
label: "会計",
|
|
36
|
+
items: [
|
|
37
|
+
{ id: "dashboard", label: "ダッシュボード", icon: LayoutDashboard },
|
|
38
|
+
{ id: "journal", label: "仕訳", icon: FileText },
|
|
39
|
+
{ id: "invoices", label: "請求書", icon: Receipt },
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
label: "管理",
|
|
44
|
+
items: [
|
|
45
|
+
{ id: "partners", label: "取引先", icon: Building2 },
|
|
46
|
+
{ id: "users", label: "ユーザー", icon: Users },
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
type RailPosition = "start" | "end" | "top" | "bottom";
|
|
52
|
+
|
|
53
|
+
function readState() {
|
|
54
|
+
const params = new URLSearchParams(window.location.search);
|
|
55
|
+
const rail = params.get("navRail");
|
|
56
|
+
return {
|
|
57
|
+
topbarSpan: params.get("topbarSpan") === "content" ? ("content" as const) : ("full" as const),
|
|
58
|
+
navRail: (["start", "end", "top", "bottom"] as const).find((p) => p === rail) as
|
|
59
|
+
RailPosition | undefined,
|
|
60
|
+
collapsed: params.get("collapsed") === "1",
|
|
61
|
+
hasSidebar: params.get("sidebar") !== "none",
|
|
62
|
+
responsiveNavigation:
|
|
63
|
+
params.get("responsive") === "docked" ? ("docked" as const) : ("drawer" as const),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export default function Demo() {
|
|
68
|
+
const [{ topbarSpan, navRail, collapsed, hasSidebar, responsiveNavigation }] =
|
|
69
|
+
useState(readState);
|
|
70
|
+
const [activeId, setActiveId] = useState("dashboard");
|
|
71
|
+
const strip = navRail === "top" || navRail === "bottom";
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<AppShell
|
|
75
|
+
topbarSpan={topbarSpan}
|
|
76
|
+
responsiveNavigation={responsiveNavigation}
|
|
77
|
+
sidebarCollapsed={collapsed}
|
|
78
|
+
sidebar={
|
|
79
|
+
hasSidebar ? (
|
|
80
|
+
<Sidebar
|
|
81
|
+
activeId={activeId}
|
|
82
|
+
collapsed={collapsed}
|
|
83
|
+
onSelect={setActiveId}
|
|
84
|
+
sections={SECTIONS}
|
|
85
|
+
product={{ name: "CoreBooks", role: "株式会社アクメ" }}
|
|
86
|
+
/>
|
|
87
|
+
) : undefined
|
|
88
|
+
}
|
|
89
|
+
navRail={
|
|
90
|
+
navRail ? (
|
|
91
|
+
<Flex direction={strip ? "row" : "col"} gap="xs" align="center">
|
|
92
|
+
<Button variant="ghost" size="icon-sm" aria-label="会計">
|
|
93
|
+
<Receipt />
|
|
94
|
+
</Button>
|
|
95
|
+
<Button variant="ghost" size="icon-sm" aria-label="チャット">
|
|
96
|
+
<MessageSquare />
|
|
97
|
+
</Button>
|
|
98
|
+
</Flex>
|
|
99
|
+
) : undefined
|
|
100
|
+
}
|
|
101
|
+
navRailPosition={navRail}
|
|
102
|
+
topbar={
|
|
103
|
+
<Topbar
|
|
104
|
+
start={<Text weight="medium">CoreBooks</Text>}
|
|
105
|
+
end={
|
|
106
|
+
<Button variant="ghost" size="icon-sm" aria-label="通知">
|
|
107
|
+
<Bell />
|
|
108
|
+
</Button>
|
|
109
|
+
}
|
|
110
|
+
/>
|
|
111
|
+
}
|
|
112
|
+
>
|
|
113
|
+
<PageContainer
|
|
114
|
+
title="請求書"
|
|
115
|
+
subtitle="株式会社アクメ · 2026年5月"
|
|
116
|
+
extra={
|
|
117
|
+
<Flex gap="sm" wrap>
|
|
118
|
+
<Button size="sm" variant="outline">
|
|
119
|
+
取引先へ一括送信する
|
|
120
|
+
</Button>
|
|
121
|
+
<Button size="sm">
|
|
122
|
+
<Plus />
|
|
123
|
+
新しい請求書を作成する
|
|
124
|
+
</Button>
|
|
125
|
+
</Flex>
|
|
126
|
+
}
|
|
127
|
+
>
|
|
128
|
+
<Card>
|
|
129
|
+
<CardHeader>
|
|
130
|
+
<CardTitle level={2}>今月の請求</CardTitle>
|
|
131
|
+
<CardDescription>未送信 3 件 · 入金待ち 12 件</CardDescription>
|
|
132
|
+
</CardHeader>
|
|
133
|
+
<CardContent>
|
|
134
|
+
<Text tone="muted">
|
|
135
|
+
状態はクエリで切り替えます。どの状態でも 900px 以下では 1 列になり、main
|
|
136
|
+
は画面幅いっぱいに広がります。
|
|
137
|
+
</Text>
|
|
138
|
+
</CardContent>
|
|
139
|
+
</Card>
|
|
140
|
+
</PageContainer>
|
|
141
|
+
</AppShell>
|
|
142
|
+
);
|
|
143
|
+
}
|