@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.
Files changed (83) hide show
  1. package/README.md +4 -4
  2. package/dist/components/data-display/scroll-area.d.ts +24 -4
  3. package/dist/components/data-display/scroll-area.js +34 -72
  4. package/dist/components/data-entry/cascader.js +8 -6
  5. package/dist/components/data-entry/checkbox.js +2 -0
  6. package/dist/components/data-entry/choice-hit-target.d.ts +24 -0
  7. package/dist/components/data-entry/choice-hit-target.js +12 -0
  8. package/dist/components/data-entry/control-surface.d.ts +8 -0
  9. package/dist/components/data-entry/control-surface.js +10 -1
  10. package/dist/components/data-entry/form-field.js +3 -2
  11. package/dist/components/data-entry/radio.js +3 -2
  12. package/dist/components/data-entry/search-select.js +225 -95
  13. package/dist/components/data-entry/select.d.ts +76 -14
  14. package/dist/components/data-entry/select.js +495 -163
  15. package/dist/components/data-entry/slider.d.ts +3 -11
  16. package/dist/components/data-entry/slider.js +582 -93
  17. package/dist/components/data-entry/switch.js +2 -0
  18. package/dist/components/navigation/dropdown-menu.d.ts +11 -3
  19. package/dist/components/navigation/dropdown-menu.js +190 -15
  20. package/dist/components/navigation/index.d.ts +0 -3
  21. package/dist/components/navigation/index.js +0 -78
  22. package/dist/components/ui/index.d.ts +0 -3
  23. package/dist/components/ui/index.js +0 -3
  24. package/dist/components/ui/input-otp.d.ts +1 -1
  25. package/dist/components/ui/segmented.js +3 -1
  26. package/dist/components/ui/tag-input.js +3 -5
  27. package/dist/lib/select-options.d.ts +21 -0
  28. package/dist/lib/select-options.js +46 -0
  29. package/dist/props/components/data-display.prop.d.ts +9 -6
  30. package/dist/props/components/data-entry.prop.d.ts +323 -30
  31. package/dist/props/components/index.d.ts +1 -1
  32. package/dist/props/components/navigation.prop.d.ts +17 -0
  33. package/dist/props/registry.d.ts +63 -0
  34. package/dist/props/registry.js +69 -0
  35. package/dist/styles/control.css +205 -23
  36. package/dist/styles/data-display-layout.css +18 -10
  37. package/dist/styles/focus-ring.css +2 -2
  38. package/dist/styles/fonts.css +88 -4
  39. package/dist/styles/navigation-layout.css +11 -236
  40. package/dist/styles/shell-layout.css +144 -139
  41. package/dist/styles/table-layout.css +7 -3
  42. package/dist/tokens/components/control.css +4 -0
  43. package/dist/tokens/components/data-display.css +0 -5
  44. package/dist/tokens/components/navigation.css +3 -5
  45. package/dist/tokens/components/scroll-area.css +7 -0
  46. package/docs/CUSTOMER-THEMING.md +7 -1
  47. package/docs/FRAME-COVERAGE-REPORT.md +4 -7
  48. package/docs/data-display/data-table/index.tsx +27 -1
  49. package/docs/data-display/popover.tsx +4 -6
  50. package/docs/data-display/scroll-area.tsx +51 -45
  51. package/docs/data-entry/date-picker.tsx +2 -3
  52. package/docs/data-entry/input-otp.tsx +5 -2
  53. package/docs/data-entry/segmented.tsx +40 -1
  54. package/docs/data-entry/select-matrix.tsx +1 -2
  55. package/docs/data-entry/select.tsx +108 -3
  56. package/docs/data-entry/slider.tsx +125 -47
  57. package/docs/feedback/dialog.tsx +1 -2
  58. package/docs/feedback/sheet.tsx +1 -2
  59. package/docs/layout/app-shell-states.tsx +143 -0
  60. package/docs/navigation/dropdown-menu.tsx +75 -4
  61. package/docs/roadmap/parity-audit-data-entry.md +44 -33
  62. package/docs/roadmap/parity-audit-layout-navigation-general.md +304 -310
  63. package/docs/roadmap/parity-backlog.md +2 -3
  64. package/package.json +20 -44
  65. package/scripts/ui-audit.mjs +1 -1
  66. package/scripts/visual-audit-rules.mjs +0 -7
  67. package/scripts/visual-audit.mjs +6 -27
  68. package/dist/components/navigation/context-menu.d.ts +0 -21
  69. package/dist/components/navigation/context-menu.js +0 -149
  70. package/dist/components/navigation/menubar.d.ts +0 -28
  71. package/dist/components/navigation/menubar.js +0 -136
  72. package/dist/components/navigation/navigation-menu.d.ts +0 -10
  73. package/dist/components/navigation/navigation-menu.js +0 -91
  74. package/dist/components/ui/context-menu.d.ts +0 -1
  75. package/dist/components/ui/context-menu.js +0 -2
  76. package/dist/components/ui/menubar.d.ts +0 -1
  77. package/dist/components/ui/menubar.js +0 -2
  78. package/dist/components/ui/navigation-menu.d.ts +0 -1
  79. package/dist/components/ui/navigation-menu.js +0 -2
  80. package/docs/FRAME-A11Y-CI.md +0 -349
  81. package/docs/navigation/context-menu.tsx +0 -128
  82. package/docs/navigation/menubar.tsx +0 -141
  83. 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 — Radix Slider wrapper. value/defaultValue MUST be number[] not a plain
