@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.
Files changed (115) hide show
  1. package/README.md +4 -4
  2. package/dist/app/date-format-labels.d.ts +14 -2
  3. package/dist/app/date-format-labels.js +1 -1
  4. package/dist/app/date-formats.d.ts +14 -2
  5. package/dist/app/date-formats.js +9 -2
  6. package/dist/components/data-display/data-table.d.ts +8 -1
  7. package/dist/components/data-display/data-table.js +9 -2
  8. package/dist/components/data-display/scroll-area.d.ts +24 -4
  9. package/dist/components/data-display/scroll-area.js +34 -72
  10. package/dist/components/data-entry/cascader.js +8 -6
  11. package/dist/components/data-entry/checkbox.js +3 -1
  12. package/dist/components/data-entry/choice-hit-target.d.ts +24 -0
  13. package/dist/components/data-entry/choice-hit-target.js +12 -0
  14. package/dist/components/data-entry/control-surface.d.ts +8 -0
  15. package/dist/components/data-entry/control-surface.js +10 -1
  16. package/dist/components/data-entry/form-field.js +5 -4
  17. package/dist/components/data-entry/input.js +1 -1
  18. package/dist/components/data-entry/number-input.js +27 -6
  19. package/dist/components/data-entry/radio.js +4 -3
  20. package/dist/components/data-entry/search-select.js +225 -95
  21. package/dist/components/data-entry/select.d.ts +76 -14
  22. package/dist/components/data-entry/select.js +495 -163
  23. package/dist/components/data-entry/slider.d.ts +3 -11
  24. package/dist/components/data-entry/slider.js +582 -93
  25. package/dist/components/data-entry/switch.js +3 -1
  26. package/dist/components/feedback/dialog.js +2 -2
  27. package/dist/components/feedback/sheet.js +2 -22
  28. package/dist/components/navigation/dropdown-menu.d.ts +11 -3
  29. package/dist/components/navigation/dropdown-menu.js +190 -15
  30. package/dist/components/navigation/filter-bar.js +2 -1
  31. package/dist/components/navigation/index.d.ts +0 -3
  32. package/dist/components/navigation/index.js +0 -78
  33. package/dist/components/navigation/tabs.js +16 -4
  34. package/dist/components/ui/index.d.ts +0 -3
  35. package/dist/components/ui/index.js +0 -3
  36. package/dist/components/ui/input-otp.d.ts +1 -1
  37. package/dist/components/ui/segmented.js +3 -1
  38. package/dist/components/ui/tag-input.js +3 -5
  39. package/dist/i18n/messages/en.json +5 -1
  40. package/dist/i18n/messages/ja.json +5 -1
  41. package/dist/i18n/messages/vi.json +5 -1
  42. package/dist/lib/breakpoint-token.d.ts +8 -0
  43. package/dist/lib/breakpoint-token.js +29 -0
  44. package/dist/lib/select-options.d.ts +21 -0
  45. package/dist/lib/select-options.js +46 -0
  46. package/dist/props/components/data-display.prop.d.ts +17 -7
  47. package/dist/props/components/data-entry.prop.d.ts +323 -30
  48. package/dist/props/components/index.d.ts +1 -1
  49. package/dist/props/components/navigation.prop.d.ts +25 -1
  50. package/dist/props/registry.d.ts +69 -1
  51. package/dist/props/registry.js +75 -0
  52. package/dist/props/vocabulary/data.prop.d.ts +5 -0
  53. package/dist/props/vocabulary/index.d.ts +1 -1
  54. package/dist/styles/control.css +246 -28
  55. package/dist/styles/data-display-layout.css +18 -10
  56. package/dist/styles/focus-ring.css +28 -0
  57. package/dist/styles/fonts.css +88 -4
  58. package/dist/styles/form-layout.css +4 -0
  59. package/dist/styles/layout.css +2 -1
  60. package/dist/styles/navigation-layout.css +24 -238
  61. package/dist/styles/shell-layout.css +148 -139
  62. package/dist/styles/table-layout.css +12 -5
  63. package/dist/tokens/components/control.css +12 -3
  64. package/dist/tokens/components/data-display.css +0 -5
  65. package/dist/tokens/components/navigation.css +5 -5
  66. package/dist/tokens/components/scroll-area.css +7 -0
  67. package/docs/CONSUMER-RULES.md +7 -2
  68. package/docs/CUSTOMER-THEMING.md +25 -9
  69. package/docs/DATETIME.md +11 -2
  70. package/docs/FRAME-COVERAGE-REPORT.md +4 -7
  71. package/docs/SPACING.md +35 -5
  72. package/docs/TOKENS.md +1 -1
  73. package/docs/data-display/data-table/index.tsx +44 -3
  74. package/docs/data-display/popover.tsx +4 -6
  75. package/docs/data-display/scroll-area.tsx +51 -45
  76. package/docs/data-display/table.tsx +1 -1
  77. package/docs/data-entry/date-picker.tsx +2 -3
  78. package/docs/data-entry/input-otp.tsx +5 -2
  79. package/docs/data-entry/segmented-in-filter-row.tsx +77 -0
  80. package/docs/data-entry/segmented.tsx +40 -1
  81. package/docs/data-entry/select-matrix.tsx +1 -2
  82. package/docs/data-entry/select.tsx +108 -3
  83. package/docs/data-entry/slider.tsx +125 -47
  84. package/docs/feedback/dialog.tsx +1 -2
  85. package/docs/feedback/sheet.tsx +1 -2
  86. package/docs/layout/app-shell-states.tsx +143 -0
  87. package/docs/navigation/dropdown-menu.tsx +77 -6
  88. package/docs/navigation/tabs.tsx +72 -0
  89. package/docs/roadmap/ai-chat-components.md +1 -2
  90. package/docs/roadmap/parity-audit-data-entry.md +44 -33
  91. package/docs/roadmap/parity-audit-layout-navigation-general.md +304 -310
  92. package/docs/roadmap/parity-backlog.md +2 -3
  93. package/docs/roadmap/tree-components.md +0 -1
  94. package/package.json +25 -55
  95. package/scripts/_agent-setup.mjs +18 -0
  96. package/scripts/guinea-pig-skill.md +12 -6
  97. package/scripts/ui-audit.mjs +185 -7
  98. package/scripts/visual-audit-rules.mjs +0 -7
  99. package/scripts/visual-audit.mjs +6 -27
  100. package/dist/components/navigation/context-menu.d.ts +0 -21
  101. package/dist/components/navigation/context-menu.js +0 -149
  102. package/dist/components/navigation/menubar.d.ts +0 -28
  103. package/dist/components/navigation/menubar.js +0 -136
  104. package/dist/components/navigation/navigation-menu.d.ts +0 -10
  105. package/dist/components/navigation/navigation-menu.js +0 -91
  106. package/dist/components/ui/context-menu.d.ts +0 -1
  107. package/dist/components/ui/context-menu.js +0 -2
  108. package/dist/components/ui/menubar.d.ts +0 -1
  109. package/dist/components/ui/menubar.js +0 -2
  110. package/dist/components/ui/navigation-menu.d.ts +0 -1
  111. package/dist/components/ui/navigation-menu.js +0 -2
  112. package/docs/FRAME-A11Y-CI.md +0 -349
  113. package/docs/navigation/context-menu.tsx +0 -128
  114. package/docs/navigation/menubar.tsx +0 -141
  115. package/docs/navigation/navigation-menu.tsx +0 -158
