@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
|
@@ -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
|
+
}
|
|
@@ -32,6 +32,11 @@ export default function Demo() {
|
|
|
32
32
|
|
|
33
33
|
return (
|
|
34
34
|
<MobileShell
|
|
35
|
+
// `width="phone"` because this frame is READ ON A DESKTOP. The shell's own docstring already
|
|
36
|
+
// named this case on the block axis (`height="fill"` for "a phone view embedded in a wider
|
|
37
|
+
// page"); the inline axis had no answer until now, so this page drew a 1232px-wide handheld
|
|
38
|
+
// app with its four tab-bar destinations spread across the screen.
|
|
39
|
+
width="phone"
|
|
35
40
|
statusBar={
|
|
36
41
|
<>
|
|
37
42
|
<Text size="sm" weight="medium" tabular>
|
|
@@ -21,8 +21,9 @@ import {
|
|
|
21
21
|
import { MoreHorizontal } from "lucide-react";
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
-
* DropdownMenu —
|
|
24
|
+
* DropdownMenu — react-aria dropdown. Compose root/Trigger(asChild)/Content/Item/Separator.
|
|
25
25
|
* Use asChild on Trigger so a godx-ui Button is the real trigger (no double-button).
|
|
26
|
+
* `trigger` picks the gestures (click / hover / contextMenu) — antd's own prop.
|
|
26
27
|
* Composed only from real @godxjp/ui components.
|
|
27
28
|
*/
|
|
28
29
|
export default function Demo() {
|
|
@@ -34,7 +35,7 @@ export default function Demo() {
|
|
|
34
35
|
return (
|
|
35
36
|
<PageContainer
|
|
36
37
|
title="DropdownMenu"
|
|
37
|
-
subtitle="
|
|
38
|
+
subtitle="trigger: click / hover / contextMenu · Trigger asChild + Content + Item/Separator/Sub"
|
|
38
39
|
>
|
|
39
40
|
<Flex direction="col" gap="lg">
|
|
40
41
|
<Card>
|
|
@@ -73,8 +74,7 @@ export default function Demo() {
|
|
|
73
74
|
<Text>JE-0042 · 売上計上 ¥480,000</Text>
|
|
74
75
|
<DropdownMenu>
|
|
75
76
|
<DropdownMenuTrigger asChild>
|
|
76
|
-
|
|
77
|
-
<Button data-axe-open variant="ghost" size="icon-sm" aria-label="行アクション">
|
|
77
|
+
<Button variant="ghost" size="icon-sm" aria-label="行アクション">
|
|
78
78
|
<MoreHorizontal />
|
|
79
79
|
</Button>
|
|
80
80
|
</DropdownMenuTrigger>
|
|
@@ -90,6 +90,77 @@ export default function Demo() {
|
|
|
90
90
|
</CardContent>
|
|
91
91
|
</Card>
|
|
92
92
|
|
|
93
|
+
{/* antd `trigger` — which gestures open the menu */}
|
|
94
|
+
<Card>
|
|
95
|
+
<CardHeader>
|
|
96
|
+
<CardTitle level={2}>trigger · 右クリック(コンテキストメニュー)</CardTitle>
|
|
97
|
+
<CardDescription>
|
|
98
|
+
trigger={"{"}["contextMenu"]{"}"} は右クリックの位置にメニューを開き、
|
|
99
|
+
ブラウザ標準のメニューを抑止する。左クリックでは開かない。キーボードからは Shift+F10
|
|
100
|
+
または ContextMenu キーで開く(トリガーにフォーカスしてから)。専用の ContextMenu
|
|
101
|
+
コンポーネントは v23 で廃止され、これがその置き換え。
|
|
102
|
+
</CardDescription>
|
|
103
|
+
</CardHeader>
|
|
104
|
+
<CardContent>
|
|
105
|
+
<Flex direction="row" align="center" gap="md">
|
|
106
|
+
<DropdownMenu trigger={["contextMenu"]}>
|
|
107
|
+
<DropdownMenuTrigger asChild>
|
|
108
|
+
<Button variant="outline">仕訳 JE-0042 を右クリック</Button>
|
|
109
|
+
</DropdownMenuTrigger>
|
|
110
|
+
<DropdownMenuContent>
|
|
111
|
+
<DropdownMenuItem>編集</DropdownMenuItem>
|
|
112
|
+
<DropdownMenuItem>複製</DropdownMenuItem>
|
|
113
|
+
<DropdownMenuSeparator />
|
|
114
|
+
<DropdownMenuItem variant="destructive">削除</DropdownMenuItem>
|
|
115
|
+
</DropdownMenuContent>
|
|
116
|
+
</DropdownMenu>
|
|
117
|
+
</Flex>
|
|
118
|
+
</CardContent>
|
|
119
|
+
</Card>
|
|
120
|
+
|
|
121
|
+
<Card>
|
|
122
|
+
<CardHeader>
|
|
123
|
+
<CardTitle level={2}>trigger · ホバーで開く</CardTitle>
|
|
124
|
+
<CardDescription>
|
|
125
|
+
trigger={"{"}["hover"]{"}"} はポインタが乗ると mouseEnterDelay(既定 0.15
|
|
126
|
+
秒)後に開き、離れると mouseLeaveDelay(既定 0.1
|
|
127
|
+
秒)後に閉じる。トリガーとメニューの間の隙間を渡れるよう、閉じるのは取り消せる予約。
|
|
128
|
+
ホバーでフォーカスは移動せず、キーボードでは Enter / Space / ↓
|
|
129
|
+
で開くので、ポインタ専用にはならない。
|
|
130
|
+
</CardDescription>
|
|
131
|
+
</CardHeader>
|
|
132
|
+
<CardContent>
|
|
133
|
+
<Flex direction="row" align="center" gap="md">
|
|
134
|
+
<DropdownMenu trigger={["hover"]}>
|
|
135
|
+
<DropdownMenuTrigger asChild>
|
|
136
|
+
<Button variant="outline">エクスポート</Button>
|
|
137
|
+
</DropdownMenuTrigger>
|
|
138
|
+
<DropdownMenuContent>
|
|
139
|
+
<DropdownMenuItem>CSV</DropdownMenuItem>
|
|
140
|
+
<DropdownMenuItem>PDF</DropdownMenuItem>
|
|
141
|
+
</DropdownMenuContent>
|
|
142
|
+
</DropdownMenu>
|
|
143
|
+
<DropdownMenu trigger={["click", "contextMenu"]}>
|
|
144
|
+
<DropdownMenuTrigger asChild>
|
|
145
|
+
<Button variant="outline">クリックでも右クリックでも</Button>
|
|
146
|
+
</DropdownMenuTrigger>
|
|
147
|
+
<DropdownMenuContent>
|
|
148
|
+
<DropdownMenuItem>編集</DropdownMenuItem>
|
|
149
|
+
<DropdownMenuItem>複製</DropdownMenuItem>
|
|
150
|
+
</DropdownMenuContent>
|
|
151
|
+
</DropdownMenu>
|
|
152
|
+
<DropdownMenu disabled>
|
|
153
|
+
<DropdownMenuTrigger asChild>
|
|
154
|
+
<Button variant="outline">無効(disabled)</Button>
|
|
155
|
+
</DropdownMenuTrigger>
|
|
156
|
+
<DropdownMenuContent>
|
|
157
|
+
<DropdownMenuItem>編集</DropdownMenuItem>
|
|
158
|
+
</DropdownMenuContent>
|
|
159
|
+
</DropdownMenu>
|
|
160
|
+
</Flex>
|
|
161
|
+
</CardContent>
|
|
162
|
+
</Card>
|
|
163
|
+
|
|
93
164
|
{/* Status quick-change with RadioGroup */}
|
|
94
165
|
<Card>
|
|
95
166
|
<CardHeader>
|