@godxjp/ui 31.5.0 → 31.7.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/agent/START-HERE.md +5 -5
- package/agent/components/BranchScopePicker.json +5 -0
- package/agent/components/Breadcrumb.json +1 -1
- package/agent/components/Cascader.json +1 -1
- package/agent/components/DataTable.json +2 -2
- package/agent/components/InfiniteQueryState.json +6 -1
- package/agent/components/PageContainer.json +1 -1
- package/agent/components/Progress.json +12 -1
- package/agent/components/RangeTimeline.json +6 -0
- package/agent/components/RecordPicker.json +10 -0
- package/agent/components/Text.json +1 -1
- package/agent/components/Transfer.json +5 -0
- package/agent/components/Tree.json +21 -4
- package/agent/components/TreeSelect.json +1 -1
- package/agent/components.json +72 -13
- package/agent/index.json +5 -5
- package/agent/llms.txt +6 -6
- package/agent/tokens.json +12 -0
- package/dist/components/data-display/data-table.d.ts +3 -0
- package/dist/components/data-display/data-table.js +415 -370
- package/dist/components/data-display/progress.d.ts +16 -0
- package/dist/components/data-display/progress.js +17 -3
- package/dist/components/data-display/range-timeline.d.ts +20 -0
- package/dist/components/data-display/range-timeline.js +217 -197
- package/dist/components/data-display/tree.js +179 -23
- package/dist/components/data-entry/branch-scope-picker.d.ts +1 -0
- package/dist/components/data-entry/branch-scope-picker.js +2 -1
- package/dist/components/data-entry/cascader.js +4 -5
- package/dist/components/data-entry/record-picker.d.ts +2 -0
- package/dist/components/data-entry/record-picker.js +22 -3
- package/dist/components/data-entry/transfer.d.ts +1 -1
- package/dist/components/data-entry/transfer.js +5 -2
- package/dist/components/data-entry/tree-select.js +14 -5
- package/dist/components/feedback/tooltip.d.ts +21 -0
- package/dist/components/feedback/tooltip.js +101 -0
- package/dist/components/general/typography.js +30 -11
- package/dist/components/layout/breadcrumb-ellipsis.d.ts +16 -0
- package/dist/components/layout/breadcrumb-ellipsis.js +28 -0
- package/dist/components/layout/breadcrumb.js +16 -7
- package/dist/components/layout/page-container.js +29 -20
- package/dist/components/query/infinite-query-state.d.ts +1 -1
- package/dist/components/query/infinite-query-state.js +2 -1
- package/dist/contracts/measurement.json +1 -1
- package/dist/i18n/messages/en.json +18 -3
- package/dist/i18n/messages/ja.json +9 -3
- package/dist/i18n/messages/vi.json +9 -3
- package/dist/lib/hooks.d.ts +8 -4
- package/dist/lib/hooks.js +5 -2
- package/dist/lib/tree.d.ts +23 -0
- package/dist/lib/tree.js +29 -0
- package/dist/props/components/data-display.prop.d.ts +21 -2
- package/dist/props/components/data-entry.prop.d.ts +31 -4
- package/dist/props/components/query.prop.d.ts +8 -1
- package/dist/props/registry.d.ts +29 -6
- package/dist/props/registry.js +46 -4
- package/dist/props/vocabulary/data.prop.d.ts +32 -2
- package/dist/props/vocabulary/index.d.ts +2 -2
- package/dist/props/vocabulary/navigation.prop.d.ts +14 -0
- package/dist/styles/data-display-layout.css +52 -0
- package/dist/styles/layers.json +3 -2
- package/dist/styles/layout.css +22 -0
- package/dist/styles/table-layout.css +24 -1
- package/dist/tokens/components/navigation.css +2 -0
- package/dist/tokens/components/tree.css +2 -0
- package/docs/data-display/data-table/examples/server-paged.tsx +23 -0
- package/docs/data-display/data-table/index.md +2 -0
- package/docs/data-display/progress.tsx +24 -6
- package/docs/data-display/timeline.tsx +33 -0
- package/docs/data-display/tree.tsx +154 -0
- package/docs/data-entry/branch-scope-picker.tsx +6 -1
- package/docs/data-entry/record-picker.tsx +1 -0
- package/docs/data-entry/transfer.tsx +1 -0
- package/docs/general/typography.tsx +84 -1
- package/docs/i18n/messages/en.json +48 -1
- package/docs/i18n/messages/ja.json +47 -1
- package/docs/i18n/messages/vi.json +47 -1
- package/docs/navigation/breadcrumb.tsx +24 -0
- package/docs/query/infinite-query-state.tsx +5 -1
- package/docs/roadmap/tree-components.md +2 -1
- package/package.json +2 -2
- package/scripts/ui-audit.mjs +15 -5
package/agent/START-HERE.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
You are about to write code against a design system you did not author. This file is the whole
|
|
4
4
|
contract. Read it before you write JSX.
|
|
5
5
|
|
|
6
|
-
**This catalog describes `@godxjp/ui` 31.
|
|
6
|
+
**This catalog describes `@godxjp/ui` 31.7.0.** If the project you are editing has a different
|
|
7
7
|
version in its `package.json`, read the pinned catalog for THAT version instead
|
|
8
8
|
(`…/v<their-version>/agent/…`). A catalog newer than the installed package describes props that do
|
|
9
9
|
not exist yet; older, and it hides props that do. Neither failure announces itself.
|
|
@@ -52,14 +52,14 @@ Then ask it: `search_components`, `get_component`, `get_tokens`, `get_rule`, `li
|
|
|
52
52
|
names that **do not exist** and map to it — `Combobox`, `Autocomplete`, `CountrySelect` and
|
|
53
53
|
`SearchSelect` are all `Select`. If you are about to hand-roll something, search this field
|
|
54
54
|
first; it exists because that is the mistake.
|
|
55
|
-
2. `components/<Name>.json` — one file per component (1 KB–
|
|
55
|
+
2. `components/<Name>.json` — one file per component (1 KB–36 KB, median 6 KB), carrying its props,
|
|
56
56
|
its `importPath`, and its examples. Fetch only the handful you picked in step 1.
|
|
57
57
|
3. `rules.json` — 50 cardinal rules. The ones about raw HTML and hardcoded colour are not
|
|
58
58
|
style advice.
|
|
59
|
-
4. `tokens.json` —
|
|
59
|
+
4. `tokens.json` — 2100 design tokens, each tagged with its `tier`. **If you were handed a
|
|
60
60
|
brand, read the 211 `foundation` entries first** — `--primary`, `--background`,
|
|
61
61
|
`--radius`, `--font-size-base` are the handful everything else derives from. The
|
|
62
|
-
|
|
62
|
+
1785 `component` entries are per-part knobs; reach for one only when a role is
|
|
63
63
|
right everywhere except one component.
|
|
64
64
|
5. `anti-ai-tells.json` — 26 shapes that make generated UI look generated, each with the
|
|
65
65
|
fix. Read before you reach for a gradient hero or a wall of coloured chips.
|
|
@@ -145,7 +145,7 @@ has stopped following the brand.
|
|
|
145
145
|
|---|---|---|---|
|
|
146
146
|
| `foundation` | 211 | the seeds — `--primary`, `--background`, `--foreground`, `--radius`, `--font-size-base`, `--shadow-color`. Everything below is derived from these | **yes — this is the main road.** Handed a brand colour, this is where it goes: `:root { --primary: <H> <S>% <L>%; }` (HSL components, no `hsl()` wrapper) |
|
|
147
147
|
| `semantic` | 104 | named roles that follow the seeds — `--ring`, `--text-link`, `--primary-hover`, `--overlay-background` | only when the seed is right and ONE role must differ. That role then stops following a later brand change |
|
|
148
|
-
| `component` |
|
|
148
|
+
| `component` | 1785 | per-part knobs, `--{component}-{part}-{property}` | rarely. Most are declared `initial` with the real default at the call site — deliberate, so a scoped override re-resolves instead of freezing at `:root` |
|
|
149
149
|
|
|
150
150
|
A token whose `value` is `initial` is not empty and not broken: `initial` is the guaranteed-invalid
|
|
151
151
|
value, so the real default is computed where the element paints it. Set it and yours wins.
|
|
@@ -59,6 +59,11 @@
|
|
|
59
59
|
"name": "searchable",
|
|
60
60
|
"type": "boolean"
|
|
61
61
|
},
|
|
62
|
+
{
|
|
63
|
+
"description": "antd `notFoundContent` — shown when the branch SEARCH matches nothing (default: localized `dataEntry.branchScope.noMatches`). An empty `branches` list is `empty`'s job, not this.",
|
|
64
|
+
"name": "notFoundContent",
|
|
65
|
+
"type": "ReactNode"
|
|
66
|
+
},
|
|
62
67
|
{
|
|
63
68
|
"description": "Override the localized radio labels (e.g. domain wording like 全店舗).",
|
|
64
69
|
"name": "allLabel / selectedLabel",
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"name": "Breadcrumb",
|
|
6
6
|
"props": [
|
|
7
7
|
{
|
|
8
|
-
"description": "Array of { label, to?, menu? } — omit `to` on the last (current) segment. `menu` (Ant Design `BreadcrumbItemType.menu`) hangs a sibling picker off that segment: `{ items: { value, label, to?, disabled? }[], onSelect? }`. The segment then renders as a menu button, not a link — an entry with `to` becomes a real anchor inside the menu while keeping `role=\"menuitem\"`.",
|
|
8
|
+
"description": "Array of { label, to?, menu?, ellipsis? } — omit `to` on the last (current) segment. `ellipsis` (`boolean | { tooltip?: ReactNode }`, gh#1046; antd Breadcrumb has none, the shape is antd Typography's) keeps the trail on one line and cuts that segment's label with an ellipsis, showing the full label in a tooltip on hover and on keyboard focus of the crumb link; `{ tooltip: false }` drops the tooltip. Link and current segments only. `--breadcrumb-item-max-inline-size` (default `none`) caps such a segment. `menu` (Ant Design `BreadcrumbItemType.menu`) hangs a sibling picker off that segment: `{ items: { value, label, to?, disabled? }[], onSelect? }`. The segment then renders as a menu button, not a link — an entry with `to` becomes a real anchor inside the menu while keeping `role=\"menuitem\"`.",
|
|
9
9
|
"name": "items",
|
|
10
10
|
"required": true,
|
|
11
11
|
"type": "BreadcrumbItemProp[]"
|
|
@@ -152,7 +152,7 @@
|
|
|
152
152
|
"type": "\"SHOW_CHILD\" | \"SHOW_PARENT\""
|
|
153
153
|
},
|
|
154
154
|
{
|
|
155
|
-
"description": "antd `loadData` — lazy children. Called
|
|
155
|
+
"description": "antd `loadData` — lazy children. Called when a branch that has no children and isLeaf !== true is expanded, and never again once its promise resolves; push the fetched children into options. A rejected promise is forgotten, so the next activation of the branch asks again (gh#1041).",
|
|
156
156
|
"name": "loadData",
|
|
157
157
|
"type": "(selectedOptions: TreeOptionProp[]) => void | Promise<void>"
|
|
158
158
|
},
|
|
@@ -159,9 +159,9 @@
|
|
|
159
159
|
"type": "() => void"
|
|
160
160
|
},
|
|
161
161
|
{
|
|
162
|
-
"description": "Full row-selection configuration (antd rowSelection). Supersedes — and can be mixed with — selectable/selected/onSelectChange, which drive the same state. type:'radio' makes the column single-choice (no header checkbox at all). getCheckboxProps is the declared home for 'this row cannot be selected' (disabled) and for a per-row accessible name. preserveSelectedRowKeys keeps a key selected after its row leaves `data` (server paging / a filter), which is the only way a select-across-pages bulk action can be correct. selections adds bulk entries under the header checkbox (true = the built-in all · invert · none).",
|
|
162
|
+
"description": "Full row-selection configuration (antd rowSelection). Supersedes — and can be mixed with — selectable/selected/onSelectChange, which drive the same state. type:'radio' makes the column single-choice (no header checkbox at all). getCheckboxProps is the declared home for 'this row cannot be selected' (disabled) and for a per-row accessible name. preserveSelectedRowKeys keeps a key selected after its row leaves `data` (server paging / a filter), which is the only way a select-across-pages bulk action can be correct. selections adds bulk entries under the header checkbox (true = the built-in all · invert · none; a list mixes antd's DataTable.SELECTION_ALL / SELECTION_INVERT / SELECTION_NONE with custom entries in the order given). selectAllLabel names the header checkbox — say what it really selects (on a server-paged table: the page) instead of replacing it through columnTitle. matching (no antd equivalent; Gmail/Jira/GitHub) is the server-paged 'select all N matching' banner: once the whole page is ticked and total exceeds the page, a polite status above the header offers 'Select all N matching rows'; choosing it reports onSelectedChange(true) — send your FILTER, not the ids, for the bulk write — and while selected every row of any page shows ticked. Unticking a row or 'Clear selection' reports false. With matching set, the header checkbox defaults to 'Select all rows on this page'.",
|
|
163
163
|
"name": "rowSelection",
|
|
164
|
-
"type": "{ type?: 'checkbox'|'radio'; selectedRowKeys?: string[]; defaultSelectedRowKeys?: string[]; onChange?: (keys, rows) => void; getCheckboxProps?: (row) => { disabled?, 'aria-label'? }; preserveSelectedRowKeys?: boolean; selections?: true | { key, text, onSelect }[]; hideSelectAll?: boolean; columnTitle?: ReactNode }"
|
|
164
|
+
"type": "{ type?: 'checkbox'|'radio'; selectedRowKeys?: string[]; defaultSelectedRowKeys?: string[]; onChange?: (keys, rows) => void; getCheckboxProps?: (row) => { disabled?, 'aria-label'? }; preserveSelectedRowKeys?: boolean; selections?: true | ({ key, text, onSelect } | DataTable.SELECTION_ALL | DataTable.SELECTION_INVERT | DataTable.SELECTION_NONE)[]; hideSelectAll?: boolean; columnTitle?: ReactNode; selectAllLabel?: string; matching?: { total: number; selected: boolean; onSelectedChange: (selected: boolean) => void } }"
|
|
165
165
|
},
|
|
166
166
|
{
|
|
167
167
|
"description": "Expandable detail rows (antd expandable). Supplying expandedRowRender adds a leading expand column before the selection column and renders the panel in a real <tr> spanning every column, so the table's grid semantics survive. rowExpandable gates the affordance per row; expandedRowKeys + onExpandedRowsChange make it controlled.",
|
|
@@ -27,6 +27,11 @@
|
|
|
27
27
|
"name": "children",
|
|
28
28
|
"required": true,
|
|
29
29
|
"type": "(flat, helpers) => ReactNode"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"description": "Idle text of the built-in load-more button (default: localized `query.loadMore`, 「さらに読み込む」) — e.g. 「さらに表示」「さらに古い版を表示」. The button, its pending label and disabled-while-fetching stay the component's. Ignored when `loadMore` replaces the footer.",
|
|
33
|
+
"name": "loadMoreLabel",
|
|
34
|
+
"type": "ReactNode"
|
|
30
35
|
}
|
|
31
36
|
],
|
|
32
37
|
"related": [
|
|
@@ -43,7 +48,7 @@
|
|
|
43
48
|
"DO: Always pass `skeleton` (e.g. `<SkeletonTable />` or `<SkeletonStat />`). It shows on initial `isPending`, on refetch-after-error, and whenever `data` is absent. Never show a blank area while loading.",
|
|
44
49
|
"DO: Pass `empty` (an `<EmptyState>` node) to handle the zero-results case — without it the children render-prop is called with an empty array and you get a silent blank screen. Provide a custom `isEmpty` only when `TFlat` is not an array.",
|
|
45
50
|
"DO: Let errors remain cause-aware. Retry is automatic only for classified transient/network/5xx failures. Unknown errors do not get a blind retry unless `showRetry` or `onRetry` is explicitly supplied; a 401 is handled by the app-root `AuthExpiryProvider` (auto, once, skeleton + live region) or, without one, by the `onAuthError` sign-in button; raw backend/token text is never rendered.",
|
|
46
|
-
"DON'T: Hand-roll a load-more button. The component renders a default centered outline Button when `hasNextPage` is true.
|
|
51
|
+
"DON'T: Hand-roll a load-more button. The component renders a default centered outline Button when `hasNextPage` is true. Rename it with `loadMoreLabel` (keeps the pending state); replace it only via `loadMore` (custom node) or `showLoadMore={false}` (hide entirely). Never call `query.fetchNextPage()` outside the component for pagination.",
|
|
47
52
|
"DON'T: Use `InfiniteQueryState` for a `useQuery` result — it expects `UseInfiniteQueryResult` shape (`pages`, `hasNextPage`, `fetchNextPage`, `isFetchingNextPage`). For regular `useQuery` use `DataState` instead.",
|
|
48
53
|
"DON'T: Confuse the two generics: `TPage` is the raw page shape from the API, `TFlat` is what `flatten` returns (usually `TItem[]`). The `children` render-prop receives `TFlat`, not `TPage`. Pass `isEmpty` if `TFlat` is not a plain array so empty detection works correctly."
|
|
49
54
|
],
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"type": "ReactNode"
|
|
57
57
|
},
|
|
58
58
|
{
|
|
59
|
-
"description": "Ordered trail of { label, to? } segments above the title.",
|
|
59
|
+
"description": "Ordered trail of { label, to?, ellipsis? } segments above the title. `ellipsis: true` on a segment keeps the trail on one line and cuts that label with an ellipsis, the full label in a tooltip on hover and on keyboard focus of the crumb link — same contract as `Breadcrumb` items.",
|
|
60
60
|
"name": "breadcrumb",
|
|
61
61
|
"type": "BreadcrumbItemProp[]"
|
|
62
62
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"example": "import { Progress } from \"@godxjp/ui/data-display\";\n\n<Progress value={pct} label={pct + \"% 使用中\"} tone={pct >= 80 ? \"warning\" : \"success\"} />\n<Progress value={252} over label=\"252% 積載\" />\n<Progress\n segments={[\n { value: 2, tone: \"destructive\", label: \"期限超過\" },\n { value: 3, tone: \"warning\", label: \"期限間近\" },\n { value: 12, tone: \"success\", label: \"対応済\" },\n ]}\n aria-labelledby={companyNameId}\n/>",
|
|
2
|
+
"example": "import { Progress } from \"@godxjp/ui/data-display\";\n\n<Progress value={pct} label={pct + \"% 使用中\"} tone={pct >= 80 ? \"warning\" : \"success\"} />\n<Progress value={252} over label=\"252% 積載\" />\n<Progress\n segments={[\n { value: 2, tone: \"destructive\", label: \"期限超過\" },\n { value: 3, tone: \"warning\", label: \"期限間近\" },\n { value: 12, tone: \"success\", label: \"対応済\" },\n ]}\n aria-labelledby={companyNameId}\n/>\n<Progress\n segments={[\n { value: 3, tone: \"success\", label: \"合格\" },\n { value: 1, tone: \"destructive\", label: \"失敗\" },\n ]}\n total={400}\n remainderLabel=\"未実施\"\n/>",
|
|
3
3
|
"group": "data-display",
|
|
4
4
|
"importPath": "@godxjp/ui/data-display",
|
|
5
5
|
"name": "Progress",
|
|
@@ -15,6 +15,16 @@
|
|
|
15
15
|
"name": "segments",
|
|
16
16
|
"type": "{ value: number; tone: \"success\" | \"warning\" | \"destructive\"; label: string }[]"
|
|
17
17
|
},
|
|
18
|
+
{
|
|
19
|
+
"description": "BREAKDOWN mode: the WHOLE the slices are drawn against, in the same unit as their values. Omit it and the whole is the sum of the slices (the bar is always full). Pass it when part of the whole has no state yet — 3 passed of 400 test cases — and the rest stays the neutral TRACK, the antd `percent` model where the unfilled track is the remainder. The remainder is spoken in the role=\"img\" name, Intl-formatted in the active locale. A total below the slice sum is ignored (the sum wins), so slices never overflow.",
|
|
20
|
+
"name": "total",
|
|
21
|
+
"type": "number"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"description": "BREAKDOWN mode, with `total`: what the remainder is called in the spoken breakdown (e.g. 未実施). Defaults to the catalogue's Remaining / 残り / Còn lại.",
|
|
25
|
+
"name": "remainderLabel",
|
|
26
|
+
"type": "string"
|
|
27
|
+
},
|
|
18
28
|
{
|
|
19
29
|
"description": "Text label beside/below the bar; it also becomes the accessible name. Pass `aria-labelledby` instead when the name is ALREADY on screen (a row's company name, a card heading) — the bar then borrows it rather than repeating it.",
|
|
20
30
|
"name": "label",
|
|
@@ -64,6 +74,7 @@
|
|
|
64
74
|
"DON'T pass children or sub-components — Progress is a single self-contained element (track + bar + label). The `label` prop is the only text injection point; don't wrap it in a custom parent div to add a label alongside it.",
|
|
65
75
|
"DON'T hand-roll a stacked bar out of three divs to show a part-to-whole split — pass `segments`. Hand-rolled slices need a hex fill, an arbitrary height and an arbitrary radius, which ui-audit blocks three ways (no-arbitrary-hex, no-arbitrary-size, no-arbitrary-radius), and they leave the picture with no accessible name at all.",
|
|
66
76
|
"DON'T convert segment amounts to percentages yourself — pass the raw counts. The component divides by the total, so the slices always sum to the whole; pre-rounded percentages do not.",
|
|
77
|
+
"DO pass `total` when part of the whole has no state yet (a test run: 合格 3 · 失敗 1 of 400) — the rest stays track and is read out as `remainderLabel` (e.g. \"未実施\"). Leaving it out makes 3 passed of 400 fill the whole bar green.",
|
|
67
78
|
"DO pair a breakdown with `Legend` so each tone is spelled out in words once, instead of repeating the labels on every bar.",
|
|
68
79
|
"DON'T use Progress for editable numeric input or range selection — it has no callbacks, no interactivity, and no form `name` prop. Use Slider (bounded range input) or Input (free-form number) for data-entry scenarios."
|
|
69
80
|
],
|
|
@@ -64,6 +64,12 @@
|
|
|
64
64
|
"description": "Fires with the next expanded parent ids when a disclosure is toggled, for controlled and uncontrolled timelines alike.",
|
|
65
65
|
"name": "onExpandedValuesChange",
|
|
66
66
|
"type": "(values: string[]) => void"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"defaultValue": "false",
|
|
70
|
+
"description": "antd Table `sticky` — keep the axis header (bands + ticks) on screen while the PAGE scrolls a long schedule. `offsetHeader` is px from the top of the scrolling viewport (the height of a fixed app topbar). The header moves out of the horizontal scroller and follows its scrollLeft; the section becomes `overflow: clip` and the body scroller takes the keyboard tab stop. Like antd, it needs no clipping ancestor between the timeline and the page scroller: `Card` is `overflow: hidden`, so a sticky timeline goes in the page as its own section, not inside a Card. antd's `offsetScroll` / `getContainer` (sticky horizontal scrollbar) are not ported.",
|
|
71
|
+
"name": "sticky",
|
|
72
|
+
"type": "boolean | { offsetHeader?: number }"
|
|
67
73
|
}
|
|
68
74
|
],
|
|
69
75
|
"rules": [],
|
|
@@ -82,6 +82,16 @@
|
|
|
82
82
|
"name": "dialogTitle",
|
|
83
83
|
"type": "string"
|
|
84
84
|
},
|
|
85
|
+
{
|
|
86
|
+
"description": "antd `notFoundContent` — shown when the search finds nothing, in the dropdown shape and the dialog alike (default: localized `dataEntry.recordPicker.empty`). Say WHAT has no match, e.g. 「該当するファイルはありません」.",
|
|
87
|
+
"name": "notFoundContent",
|
|
88
|
+
"type": "ReactNode"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"description": "Text of the dialog's load-more button (default: localized `dataEntry.recordPicker.more`). Only the label — the button still appears only while the server returns a `nextCursor`.",
|
|
92
|
+
"name": "loadMoreLabel",
|
|
93
|
+
"type": "ReactNode"
|
|
94
|
+
},
|
|
85
95
|
{
|
|
86
96
|
"description": "Control height of the trigger, on the shared control ladder.",
|
|
87
97
|
"name": "size",
|
|
@@ -132,7 +132,7 @@
|
|
|
132
132
|
"type": "boolean | { text, editing, icon, tooltip, onStart, onChange, onCancel, onEnd, maxLength, autoSize, triggerType, enterIcon, tabIndex }"
|
|
133
133
|
},
|
|
134
134
|
{
|
|
135
|
-
"description": "Single-line truncation, antd's spelling. antd drops `rows` / `expandable` / `onExpand` on `Text` — an inline run has no second line to expand into — and that omission is ported; reach for `Paragraph` when you want them. It is the SAME axis as `truncate` / `clamp` and OUTRANKS both (dev builds warn), because it is the only spelling that can also carry a suffix or a tooltip.",
|
|
135
|
+
"description": "Single-line truncation, antd's spelling. antd drops `rows` / `expandable` / `onExpand` on `Text` — an inline run has no second line to expand into — and that omission is ported; reach for `Paragraph` when you want them. It is the SAME axis as `truncate` / `clamp` and OUTRANKS both (dev builds warn), because it is the only spelling that can also carry a suffix or a tooltip. `tooltip: true` (the children) or a node shows the full text in a Tooltip ONLY while the run is actually clipped — on pointer hover, and on keyboard focus of the Text itself (`asChild` link) or of the nearest focusable control around it (a Tree `treeitem`, a DataTable sort button, a link); the Text never becomes a tab stop of its own and its accessible name stays the full text. With `asChild` the child element is the truncated box (one `<a>`, not `<a><a>`). A `<Text ellipsis>` in `ColumnDef.header` truncates inside its column like a cell.",
|
|
136
136
|
"name": "ellipsis",
|
|
137
137
|
"type": "boolean | { suffix, symbol, defaultExpanded, expanded, onEllipsis, tooltip }"
|
|
138
138
|
},
|
|
@@ -109,6 +109,11 @@
|
|
|
109
109
|
"name": "onSelectChange",
|
|
110
110
|
"type": "(sourceSelectedKeys: string[], targetSelectedKeys: string[]) => void"
|
|
111
111
|
},
|
|
112
|
+
{
|
|
113
|
+
"description": "antd `locale`, ported for `notFoundContent` only: what an empty or search-emptied pane shows (default: localized `dataEntry.transfer.empty`). A `[source, target]` pair sets each pane separately, as in antd.",
|
|
114
|
+
"name": "locale",
|
|
115
|
+
"type": "{ notFoundContent?: ReactNode | [ReactNode, ReactNode] }"
|
|
116
|
+
},
|
|
112
117
|
{
|
|
113
118
|
"description": "Fires when items move between panels; you own `targetKeys` state.",
|
|
114
119
|
"name": "onValueChange",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"type": "boolean"
|
|
87
87
|
},
|
|
88
88
|
{
|
|
89
|
-
"description": "Lazy children (antd `loadData`). Called
|
|
89
|
+
"description": "Lazy children (antd `loadData`). Called when a branch with no `children` and `isLeaf !== true` is expanded, and never again once its promise RESOLVES; a Skeleton row and `aria-busy` cover the wait. Push the fetched children into `treeData`. A REJECTED promise is not a load (rc-tree, gh#1041): the branch folds back shut (uncontrolled expansion) and the next expand asks again, up to 10 attempts.",
|
|
90
90
|
"name": "loadData",
|
|
91
91
|
"type": "(node: TreeNodeProp) => void | Promise<void>"
|
|
92
92
|
},
|
|
@@ -95,6 +95,22 @@
|
|
|
95
95
|
"name": "titleRender",
|
|
96
96
|
"type": "(node: TreeNodeProp) => ReactNode"
|
|
97
97
|
},
|
|
98
|
+
{
|
|
99
|
+
"description": "Highlight the nodes this returns true for (antd `filterTreeNode`, gh#1043) — the match of a search box above the tree. Matching rows are MARKED, not hidden: `data-filter-node=\"true\"`, the label in `--tree-node-filter-foreground` (default `hsl(var(--primary))`) at the medium weight, plus sr-only \"matches the filter\" text. Outline, keyboard and ARIA are unchanged. To also open the branches that hold a match, drive `expandedValues`.",
|
|
100
|
+
"name": "filterTreeNode",
|
|
101
|
+
"type": "(node: TreeNodeProp) => boolean"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"description": "Viewport height in px (antd `height`, gh#1042). The tree scrolls inside it and, unless `virtual={false}`, renders only the rows in view plus a small overscan — the windowed rows stay a flat run of treeitems whose `aria-level`/`aria-setsize`/`aria-posinset` still describe the whole outline. Rows must share one height (the `size` tier).",
|
|
105
|
+
"name": "height",
|
|
106
|
+
"type": "number"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"defaultValue": "true",
|
|
110
|
+
"description": "Set `false` to keep the `height` viewport but render every row (antd `virtual`).",
|
|
111
|
+
"name": "virtual",
|
|
112
|
+
"type": "boolean"
|
|
113
|
+
},
|
|
98
114
|
{
|
|
99
115
|
"defaultValue": "false",
|
|
100
116
|
"description": "Draw the connector rails between a parent and its children (antd `showLine`). Off by default — a rail is chrome, and chrome defaults quiet.",
|
|
@@ -152,7 +168,7 @@
|
|
|
152
168
|
"TreeSelect — the same hierarchy INSIDE a Popover, as a form field. Use TreeSelect when the answer is a value in a form; use Tree when the hierarchy itself is the page.",
|
|
153
169
|
"Cascader — a path picker across columns. Use it when the user walks one path to a leaf; use Tree when several branches are open at once.",
|
|
154
170
|
"Accordion — single-level disclosure with rich panel content. It is not a hierarchy and has no tree keyboard model.",
|
|
155
|
-
"ScrollArea —
|
|
171
|
+
"ScrollArea — not needed around Tree: pass `height`, and the tree is its own (windowed) scroll viewport."
|
|
156
172
|
],
|
|
157
173
|
"rules": [
|
|
158
174
|
2,
|
|
@@ -172,8 +188,9 @@
|
|
|
172
188
|
"DON'T nest a Button, Checkbox, Link or any focusable control inside a node label. A tree item owns exactly ONE tab stop; the disclosure triangle and the tick box are decorative glyphs for that reason. Put row actions in a sibling column outside the tree, or open a detail pane on selection.",
|
|
173
189
|
"DON'T hand-roll an indented `<ul>` (or a NavList / ListRow stack with a per-depth margin) for a hierarchy. A flat indented list only LOOKS like a tree: no expand/collapse, no `role=\"tree\"`, no keyboard model, no selection contract. `TreeList` was exactly that list and was REMOVED in 21.0.0 — Tree is what replaced it, and it is the one to reach for whenever nodes expand, collapse or are keyboard-navigated.",
|
|
174
190
|
"DO pass `divided` when the tree IS the navigation of a page — a wiki/document outline or a section index sitting in a `Card` (`Card` > `CardContent flush` > `Tree divided`). Without a rule the rows run together and the outline reads as one block; with it, it reads as the ruled list ListRow and Table already give a flat list. Retint it per theme with `--tree-divider-color`, never with a per-page utility class.",
|
|
175
|
-
"DO
|
|
176
|
-
"DO push fetched children into `treeData` from `loadData`; the tree calls it once per node and shows a Skeleton row until the data lands."
|
|
191
|
+
"DO pass `height` for a long tree (antd `height` + `virtual`): the tree scrolls inside that height and keeps only the rows in view in the DOM, so a 421-child level renders a few dozen rows. Do not wrap it in `ScrollArea` as well — the tree is its own viewport.",
|
|
192
|
+
"DO push fetched children into `treeData` from `loadData`; the tree calls it once per node that loads and shows a Skeleton row until the data lands. Reject the promise on failure — the branch folds shut and the next expand retries.",
|
|
193
|
+
"DON'T wait for a paged \"load more\" node — antd's Tree has none, and `height` covers a long list. If the API itself is paged, append a leaf node such as `{ value: `${parent}::more`, label: t(\"…load more\"), isLeaf: true }` to the loaded children and fetch the next page from `onValueChange` when it is selected: it is a real treeitem, so it is keyboard-reachable and announced."
|
|
177
194
|
],
|
|
178
195
|
"useCases": [
|
|
179
196
|
"A permission tree: modules → resources → actions with tri-state checkboxes, where ticking a module ticks everything under it and a partly-granted module shows the dash.",
|
|
@@ -179,7 +179,7 @@
|
|
|
179
179
|
"type": "boolean"
|
|
180
180
|
},
|
|
181
181
|
{
|
|
182
|
-
"description": "antd `loadData` — lazy children. Called
|
|
182
|
+
"description": "antd `loadData` — lazy children. Called when a node that has no children and isLeaf !== true is expanded, and never again once its promise resolves; push the fetched children into treeData. A rejected promise folds the branch shut and the next expand asks again, up to 10 attempts (rc-tree, gh#1041). Such a node still reads as expandable (aria-expanded + a working expander).",
|
|
183
183
|
"name": "loadData",
|
|
184
184
|
"type": "(node: TreeOptionProp) => void | Promise<void>"
|
|
185
185
|
},
|
package/agent/components.json
CHANGED
|
@@ -590,6 +590,12 @@
|
|
|
590
590
|
"description": "Fires with the next expanded parent ids when a disclosure is toggled, for controlled and uncontrolled timelines alike.",
|
|
591
591
|
"name": "onExpandedValuesChange",
|
|
592
592
|
"type": "(values: string[]) => void"
|
|
593
|
+
},
|
|
594
|
+
{
|
|
595
|
+
"defaultValue": "false",
|
|
596
|
+
"description": "antd Table `sticky` — keep the axis header (bands + ticks) on screen while the PAGE scrolls a long schedule. `offsetHeader` is px from the top of the scrolling viewport (the height of a fixed app topbar). The header moves out of the horizontal scroller and follows its scrollLeft; the section becomes `overflow: clip` and the body scroller takes the keyboard tab stop. Like antd, it needs no clipping ancestor between the timeline and the page scroller: `Card` is `overflow: hidden`, so a sticky timeline goes in the page as its own section, not inside a Card. antd's `offsetScroll` / `getContainer` (sticky horizontal scrollbar) are not ported.",
|
|
597
|
+
"name": "sticky",
|
|
598
|
+
"type": "boolean | { offsetHeader?: number }"
|
|
593
599
|
}
|
|
594
600
|
],
|
|
595
601
|
"rules": [],
|
|
@@ -662,7 +668,7 @@
|
|
|
662
668
|
"type": "ReactNode"
|
|
663
669
|
},
|
|
664
670
|
{
|
|
665
|
-
"description": "Ordered trail of { label, to? } segments above the title.",
|
|
671
|
+
"description": "Ordered trail of { label, to?, ellipsis? } segments above the title. `ellipsis: true` on a segment keeps the trail on one line and cuts that label with an ellipsis, the full label in a tooltip on hover and on keyboard focus of the crumb link — same contract as `Breadcrumb` items.",
|
|
666
672
|
"name": "breadcrumb",
|
|
667
673
|
"type": "BreadcrumbItemProp[]"
|
|
668
674
|
},
|
|
@@ -2333,7 +2339,7 @@
|
|
|
2333
2339
|
"name": "Breadcrumb",
|
|
2334
2340
|
"props": [
|
|
2335
2341
|
{
|
|
2336
|
-
"description": "Array of { label, to?, menu? } — omit `to` on the last (current) segment. `menu` (Ant Design `BreadcrumbItemType.menu`) hangs a sibling picker off that segment: `{ items: { value, label, to?, disabled? }[], onSelect? }`. The segment then renders as a menu button, not a link — an entry with `to` becomes a real anchor inside the menu while keeping `role=\"menuitem\"`.",
|
|
2342
|
+
"description": "Array of { label, to?, menu?, ellipsis? } — omit `to` on the last (current) segment. `ellipsis` (`boolean | { tooltip?: ReactNode }`, gh#1046; antd Breadcrumb has none, the shape is antd Typography's) keeps the trail on one line and cuts that segment's label with an ellipsis, showing the full label in a tooltip on hover and on keyboard focus of the crumb link; `{ tooltip: false }` drops the tooltip. Link and current segments only. `--breadcrumb-item-max-inline-size` (default `none`) caps such a segment. `menu` (Ant Design `BreadcrumbItemType.menu`) hangs a sibling picker off that segment: `{ items: { value, label, to?, disabled? }[], onSelect? }`. The segment then renders as a menu button, not a link — an entry with `to` becomes a real anchor inside the menu while keeping `role=\"menuitem\"`.",
|
|
2337
2343
|
"name": "items",
|
|
2338
2344
|
"required": true,
|
|
2339
2345
|
"type": "BreadcrumbItemProp[]"
|
|
@@ -2738,7 +2744,7 @@
|
|
|
2738
2744
|
"type": "boolean | { text, editing, icon, tooltip, onStart, onChange, onCancel, onEnd, maxLength, autoSize, triggerType, enterIcon, tabIndex }"
|
|
2739
2745
|
},
|
|
2740
2746
|
{
|
|
2741
|
-
"description": "Single-line truncation, antd's spelling. antd drops `rows` / `expandable` / `onExpand` on `Text` — an inline run has no second line to expand into — and that omission is ported; reach for `Paragraph` when you want them. It is the SAME axis as `truncate` / `clamp` and OUTRANKS both (dev builds warn), because it is the only spelling that can also carry a suffix or a tooltip.",
|
|
2747
|
+
"description": "Single-line truncation, antd's spelling. antd drops `rows` / `expandable` / `onExpand` on `Text` — an inline run has no second line to expand into — and that omission is ported; reach for `Paragraph` when you want them. It is the SAME axis as `truncate` / `clamp` and OUTRANKS both (dev builds warn), because it is the only spelling that can also carry a suffix or a tooltip. `tooltip: true` (the children) or a node shows the full text in a Tooltip ONLY while the run is actually clipped — on pointer hover, and on keyboard focus of the Text itself (`asChild` link) or of the nearest focusable control around it (a Tree `treeitem`, a DataTable sort button, a link); the Text never becomes a tab stop of its own and its accessible name stays the full text. With `asChild` the child element is the truncated box (one `<a>`, not `<a><a>`). A `<Text ellipsis>` in `ColumnDef.header` truncates inside its column like a cell.",
|
|
2742
2748
|
"name": "ellipsis",
|
|
2743
2749
|
"type": "boolean | { suffix, symbol, defaultExpanded, expanded, onEllipsis, tooltip }"
|
|
2744
2750
|
},
|
|
@@ -3525,9 +3531,9 @@
|
|
|
3525
3531
|
"type": "() => void"
|
|
3526
3532
|
},
|
|
3527
3533
|
{
|
|
3528
|
-
"description": "Full row-selection configuration (antd rowSelection). Supersedes — and can be mixed with — selectable/selected/onSelectChange, which drive the same state. type:'radio' makes the column single-choice (no header checkbox at all). getCheckboxProps is the declared home for 'this row cannot be selected' (disabled) and for a per-row accessible name. preserveSelectedRowKeys keeps a key selected after its row leaves `data` (server paging / a filter), which is the only way a select-across-pages bulk action can be correct. selections adds bulk entries under the header checkbox (true = the built-in all · invert · none).",
|
|
3534
|
+
"description": "Full row-selection configuration (antd rowSelection). Supersedes — and can be mixed with — selectable/selected/onSelectChange, which drive the same state. type:'radio' makes the column single-choice (no header checkbox at all). getCheckboxProps is the declared home for 'this row cannot be selected' (disabled) and for a per-row accessible name. preserveSelectedRowKeys keeps a key selected after its row leaves `data` (server paging / a filter), which is the only way a select-across-pages bulk action can be correct. selections adds bulk entries under the header checkbox (true = the built-in all · invert · none; a list mixes antd's DataTable.SELECTION_ALL / SELECTION_INVERT / SELECTION_NONE with custom entries in the order given). selectAllLabel names the header checkbox — say what it really selects (on a server-paged table: the page) instead of replacing it through columnTitle. matching (no antd equivalent; Gmail/Jira/GitHub) is the server-paged 'select all N matching' banner: once the whole page is ticked and total exceeds the page, a polite status above the header offers 'Select all N matching rows'; choosing it reports onSelectedChange(true) — send your FILTER, not the ids, for the bulk write — and while selected every row of any page shows ticked. Unticking a row or 'Clear selection' reports false. With matching set, the header checkbox defaults to 'Select all rows on this page'.",
|
|
3529
3535
|
"name": "rowSelection",
|
|
3530
|
-
"type": "{ type?: 'checkbox'|'radio'; selectedRowKeys?: string[]; defaultSelectedRowKeys?: string[]; onChange?: (keys, rows) => void; getCheckboxProps?: (row) => { disabled?, 'aria-label'? }; preserveSelectedRowKeys?: boolean; selections?: true | { key, text, onSelect }[]; hideSelectAll?: boolean; columnTitle?: ReactNode }"
|
|
3536
|
+
"type": "{ type?: 'checkbox'|'radio'; selectedRowKeys?: string[]; defaultSelectedRowKeys?: string[]; onChange?: (keys, rows) => void; getCheckboxProps?: (row) => { disabled?, 'aria-label'? }; preserveSelectedRowKeys?: boolean; selections?: true | ({ key, text, onSelect } | DataTable.SELECTION_ALL | DataTable.SELECTION_INVERT | DataTable.SELECTION_NONE)[]; hideSelectAll?: boolean; columnTitle?: ReactNode; selectAllLabel?: string; matching?: { total: number; selected: boolean; onSelectedChange: (selected: boolean) => void } }"
|
|
3531
3537
|
},
|
|
3532
3538
|
{
|
|
3533
3539
|
"description": "Expandable detail rows (antd expandable). Supplying expandedRowRender adds a leading expand column before the selection column and renders the panel in a real <tr> spanning every column, so the table's grid semantics survive. rowExpandable gates the affordance per row; expandedRowKeys + onExpandedRowsChange make it controlled.",
|
|
@@ -4729,7 +4735,7 @@
|
|
|
4729
4735
|
]
|
|
4730
4736
|
},
|
|
4731
4737
|
{
|
|
4732
|
-
"example": "import { Progress } from \"@godxjp/ui/data-display\";\n\n<Progress value={pct} label={pct + \"% 使用中\"} tone={pct >= 80 ? \"warning\" : \"success\"} />\n<Progress value={252} over label=\"252% 積載\" />\n<Progress\n segments={[\n { value: 2, tone: \"destructive\", label: \"期限超過\" },\n { value: 3, tone: \"warning\", label: \"期限間近\" },\n { value: 12, tone: \"success\", label: \"対応済\" },\n ]}\n aria-labelledby={companyNameId}\n/>",
|
|
4738
|
+
"example": "import { Progress } from \"@godxjp/ui/data-display\";\n\n<Progress value={pct} label={pct + \"% 使用中\"} tone={pct >= 80 ? \"warning\" : \"success\"} />\n<Progress value={252} over label=\"252% 積載\" />\n<Progress\n segments={[\n { value: 2, tone: \"destructive\", label: \"期限超過\" },\n { value: 3, tone: \"warning\", label: \"期限間近\" },\n { value: 12, tone: \"success\", label: \"対応済\" },\n ]}\n aria-labelledby={companyNameId}\n/>\n<Progress\n segments={[\n { value: 3, tone: \"success\", label: \"合格\" },\n { value: 1, tone: \"destructive\", label: \"失敗\" },\n ]}\n total={400}\n remainderLabel=\"未実施\"\n/>",
|
|
4733
4739
|
"group": "data-display",
|
|
4734
4740
|
"importPath": "@godxjp/ui/data-display",
|
|
4735
4741
|
"name": "Progress",
|
|
@@ -4745,6 +4751,16 @@
|
|
|
4745
4751
|
"name": "segments",
|
|
4746
4752
|
"type": "{ value: number; tone: \"success\" | \"warning\" | \"destructive\"; label: string }[]"
|
|
4747
4753
|
},
|
|
4754
|
+
{
|
|
4755
|
+
"description": "BREAKDOWN mode: the WHOLE the slices are drawn against, in the same unit as their values. Omit it and the whole is the sum of the slices (the bar is always full). Pass it when part of the whole has no state yet — 3 passed of 400 test cases — and the rest stays the neutral TRACK, the antd `percent` model where the unfilled track is the remainder. The remainder is spoken in the role=\"img\" name, Intl-formatted in the active locale. A total below the slice sum is ignored (the sum wins), so slices never overflow.",
|
|
4756
|
+
"name": "total",
|
|
4757
|
+
"type": "number"
|
|
4758
|
+
},
|
|
4759
|
+
{
|
|
4760
|
+
"description": "BREAKDOWN mode, with `total`: what the remainder is called in the spoken breakdown (e.g. 未実施). Defaults to the catalogue's Remaining / 残り / Còn lại.",
|
|
4761
|
+
"name": "remainderLabel",
|
|
4762
|
+
"type": "string"
|
|
4763
|
+
},
|
|
4748
4764
|
{
|
|
4749
4765
|
"description": "Text label beside/below the bar; it also becomes the accessible name. Pass `aria-labelledby` instead when the name is ALREADY on screen (a row's company name, a card heading) — the bar then borrows it rather than repeating it.",
|
|
4750
4766
|
"name": "label",
|
|
@@ -4794,6 +4810,7 @@
|
|
|
4794
4810
|
"DON'T pass children or sub-components — Progress is a single self-contained element (track + bar + label). The `label` prop is the only text injection point; don't wrap it in a custom parent div to add a label alongside it.",
|
|
4795
4811
|
"DON'T hand-roll a stacked bar out of three divs to show a part-to-whole split — pass `segments`. Hand-rolled slices need a hex fill, an arbitrary height and an arbitrary radius, which ui-audit blocks three ways (no-arbitrary-hex, no-arbitrary-size, no-arbitrary-radius), and they leave the picture with no accessible name at all.",
|
|
4796
4812
|
"DON'T convert segment amounts to percentages yourself — pass the raw counts. The component divides by the total, so the slices always sum to the whole; pre-rounded percentages do not.",
|
|
4813
|
+
"DO pass `total` when part of the whole has no state yet (a test run: 合格 3 · 失敗 1 of 400) — the rest stays track and is read out as `remainderLabel` (e.g. \"未実施\"). Leaving it out makes 3 passed of 400 fill the whole bar green.",
|
|
4797
4814
|
"DO pair a breakdown with `Legend` so each tone is spelled out in words once, instead of repeating the labels on every bar.",
|
|
4798
4815
|
"DON'T use Progress for editable numeric input or range selection — it has no callbacks, no interactivity, and no form `name` prop. Use Slider (bounded range input) or Input (free-form number) for data-entry scenarios."
|
|
4799
4816
|
],
|
|
@@ -5346,6 +5363,11 @@
|
|
|
5346
5363
|
"name": "children",
|
|
5347
5364
|
"required": true,
|
|
5348
5365
|
"type": "(flat, helpers) => ReactNode"
|
|
5366
|
+
},
|
|
5367
|
+
{
|
|
5368
|
+
"description": "Idle text of the built-in load-more button (default: localized `query.loadMore`, 「さらに読み込む」) — e.g. 「さらに表示」「さらに古い版を表示」. The button, its pending label and disabled-while-fetching stay the component's. Ignored when `loadMore` replaces the footer.",
|
|
5369
|
+
"name": "loadMoreLabel",
|
|
5370
|
+
"type": "ReactNode"
|
|
5349
5371
|
}
|
|
5350
5372
|
],
|
|
5351
5373
|
"related": [
|
|
@@ -5362,7 +5384,7 @@
|
|
|
5362
5384
|
"DO: Always pass `skeleton` (e.g. `<SkeletonTable />` or `<SkeletonStat />`). It shows on initial `isPending`, on refetch-after-error, and whenever `data` is absent. Never show a blank area while loading.",
|
|
5363
5385
|
"DO: Pass `empty` (an `<EmptyState>` node) to handle the zero-results case — without it the children render-prop is called with an empty array and you get a silent blank screen. Provide a custom `isEmpty` only when `TFlat` is not an array.",
|
|
5364
5386
|
"DO: Let errors remain cause-aware. Retry is automatic only for classified transient/network/5xx failures. Unknown errors do not get a blind retry unless `showRetry` or `onRetry` is explicitly supplied; a 401 is handled by the app-root `AuthExpiryProvider` (auto, once, skeleton + live region) or, without one, by the `onAuthError` sign-in button; raw backend/token text is never rendered.",
|
|
5365
|
-
"DON'T: Hand-roll a load-more button. The component renders a default centered outline Button when `hasNextPage` is true.
|
|
5387
|
+
"DON'T: Hand-roll a load-more button. The component renders a default centered outline Button when `hasNextPage` is true. Rename it with `loadMoreLabel` (keeps the pending state); replace it only via `loadMore` (custom node) or `showLoadMore={false}` (hide entirely). Never call `query.fetchNextPage()` outside the component for pagination.",
|
|
5366
5388
|
"DON'T: Use `InfiniteQueryState` for a `useQuery` result — it expects `UseInfiniteQueryResult` shape (`pages`, `hasNextPage`, `fetchNextPage`, `isFetchingNextPage`). For regular `useQuery` use `DataState` instead.",
|
|
5367
5389
|
"DON'T: Confuse the two generics: `TPage` is the raw page shape from the API, `TFlat` is what `flatten` returns (usually `TItem[]`). The `children` render-prop receives `TFlat`, not `TPage`. Pass `isEmpty` if `TFlat` is not a plain array so empty detection works correctly."
|
|
5368
5390
|
],
|
|
@@ -6117,6 +6139,16 @@
|
|
|
6117
6139
|
"name": "dialogTitle",
|
|
6118
6140
|
"type": "string"
|
|
6119
6141
|
},
|
|
6142
|
+
{
|
|
6143
|
+
"description": "antd `notFoundContent` — shown when the search finds nothing, in the dropdown shape and the dialog alike (default: localized `dataEntry.recordPicker.empty`). Say WHAT has no match, e.g. 「該当するファイルはありません」.",
|
|
6144
|
+
"name": "notFoundContent",
|
|
6145
|
+
"type": "ReactNode"
|
|
6146
|
+
},
|
|
6147
|
+
{
|
|
6148
|
+
"description": "Text of the dialog's load-more button (default: localized `dataEntry.recordPicker.more`). Only the label — the button still appears only while the server returns a `nextCursor`.",
|
|
6149
|
+
"name": "loadMoreLabel",
|
|
6150
|
+
"type": "ReactNode"
|
|
6151
|
+
},
|
|
6120
6152
|
{
|
|
6121
6153
|
"description": "Control height of the trigger, on the shared control ladder.",
|
|
6122
6154
|
"name": "size",
|
|
@@ -9078,7 +9110,7 @@
|
|
|
9078
9110
|
"type": "\"SHOW_CHILD\" | \"SHOW_PARENT\""
|
|
9079
9111
|
},
|
|
9080
9112
|
{
|
|
9081
|
-
"description": "antd `loadData` — lazy children. Called
|
|
9113
|
+
"description": "antd `loadData` — lazy children. Called when a branch that has no children and isLeaf !== true is expanded, and never again once its promise resolves; push the fetched children into options. A rejected promise is forgotten, so the next activation of the branch asks again (gh#1041).",
|
|
9082
9114
|
"name": "loadData",
|
|
9083
9115
|
"type": "(selectedOptions: TreeOptionProp[]) => void | Promise<void>"
|
|
9084
9116
|
},
|
|
@@ -9319,7 +9351,7 @@
|
|
|
9319
9351
|
"type": "boolean"
|
|
9320
9352
|
},
|
|
9321
9353
|
{
|
|
9322
|
-
"description": "antd `loadData` — lazy children. Called
|
|
9354
|
+
"description": "antd `loadData` — lazy children. Called when a node that has no children and isLeaf !== true is expanded, and never again once its promise resolves; push the fetched children into treeData. A rejected promise folds the branch shut and the next expand asks again, up to 10 attempts (rc-tree, gh#1041). Such a node still reads as expandable (aria-expanded + a working expander).",
|
|
9323
9355
|
"name": "loadData",
|
|
9324
9356
|
"type": "(node: TreeOptionProp) => void | Promise<void>"
|
|
9325
9357
|
},
|
|
@@ -9481,6 +9513,11 @@
|
|
|
9481
9513
|
"name": "onSelectChange",
|
|
9482
9514
|
"type": "(sourceSelectedKeys: string[], targetSelectedKeys: string[]) => void"
|
|
9483
9515
|
},
|
|
9516
|
+
{
|
|
9517
|
+
"description": "antd `locale`, ported for `notFoundContent` only: what an empty or search-emptied pane shows (default: localized `dataEntry.transfer.empty`). A `[source, target]` pair sets each pane separately, as in antd.",
|
|
9518
|
+
"name": "locale",
|
|
9519
|
+
"type": "{ notFoundContent?: ReactNode | [ReactNode, ReactNode] }"
|
|
9520
|
+
},
|
|
9484
9521
|
{
|
|
9485
9522
|
"description": "Fires when items move between panels; you own `targetKeys` state.",
|
|
9486
9523
|
"name": "onValueChange",
|
|
@@ -11046,7 +11083,7 @@
|
|
|
11046
11083
|
"type": "boolean"
|
|
11047
11084
|
},
|
|
11048
11085
|
{
|
|
11049
|
-
"description": "Lazy children (antd `loadData`). Called
|
|
11086
|
+
"description": "Lazy children (antd `loadData`). Called when a branch with no `children` and `isLeaf !== true` is expanded, and never again once its promise RESOLVES; a Skeleton row and `aria-busy` cover the wait. Push the fetched children into `treeData`. A REJECTED promise is not a load (rc-tree, gh#1041): the branch folds back shut (uncontrolled expansion) and the next expand asks again, up to 10 attempts.",
|
|
11050
11087
|
"name": "loadData",
|
|
11051
11088
|
"type": "(node: TreeNodeProp) => void | Promise<void>"
|
|
11052
11089
|
},
|
|
@@ -11055,6 +11092,22 @@
|
|
|
11055
11092
|
"name": "titleRender",
|
|
11056
11093
|
"type": "(node: TreeNodeProp) => ReactNode"
|
|
11057
11094
|
},
|
|
11095
|
+
{
|
|
11096
|
+
"description": "Highlight the nodes this returns true for (antd `filterTreeNode`, gh#1043) — the match of a search box above the tree. Matching rows are MARKED, not hidden: `data-filter-node=\"true\"`, the label in `--tree-node-filter-foreground` (default `hsl(var(--primary))`) at the medium weight, plus sr-only \"matches the filter\" text. Outline, keyboard and ARIA are unchanged. To also open the branches that hold a match, drive `expandedValues`.",
|
|
11097
|
+
"name": "filterTreeNode",
|
|
11098
|
+
"type": "(node: TreeNodeProp) => boolean"
|
|
11099
|
+
},
|
|
11100
|
+
{
|
|
11101
|
+
"description": "Viewport height in px (antd `height`, gh#1042). The tree scrolls inside it and, unless `virtual={false}`, renders only the rows in view plus a small overscan — the windowed rows stay a flat run of treeitems whose `aria-level`/`aria-setsize`/`aria-posinset` still describe the whole outline. Rows must share one height (the `size` tier).",
|
|
11102
|
+
"name": "height",
|
|
11103
|
+
"type": "number"
|
|
11104
|
+
},
|
|
11105
|
+
{
|
|
11106
|
+
"defaultValue": "true",
|
|
11107
|
+
"description": "Set `false` to keep the `height` viewport but render every row (antd `virtual`).",
|
|
11108
|
+
"name": "virtual",
|
|
11109
|
+
"type": "boolean"
|
|
11110
|
+
},
|
|
11058
11111
|
{
|
|
11059
11112
|
"defaultValue": "false",
|
|
11060
11113
|
"description": "Draw the connector rails between a parent and its children (antd `showLine`). Off by default — a rail is chrome, and chrome defaults quiet.",
|
|
@@ -11112,7 +11165,7 @@
|
|
|
11112
11165
|
"TreeSelect — the same hierarchy INSIDE a Popover, as a form field. Use TreeSelect when the answer is a value in a form; use Tree when the hierarchy itself is the page.",
|
|
11113
11166
|
"Cascader — a path picker across columns. Use it when the user walks one path to a leaf; use Tree when several branches are open at once.",
|
|
11114
11167
|
"Accordion — single-level disclosure with rich panel content. It is not a hierarchy and has no tree keyboard model.",
|
|
11115
|
-
"ScrollArea —
|
|
11168
|
+
"ScrollArea — not needed around Tree: pass `height`, and the tree is its own (windowed) scroll viewport."
|
|
11116
11169
|
],
|
|
11117
11170
|
"rules": [
|
|
11118
11171
|
2,
|
|
@@ -11132,8 +11185,9 @@
|
|
|
11132
11185
|
"DON'T nest a Button, Checkbox, Link or any focusable control inside a node label. A tree item owns exactly ONE tab stop; the disclosure triangle and the tick box are decorative glyphs for that reason. Put row actions in a sibling column outside the tree, or open a detail pane on selection.",
|
|
11133
11186
|
"DON'T hand-roll an indented `<ul>` (or a NavList / ListRow stack with a per-depth margin) for a hierarchy. A flat indented list only LOOKS like a tree: no expand/collapse, no `role=\"tree\"`, no keyboard model, no selection contract. `TreeList` was exactly that list and was REMOVED in 21.0.0 — Tree is what replaced it, and it is the one to reach for whenever nodes expand, collapse or are keyboard-navigated.",
|
|
11134
11187
|
"DO pass `divided` when the tree IS the navigation of a page — a wiki/document outline or a section index sitting in a `Card` (`Card` > `CardContent flush` > `Tree divided`). Without a rule the rows run together and the outline reads as one block; with it, it reads as the ruled list ListRow and Table already give a flat list. Retint it per theme with `--tree-divider-color`, never with a per-page utility class.",
|
|
11135
|
-
"DO
|
|
11136
|
-
"DO push fetched children into `treeData` from `loadData`; the tree calls it once per node and shows a Skeleton row until the data lands."
|
|
11188
|
+
"DO pass `height` for a long tree (antd `height` + `virtual`): the tree scrolls inside that height and keeps only the rows in view in the DOM, so a 421-child level renders a few dozen rows. Do not wrap it in `ScrollArea` as well — the tree is its own viewport.",
|
|
11189
|
+
"DO push fetched children into `treeData` from `loadData`; the tree calls it once per node that loads and shows a Skeleton row until the data lands. Reject the promise on failure — the branch folds shut and the next expand retries.",
|
|
11190
|
+
"DON'T wait for a paged \"load more\" node — antd's Tree has none, and `height` covers a long list. If the API itself is paged, append a leaf node such as `{ value: `${parent}::more`, label: t(\"…load more\"), isLeaf: true }` to the loaded children and fetch the next page from `onValueChange` when it is selected: it is a real treeitem, so it is keyboard-reachable and announced."
|
|
11137
11191
|
],
|
|
11138
11192
|
"useCases": [
|
|
11139
11193
|
"A permission tree: modules → resources → actions with tri-state checkboxes, where ticking a module ticks everything under it and a partly-granted module shows the dash.",
|
|
@@ -14655,6 +14709,11 @@
|
|
|
14655
14709
|
"name": "searchable",
|
|
14656
14710
|
"type": "boolean"
|
|
14657
14711
|
},
|
|
14712
|
+
{
|
|
14713
|
+
"description": "antd `notFoundContent` — shown when the branch SEARCH matches nothing (default: localized `dataEntry.branchScope.noMatches`). An empty `branches` list is `empty`'s job, not this.",
|
|
14714
|
+
"name": "notFoundContent",
|
|
14715
|
+
"type": "ReactNode"
|
|
14716
|
+
},
|
|
14658
14717
|
{
|
|
14659
14718
|
"description": "Override the localized radio labels (e.g. domain wording like 全店舗).",
|
|
14660
14719
|
"name": "allLabel / selectedLabel",
|
package/agent/index.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"components": 177,
|
|
5
5
|
"patterns": 21,
|
|
6
6
|
"rules": 50,
|
|
7
|
-
"tokens":
|
|
7
|
+
"tokens": 2100,
|
|
8
8
|
"vocabulary": 14
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
{
|
|
17
17
|
"file": "components/<Name>.json",
|
|
18
|
-
"note": "One file per component (1 KB–
|
|
18
|
+
"note": "One file per component (1 KB–36 KB, median 6 KB), each carrying its importPath. This is the selective route: read the index, then fetch only what you need instead of the 1.2 MB blob.",
|
|
19
19
|
"url": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components/<Name>.json"
|
|
20
20
|
},
|
|
21
21
|
{
|
|
@@ -48,19 +48,19 @@
|
|
|
48
48
|
"note": "Pin to the tag that matches the @godxjp/ui version you installed. A catalog newer than your package describes props you do not have; older, and it hides props you do.",
|
|
49
49
|
"read": {
|
|
50
50
|
"live": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/index.json",
|
|
51
|
-
"pinned": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/v31.
|
|
51
|
+
"pinned": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/v31.7.0/agent/index.json"
|
|
52
52
|
},
|
|
53
53
|
"source": "mcp/src/data — the same data @godxjp/ui-mcp serves — plus the foundation and semantic token tiers, read from src/tokens/*.css",
|
|
54
54
|
"start": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/START-HERE.md",
|
|
55
55
|
"tokenTiers": {
|
|
56
56
|
"component": "per-part knobs, --{component}-{part}-{property}; usually leave these alone",
|
|
57
57
|
"counts": {
|
|
58
|
-
"component":
|
|
58
|
+
"component": 1785,
|
|
59
59
|
"foundation": 211,
|
|
60
60
|
"semantic": 104
|
|
61
61
|
},
|
|
62
62
|
"foundation": "the seeds a consumer is invited to set — --primary, --background, --radius",
|
|
63
63
|
"semantic": "named roles that follow the seeds — --ring, --text-link, --overlay-background"
|
|
64
64
|
},
|
|
65
|
-
"version": "31.
|
|
65
|
+
"version": "31.7.0"
|
|
66
66
|
}
|
package/agent/llms.txt
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# @godxjp/ui
|
|
2
2
|
|
|
3
|
-
> A Japanese-enterprise React design system: 177 components,
|
|
4
|
-
> 50 cardinal rules. This file is the entry point for AI agents. Catalog version 31.
|
|
3
|
+
> A Japanese-enterprise React design system: 177 components, 2100 design tokens,
|
|
4
|
+
> 50 cardinal rules. This file is the entry point for AI agents. Catalog version 31.7.0.
|
|
5
5
|
|
|
6
6
|
If your client can run a process, do not read these files — run the MCP server instead
|
|
7
|
-
(`npx @godxjp/ui-mcp@31.
|
|
7
|
+
(`npx @godxjp/ui-mcp@31.7.0`). It is searchable and version-locked. These files exist for agents
|
|
8
8
|
that can only fetch URLs.
|
|
9
9
|
|
|
10
10
|
## Start
|
|
@@ -16,9 +16,9 @@ that can only fetch URLs.
|
|
|
16
16
|
|
|
17
17
|
- [patterns-index.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/patterns-index.json): 21 whole-task patterns (name, tagline, tags). Start here when the task is a TASK — "build a settings page" — then fetch `patterns/<name>.json` for complete code.
|
|
18
18
|
- [components-index.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components-index.json): 47 KB — all 177 components as name, group, tagline, plus `absorbed`: the names that do NOT exist and map to it (`Combobox` → `Select`).
|
|
19
|
-
- [components/<Name>.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components/Select.json): one file per component (1 KB–
|
|
19
|
+
- [components/<Name>.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components/Select.json): one file per component (1 KB–36 KB, median 6 KB). Read the index, then fetch only the ones you chose — this is the selective route, and the reason you do not need the blob.
|
|
20
20
|
- [components.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components.json): 1.2 MB — every entry in one file. Most URL fetchers truncate a response this size without saying so; prefer the per-component files.
|
|
21
|
-
- [tokens.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/tokens.json): every design token with its value, the reason it exists, and its `tier` — 211 `foundation` seeds (`--primary`, `--background`, `--radius`: set these when you are handed a brand), 104 `semantic` roles,
|
|
21
|
+
- [tokens.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/tokens.json): every design token with its value, the reason it exists, and its `tier` — 211 `foundation` seeds (`--primary`, `--background`, `--radius`: set these when you are handed a brand), 104 `semantic` roles, 1785 `component` knobs.
|
|
22
22
|
- [vocabulary.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/vocabulary.json): the controlled prop vocabulary — which prop name means what, across every component.
|
|
23
23
|
- [rules.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/rules.json): 50 cardinal rules.
|
|
24
24
|
- [anti-ai-tells.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/anti-ai-tells.json): 26 shapes that make generated UI look generated, each with its fix.
|
|
@@ -26,7 +26,7 @@ that can only fetch URLs.
|
|
|
26
26
|
## Pinning
|
|
27
27
|
|
|
28
28
|
Every URL above tracks `main`. To pin to the release a project actually installed, swap `main` for
|
|
29
|
-
the tag: `.../godx-jp/godxjp-ui/v31.
|
|
29
|
+
the tag: `.../godx-jp/godxjp-ui/v31.7.0/agent/...`. A catalog that does not match the installed
|
|
30
30
|
package describes props that are absent, or hides props that are present, and says nothing either way.
|
|
31
31
|
|
|
32
32
|
Pinned catalogs only exist for releases whose tag actually contains `agent/`. If `…/v<version>/agent/index.json` returns 404, that release predates this catalog: read `…/main/…` instead and compare `index.json` → `version` against the package you have, so you at least know which way it drifted.
|