@@ -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>
@@ -69,12 +70,11 @@ export default function Demo() {
69
70
  </CardDescription>
70
71
  </CardHeader>
71
72
  <CardContent>
72
- <Flex direction="row" align="center" gap="md">
73
+ <Flex direction="row" align="center" gap="md" wrap>
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" wrap>
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" wrap>
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>
@@ -100,7 +171,7 @@ export default function Demo() {
100
171
  </CardDescription>
101
172
  </CardHeader>
102
173
  <CardContent>
103
- <Flex direction="row" align="center" gap="md">
174
+ <Flex direction="row" align="center" gap="md" wrap>
104
175
  <span className="text-sm">
105
176
  現在のステータス:{" "}
106
177
  <strong>
@@ -46,6 +46,56 @@ const journalItems = [
46
46
  },
47
47
  ];
48
48
 
49
+ /**
50
+ * A 設定 screen shaped like the one gh#502 was filed from: a vertical strip beside a panel whose
51
+ * content does NOT collapse below about 200px (an action row of two buttons). That min-content is
52
+ * what starved the strip — measured at 393px before the fold, the strip was 8px wide with 0px of
53
+ * tab in it. `pnpm check:frame-geometry` sweeps this frame at 320/375/390 and fails on the inline
54
+ * overflow it produced; a demo whose panel holds one short paragraph proves nothing, because a
55
+ * paragraph's min-content is one character wide.
56
+ */
57
+ const settingItems = [
58
+ {
59
+ value: "general",
60
+ label: "基本設定",
61
+ content: (
62
+ <Flex direction="col" gap="sm">
63
+ <Text as="p">表示名・タイムゾーン・言語。</Text>
64
+ <Flex gap="sm">
65
+ <Button variant="outline">変更を破棄</Button>
66
+ <Button>保存する</Button>
67
+ </Flex>
68
+ </Flex>
69
+ ),
70
+ },
71
+ {
72
+ value: "members",
73
+ label: "メンバー",
74
+ content: (
75
+ <Flex direction="col" gap="sm">
76
+ <Text as="p">招待済 8 名 · 管理者 2 名。</Text>
77
+ <Flex gap="sm">
78
+ <Button variant="outline">権限を見る</Button>
79
+ <Button>招待する</Button>
80
+ </Flex>
81
+ </Flex>
82
+ ),
83
+ },
84
+ {
85
+ value: "billing",
86
+ label: "請求",
87
+ content: (
88
+ <Flex direction="col" gap="sm">
89
+ <Text as="p">次回請求日 2026年10月1日。</Text>
90
+ <Flex gap="sm">
91
+ <Button variant="outline">履歴を見る</Button>
92
+ <Button>支払方法</Button>
93
+ </Flex>
94
+ </Flex>
95
+ ),
96
+ },
97
+ ];
98
+
49
99
  /**
50
100
  * 20 saved views with real Japanese labels — a strip that is wider than 1920px, so it overflows at
51
101
  * EVERY width the browser gates sweep. `scripts/check-tabs-overflow-menu.mjs` measures this frame;
@@ -553,6 +603,28 @@ export default function Demo() {
553
603
  </Flex>
554
604
  </CardContent>
555
605
  </Card>
606
+
607
+ <Card>
608
+ <CardHeader>
609
+ <CardTitle level={2}>tabPlacement=&quot;start&quot; · 狭い画面での折り返し</CardTitle>
610
+ <CardDescription>
611
+ 縦のタブ列はパネルと同じインライン軸を共有するので、パネルの min-content
612
+ が画面の大半を占めると列が 0px
613
+ まで潰れ、開いているタブ以外へ行く手段が消える(gh#502)。
614
+ --tabs-placement-responsive-breakpoint-width(48rem)以下では start / end を top /
615
+ bottom へ折り返す。ロービングフォーカスの軸も一緒に切り替わる。
616
+ </CardDescription>
617
+ </CardHeader>
618
+ <CardContent>
619
+ <Tabs
620
+ id="antd-start-narrow"
621
+ defaultValue="general"
622
+ variant="line"
623
+ tabPlacement="start"
624
+ items={settingItems}
625
+ />
626
+ </CardContent>
627
+ </Card>
556
628
  </Flex>
557
629
  </PageContainer>
558
630
  );
@@ -4,7 +4,7 @@
4
4
  > **Naming:** when a component's identity is unclear, look it up at
5
5
  > <https://namethatui.com/?platform=web> before inventing a name.
6
6
  > **Contract:** `.claude/skills/godxjp-ui-component/SKILL.md` is the hard gate — MCP-first, real
7
- > primitives only, `t()` + `Intl`, WAI-ARIA APG + WCAG 2.2 AA + vitest-axe, logical CSS, controlled
7
+ > primitives only, `t()` + `Intl`, WAI-ARIA APG + WCAG 2.2 AA, logical CSS, controlled
8
8
  > vocabulary, semantic tokens, MCP catalog entry, real-screen docs page.
9
9
 
10
10
  The library has **zero** chat/AI components today (verified against `mcp/src/data/components.ts` —
@@ -187,7 +187,6 @@ Every component in the build set ships **all** of:
187
187
  `check:token-tiers`; control boxes come from the `--control-height` tier.
188
188
  4. Keys in `src/i18n/messages/en.json`, `vi.json`, `ja.json` — all three, no exceptions.
189
189
  5. Tests in `src/components/<group>/__tests__/`: a behavior test using `@testing-library/user-event`
190
- **and** a `<name>.a11y.test.tsx` with `expectNoA11yViolations` at **0 violations**.
191
190
  6. An `mcp/src/data/components.ts` entry (props / usage / useCases / related / example / rules) —
192
191
  `check:mcp-sync` and `check:mcp-orphans` must pass.
193
192
  7. A real-screen docs page under `docs/<group>/` (AppShell + PageContainer + real primitives), not
@@ -1,6 +1,12 @@
1
1
  # Ant Design parity — `data-entry` group
2
2
 
3
3
  > Audit pass, read-only, 2026-09-10. Method and ledger format: `antd-parity.md` §0 / §2.
4
+ > **Cập nhật 11/09/2026 — `Select` (§2.1).** Chủ dự án yêu cầu Select bám sát Ant Design 6, nên
5
+ > nhiều dòng `WONT-PORT` / `COVERED-ELSEWHERE` bên dưới ĐÃ BỊ ĐẢO và nay là `PRESENT`. Lý do cũ
6
+ > không sai về kỹ thuật; nó chỉ không còn là quyết định hiện hành. Hai dòng KHÔNG đảo, và vì sao:
7
+ > `variant: "underlined"` (docs/DESIGN-AUTHORITY.md nêu đích danh: SmartHR vẽ ô kín — đó là quyết
8
+ > định của design authority, không phải của bản kiểm này) và `virtual` (vẫn thiếu — xem dòng của nó).
9
+ >
4
10
  > Skipped by instruction: `TreeSelect`, `Segmented`, `TagInput` chip rendering, everything chat-shaped
5
11
  > (`ChatComposer`, `ChatSuggestion`). 45 catalog entries carry `group: "data-entry"`.
6
12
 
@@ -31,8 +37,9 @@ The five that matter, in order:
31
37
  3. **No option-list virtualization anywhere in `src/`** (`grep -rl 'virtual\|useVirtualizer\|react-window\|@tanstack/react-virtual' src/` → nothing).
32
38
  antd `Select virtual` is on by default; a 5 000-row `Select`/`Cascader` here renders 5 000 DOM
33
39
  nodes. Same root cause as the missing `List` in `list-masonry.md`. **P1.**
34
- 4. **`Slider` never exposes a formatted value to assistive tech** — `tooltip.formatter` paints an
35
- `aria-hidden` bubble and no `aria-valuetext`, so a ¥/%/件 slider announces a bare number. **P1 a11y.**
40
+ 4. ~~**`Slider` never exposes a formatted value to assistive tech.**~~ CLOSED — `tooltip.formatter`
41
+ is now also the thumb's `aria-valuetext` (`slider.tsx`, `slider-antd.test.tsx`), landed with the
42
+ move to react-aria-components.
36
43
  5. **`ColorPicker` is a native `<input type="color">` + hex box** and is the one control in the group
37
44
  with no `size`/`status`/`variant`/`allowClear`/`readOnly`, and no `presets`. It cannot express a
38
45
  brand palette, which is the ordinary enterprise use. **P1.**
@@ -65,24 +72,24 @@ divergence was from the component beside them. They were merged into `DatePicker
65
72
 
66
73
  `src/props/components/data-entry.prop.ts:941-1142`, `src/components/data-entry/search-select.tsx`.
67
74
 
68
- | Ant Design prop / behaviour | Status | Evidence | Verdict |
69
- | ------------------------------------------------------------------------------ | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
70
- | `virtual` — virtualized option list (default ON in antd) | `MISSING` | `grep -rl "virtual\|useVirtualizer\|react-window\|@tanstack/react-virtual" src/` → no files | Add `virtual?: boolean` + a windowed list. Shared work with `List` (`list-masonry.md`) — do it once. |
71
- | `fieldNames` — map `{label,value,options}` onto foreign row shapes | `MISSING` | `grep -n fieldNames src/props/components/data-entry.prop.ts` only `:1281` (Cascader), `:1362` (TreeSelect) | Add `fieldNames?: TreeFieldNamesProp`-shaped sibling. The spelling already exists on two neighbours; a Select that cannot eat `{id,name}` is the odd one out. |
72
- | `labelInValue` — report `{value,label}` instead of a bare value | `COVERED-ELSEWHERE` | `onValueChange?: (value, option?)` `:1091`, `:1110` | The option already rides the callback. No second dialect. |
73
- | `optionFilterProp` / `optionLabelProp` | `COVERED-ELSEWHERE` | `filterOption` `:1012`, `labelRender` `:954`, `optionRender` `:1031` | Function form is strictly more expressive than a prop-name string. |
74
- | `maxTagTextLength` — truncate each chip's text | `WONT-PORT` | trigger is a `<button>` with collapsed labels, `:1096-1104` | A character-count truncation is a text contract; use `maxTagCount` + `maxTagPlaceholder`, or CSS. |
75
- | `listHeight` — popup max height in px | `WONT-PORT` | `search-select.tsx:534` uses `collisionPadding` + available height | Pixel height is a design knob token (`--select-popup-*`), cardinal rule #44. |
76
- | `placement` (`bottomLeft`…) | `COVERED-ELSEWHERE` | Radix `PopoverContent` collision flip, `search-select.tsx:529-534` | Auto-placement beats a manual physical spelling (ground rule #4). |
77
- | `suffixIcon` / `removeIcon` / `loadingIcon` | `WONT-PORT` | `allowClear` object form already carries `clearIcon` `src/props/vocabulary/shared.prop.ts:105` | Icon-per-slot props are a token/`allowClear` job, not four more props. |
78
- | `getPopupContainer` / `styles` / `classNames` / `popupClassName` | `WONT-PORT` | ground rule #4 | Inline-style twins and portal escape hatches. |
79
- | `tagRender` in `mode="multiple"` | `WONT-PORT` | `:1096-1104` states the reason verbatim (button-in-button) | Documented refusal; `TagInput` owns `tagRender` where chips are legal. |
80
- | `onPopupScroll` | `COVERED-ELSEWHERE` | built-in infinite scroll + `renderLoadMore` `:1062` | |
81
- | `defaultActiveFirstOption` | `MISSING` | `grep -n defaultActiveFirstOption src/` → nothing | P2. Add as `defaultActiveFirstOption?: boolean`; a search box that pre-highlights row 1 makes Enter a one-key pick. |
82
- | `onInputKeyDown` | `MISSING` | grep → nothing | P2. Real for "Enter creates a new record" flows. |
83
- | `maxTagCount: "responsive"` | `WONT-PORT` | `src/props/vocabulary/shared.prop.ts:109-113` documents the refusal | Container queries instead. Already recorded. |
84
- | `variant: "underlined"` | `WONT-PORT` | `src/props/vocabulary/interaction.prop.ts:126-130` documents the refusal | SmartHR draws full boxes. Already recorded. |
85
- | `onSelect` / `onDeselect` / `maxTagPlaceholder` **exist but are undocumented** | `MISSING` (catalog) | props at `:1093`, `:1112-1114`, `:1124`; `sed -n '5560,5990p' mcp/src/data/components.ts \| grep -n "onSelect\|onDeselect\|maxTagPlaceholder"` → **no match** | Catalog drift: three shipped props the MCP never tells a consumer about. Add three catalog rows (`godxjp-ui-mcp-catalog-sync`). |
75
+ | Ant Design prop / behaviour | Status | Evidence | Verdict |
76
+ | ------------------------------------------------------------------------------ | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
77
+ | `virtual` — virtualized option list (default ON in antd) | `MISSING` | `grep -rl "virtual\|useVirtualizer\|react-window\|@tanstack/react-virtual" src/` → no files | Add `virtual?: boolean` + a windowed list. Shared work with `List` (`list-masonry.md`) — do it once. |
78
+ | `fieldNames` — map `{label,value,options}` onto foreign row shapes | `PRESENT` | `SelectFieldNamesProp`; `src/lib/select-options.ts` normalises rows, groups and foreign keys into one list for both branches | Done. Rows in a foreign shape need a cast at the call site, exactly as Cascader's and TreeSelect's do. |
79
+ | `labelInValue` — report `{value,label}` instead of a bare value | `PRESENT` | `SelectLabeledValueProp`; the adapter in `select.tsx` translates it in and out | Done. The earlier "no second dialect" ruling is REVERSED: the option riding the callback does not help the async EDIT form, which holds `{value,label}` and no option list yet. Labels that arrive on the value join the option list so the trigger can show them. |
80
+ | `optionFilterProp` | `PRESENT` | `SearchSelectBaseProp.optionFilterProp` + `showSearch.optionFilterProp` | Done. The function form is still more expressive, but naming one field is the two-word answer to the common case. `optionLabelProp` stays COVERED-ELSEWHERE (`labelRender`). |
81
+ | `maxTagTextLength` — truncate each chip's text | `PRESENT` | `chipLabel()` in `search-select.tsx`; test `select-antd-tags.test.tsx` | Done. Cuts what the TRIGGER shows; the value keeps its whole label. |
82
+ | `listHeight` — popup max height in px | `PRESENT` | writes `--select-content-max-height` / `--search-select-list-max-height` inline | Done, and it does NOT break rule #44: the height stays a token, and `listHeight` overrides that token for one instance — the same shape `popupMatchSelectWidth`'s number already had. |
83
+ | `placement` (`bottomLeft`…) | `PRESENT` | `SelectPlacementProp` `bottomStart` / `bottomEnd` / `topStart` / `topEnd` | Done, spelled LOGICALLY (the DESIGN-AUTHORITY override antd's physical names get everywhere else). Auto-placement with collision flipping is still the default. |
84
+ | `suffixIcon` / `prefix` | `PRESENT` | both branches; `suffixIcon={null}` removes the indicator (antd's own replacement for `showArrow`) | Done. `removeIcon` / `loadingIcon` stay WONT-PORT: `allowClear`'s object form already carries an icon, and the spinner is a token. |
85
+ | `getPopupContainer` / `styles` / `classNames` / `popupClassName` | `WONT-PORT` | ground rule #4 | Inline-style twins and portal escape hatches. |
86
+ | `tagRender` in `mode="multiple"` | `WONT-PORT` | `:1096-1104` states the reason verbatim (button-in-button) | Documented refusal; `TagInput` owns `tagRender` where chips are legal. |
87
+ | `onPopupScroll` | `PRESENT` | fires BESIDE the built-in infinite scroll, never instead of it | Done. The built-in pagination and `renderLoadMore` remain the reason most call sites need neither. |
88
+ | `defaultActiveFirstOption` | `MISSING` | `grep -n defaultActiveFirstOption src/` → nothing | P2. Add as `defaultActiveFirstOption?: boolean`; a search box that pre-highlights row 1 makes Enter a one-key pick. |
89
+ | `onInputKeyDown` | `MISSING` | grep → nothing | P2. Real for "Enter creates a new record" flows. |
90
+ | `maxTagCount: "responsive"` | `WONT-PORT` | `src/props/vocabulary/shared.prop.ts:109-113` documents the refusal | Container queries instead. Already recorded. |
91
+ | `variant: "underlined"` | `WONT-PORT` | `src/props/vocabulary/interaction.prop.ts:126-130` documents the refusal | SmartHR draws full boxes. Already recorded. |
92
+ | `onSelect` / `onDeselect` / `maxTagPlaceholder` **exist but are undocumented** | `MISSING` (catalog) | props at `:1093`, `:1112-1114`, `:1124`; `sed -n '5560,5990p' mcp/src/data/components.ts \| grep -n "onSelect\|onDeselect\|maxTagPlaceholder"` → **no match** | Catalog drift: three shipped props the MCP never tells a consumer about. Add three catalog rows (`godxjp-ui-mcp-catalog-sync`). |
86
93
 
87
94
  ### 2.2 `Cascader` — `CascaderProp` `src/props/components/data-entry.prop.ts:1253-1330`
88
95
 
@@ -108,18 +115,23 @@ divergence was from the component beside them. They were merged into `DatePicker
108
115
  | `onPressEnter` | `COVERED-ELSEWHERE` | commit-on-Enter is already the behaviour, `:237` | |
109
116
  | `decimalSeparator` as an explicit prop | `WONT-PORT` | should follow the locale, not a prop | Fixing the round-trip above removes the need. |
110
117
 
111
- ### 2.4 `Slider` — `SliderProp` `:547-568` · `src/components/data-entry/slider.tsx`
118
+ ### 2.4 `Slider` — `SliderProp` · `src/components/data-entry/slider.tsx`
112
119
 
113
- | Ant Design prop / behaviour | Status | Evidence | Verdict |
114
- | ------------------------------------------------------------------------------------------------ | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------- |
115
- | **`aria-valuetext` mirroring `tooltip.formatter`** (rc-slider `ariaValueTextFormatterForHandle`) | `MISSING` — **a11y** | `tooltipContent` returns the bare number `slider.tsx:33,35`; the bubble is `aria-hidden` `:152`; the `Thumb` `:138-157` sets no `aria-valuetext` | **P1.** A `¥50,000` / `3 件` slider announces "50000". Feed the resolved `tooltip.formatter` (or `Intl.NumberFormat`) into `aria-valuetext`. |
116
- | default tooltip / mark text is not `Intl`-formatted | `MISSING` — i18n | `tooltipContent` `:33` returns `value` verbatim; no `Intl.NumberFormat` in the file | P2 (same fix as the row above). |
117
- | `onChangeComplete` | `RENAMED` | Radix `onValueCommit`, inherited via `React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>` `:547` | No work. Record both names in the catalog. |
118
- | `vertical` | `RENAMED` | Radix `orientation="vertical"`, `slider.tsx:55,88,112` | No work. |
119
- | `reverse` | `PRESENT` (aliased) | `inverted ?? reverse`, `slider.tsx:115` | |
120
- | `keyboard: false` | `WONT-PORT` | — | Removing keyboard operation from a `role="slider"` fails WCAG 2.1.1. |
121
- | `range: { draggableTrack }` drag the whole span | `MISSING` | grep `draggableTrack` → nothing; Radix has no equivalent | P2. |
122
- | `tooltip.placement` / `getPopupContainer` / `autoAdjustOverflow` | `WONT-PORT` | ground rule #4 | Token + collision-aware positioning. |
120
+ CLOSED. `Slider` moved to `react-aria-components` and took the antd 6 API with it, so every row
121
+ this table used to hold is now either `PRESENT` or a recorded non-port:
122
+
123
+ | Ant Design prop / behaviour | Status |
124
+ | ------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------- |
125
+ | `aria-valuetext` mirroring `tooltip.formatter` | `PRESENT` — a string/number `formatter` result is written onto the thumb's input |
126
+ | `value`/`defaultValue`/`onChange`/`onChangeComplete` as antd spells them | `PRESENT` the Radix-era `number[]` + `onValueChange`/`onValueCommit` spelling still compiles |
127
+ | `step={null}`, `marks` object form, `dots`, `included`, `vertical` | `PRESENT` |
128
+ | `range: { editable, minCount, maxCount, draggableTrack }` | `PRESENT` |
129
+ | `disabled` as `boolean[]` | `PRESENT` |
130
+ | `tooltip.placement` / `autoAdjustOverflow` | `PRESENT` — logical sides, flip measured against the thumb's rect |
131
+ | `tooltip.getPopupContainer` | `WONT-PORT` — the bubble lives inside the thumb; nothing is portalled, so there is no container to choose |
132
+ | `keyboard: false` | `WONT-PORT` — removing keyboard operation from a `role="slider"` fails WCAG 2.1.1 |
133
+ | `classNames` / `styles` semantic slots | `WONT-PORT` — docs/WHAT-BELONGS-HERE.md, "lỗ kiểu dáng tự do" |
134
+ | default tooltip text is not `Intl`-formatted | `MISSING` — P2, unchanged: pass `tooltip.formatter` for ¥/%/件 |
123
135
 
124
136
  ### 2.5 `ColorPicker` — `ColorPickerProp` `:893-908` · `src/components/data-entry/color-picker.tsx` (114 lines)
125
137
 
@@ -281,7 +293,6 @@ Present: `count` (+ the legacy `max`), `allowHalf`, `allowClear`, `character` (n
281
293
 
282
294
  | # | Component | Gap | Cite |
283
295
  | --- | --------------------- | --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
284
- | 3 | `Slider` | No `aria-valuetext`; `tooltip.formatter` paints an `aria-hidden` bubble only. Formatted sliders announce a bare number. | `slider.tsx:33,138-157` |
285
296
  | 4 | `Select` / `Cascader` | No list virtualization anywhere in `src/` (antd `virtual` is on by default). | `grep -rl "virtual\|useVirtualizer\|react-window\|@tanstack/react-virtual" src/` → ∅ |
286
297
  | 5 | `ColorPicker` | No `presets`, and the only control in the group with no `size`/`status`/`variant`. | `data-entry.prop.ts:893-908` |
287
298
  | 6 | `PasswordStrength` | `role="img"` on a value meter instead of `role="meter"` + `aria-valuenow`. | `password-strength.tsx:74-76` |
@@ -300,7 +311,7 @@ Present: `count` (+ the legacy `max`), `allowHalf`, `allowClear`, `character` (n
300
311
  `Select`: `defaultActiveFirstOption`, `onInputKeyDown`. ·
301
312
  `Cascader`: `Cascader.Panel`. ·
302
313
  `NumberInput`: `onStep`. ·
303
- `Slider`: `Intl`-formatted default tooltip, `draggableTrack`. ·
314
+ `Slider`: `Intl`-formatted default tooltip (`draggableTrack` has landed). ·
304
315
  `ColorPicker`: `allowClear`+`onClear`, `readOnly`, `format`/`defaultFormat`/`onFormatChange`. ·
305
316
  `DatePicker`: `mode`+`onPanelChange`, `onOk`, `maxTagCount` for `multiple`, `format` as an
306
317
  array of accepted inputs, and — with `range` — `separator` (token) and `onCalendarChange`. ·