9
- * number. Single-thumb: [50], dual-thumb range: [20, 80].
10
- * Use onValueCommit (not onValueChange) for expensive side-effects.
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 = (n: number) =>
14
- new Intl.NumberFormat("ja-JP", { style: "currency", currency: "JPY" }).format(n);
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<number[]>([10]);
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="Numeric range slider · value/defaultValue must be number[] (single-thumb: [n], range: [min, max])"
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
- Single-thumb controlled slider. value={`[n]`} plain number breaks rendering.
32
- onValueChange fires on every drag; onValueCommit fires on release.
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="tax-rate"
39
- label={`消費税率: ${taxRate[0]}%`}
40
- helper="0% / 8% (軽減税率) / 10% から選択"
67
+ id="amount-range"
68
+ label={`請求金額: ${yen(amountRange[0])} 〜 ${yen(amountRange[1])}`}
41
69
  >
42
70
  <Slider
43
- value={taxRate}
44
- onValueChange={setTaxRate}
71
+ range
72
+ value={amountRange}
73
+ onChange={setAmountRange}
74
+ onChangeComplete={setCommittedRange}
45
75
  min={0}
46
- max={10}
47
- step={2}
48
- name="tax_rate"
49
- aria-label="消費税率"
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}>レンジスライダー · 請求金額フィルタ</CardTitle>
91
+ <CardTitle level={2}>目盛りだけを値にする · step={"{null}"}</CardTitle>
59
92
  <CardDescription>
60
- Dual-thumb range slider: value={`[min, max]`}. Use minStepsBetweenThumbs to prevent
61
- thumbs overlapping.
93
+ marks step={"{null}"} を組み合わせると、つまみは目盛り・minmax にしか止まらない。
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={amountRange}
71
- onValueChange={setAmountRange}
72
- onValueCommit={(v) => {
73
- // expensive filter refetch only on commit (pointer/key release)
74
- void v;
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}>予算配分スライダー</CardTitle>
117
+ <CardTitle level={2}>予算配分 · Radix 時代の書き方も有効</CardTitle>
89
118
  <CardDescription>
90
- step=5 for coarse granularity. Use name= to submit with a native form without JS
91
- wiring.
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="残り ${100 - allocation[0]}% が運転資金へ充当されます"
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
- aria-label="広告費配分"
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}>Disabled (read-only indicator)</CardTitle>
144
+ <CardTitle level={2}>編集できるレンジ · range={"{{ editable: true }}"}</CardTitle>
116
145
  <CardDescription>
117
- Pass disabled with a controlled value to show a non-interactive bar. Use Progress for
118
- pure status display.
146
+ レール上を押すとつまみが増え、Delete / Backspace で減る (minCount maxCount)。
147
+ included=false は「ここまで」を塗らない目盛り専用のレール。
119
148
  </CardDescription>
120
149
  </CardHeader>
121
150
  <CardContent>
122
- <FormField id="locked-rate" label="確定済み税率 (変更不可)">
123
- <Slider value={[10]} disabled min={0} max={20} step={1} aria-label="確定済み税率" />
124
- </FormField>
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>
@@ -109,8 +109,7 @@ export default function Demo() {
109
109
  <CardContent>
110
110
  <Dialog open={detailOpen} onOpenChange={setDetailOpen}>
111
111
  <DialogTrigger asChild>
112
- {/* data-axe-open: opened by check-frame-axe before its overlay scan. */}
113
- <Button data-axe-open variant="outline" size="sm">
112
+ <Button variant="outline" size="sm">
114
113
  取引詳細を見る
115
114
  </Button>
116
115
  </DialogTrigger>
@@ -213,8 +213,7 @@ export default function Demo() {
213
213
  <CardContent>
214
214
  <Sheet open={editOpen} onOpenChange={setEditOpen}>
215
215
  <SheetTrigger asChild>
216
- {/* data-axe-open: opened by check-frame-axe before its overlay scan. */}
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
+ }
@@ -21,8 +21,9 @@ import {
21
21
  import { MoreHorizontal } from "lucide-react";
22
22
 
23
23
  /**
24
- * DropdownMenu — Radix dropdown. Compose root/Trigger(asChild)/Content/Item/Separator.
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="Radix dropdown · Trigger asChild + Content + Item/Separator/Sub"
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
- {/* data-axe-open: opened by check-frame-axe before its overlay scan. */}
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={"{"}[&quot;contextMenu&quot;]{"}"} は右クリックの位置にメニューを開き、
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={"{"}[&quot;hover&quot;]{"}"} はポインタが乗ると 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>