@godxjp/ui 31.15.0 → 31.17.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/Badge.json +2 -2
- package/agent/components/DataTable.json +3 -3
- package/agent/components/Table.json +1 -1
- package/agent/components/Text.json +1 -1
- package/agent/components/TextDiff.json +86 -0
- package/agent/components-index.json +6 -1
- package/agent/components.json +93 -7
- package/agent/index.json +6 -6
- package/agent/llms.txt +6 -6
- package/agent/tokens.json +48 -0
- package/dist/components/data-display/badge.js +17 -1
- package/dist/components/data-display/data-table.js +1 -1
- package/dist/components/data-display/image.js +6 -1
- package/dist/components/data-display/index.d.ts +2 -0
- package/dist/components/data-display/index.js +4 -0
- package/dist/components/data-display/table.js +1 -1
- package/dist/components/data-display/text-diff.d.ts +45 -0
- package/dist/components/data-display/text-diff.js +240 -0
- package/dist/components/general/typography.js +3 -3
- package/dist/contracts/measurement.json +1 -1
- package/dist/i18n/messages/en.json +12 -0
- package/dist/i18n/messages/ja.json +9 -0
- package/dist/i18n/messages/vi.json +9 -0
- package/dist/props/components/data-display.prop.d.ts +43 -0
- package/dist/props/registry.d.ts +46 -1
- package/dist/props/registry.js +58 -1
- package/dist/props/vocabulary/data.prop.d.ts +6 -0
- package/dist/props/vocabulary/interaction.prop.d.ts +1 -0
- package/dist/styles/badge-layout.css +12 -0
- package/dist/styles/data-display-layout.css +52 -0
- package/dist/styles/layers.json +6 -1
- package/dist/styles/navigation-layout.css +3 -0
- package/dist/styles/table-layout.css +33 -0
- package/dist/styles/text-layout.css +4 -0
- package/dist/tokens/components/data-display.css +8 -0
- package/dist/tokens/components/navigation.css +2 -0
- package/dist/tokens/components/table.css +4 -0
- package/docs/FRAME-COVERAGE-REPORT.md +3 -2
- package/docs/data-display/badge.tsx +15 -0
- package/docs/data-display/text-diff.tsx +89 -0
- package/docs/i18n/messages/en.json +24 -0
- package/docs/i18n/messages/ja.json +24 -0
- package/docs/i18n/messages/vi.json +24 -0
- package/package.json +2 -2
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.17.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.
|
|
@@ -47,7 +47,7 @@ Then ask it: `search_components`, `get_component`, `get_tokens`, `get_rule`, `li
|
|
|
47
47
|
task is a task** — "build a settings page", "confirm a destructive delete", "a list page with
|
|
48
48
|
filters" — start HERE, not at the components. Then fetch `patterns/<name>.json` for complete,
|
|
49
49
|
copy-paste-ready code. A component index answers "does X exist"; it cannot answer "build Y".
|
|
50
|
-
1. `components-index.json` — 48 KB, all
|
|
50
|
+
1. `components-index.json` — 48 KB, all 179 components as name + group +
|
|
51
51
|
tagline. Read this when you already know the SHAPE you need. Each entry may carry `absorbed`:
|
|
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
|
|
@@ -56,10 +56,10 @@ Then ask it: `search_components`, `get_component`, `get_tokens`, `get_rule`, `li
|
|
|
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` — 2129 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
|
+
1814 `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` | 1814 | 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.
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"type": "React.ComponentType<{ className?: string }> | null"
|
|
50
50
|
},
|
|
51
51
|
{
|
|
52
|
-
"description": "Badge label. When omitted with status, Badge renders the translated lifecycle label or raw status.",
|
|
52
|
+
"description": "Badge label. When omitted with status, Badge renders the translated lifecycle label or raw status. LONG LABEL CONTRACT (gh#1101): the chip is `max-inline-size: 100%` of its container and never wraps; the label ellipsizes and, when it was cut, shows the full text as a native `title` on hover (antd `Typography ellipsis`). A caller's own `title` on the Badge wins. So a Badge in a fixed-width DataTable cell or a narrow Card stays inside it with no extra props; `<Badge><Text ellipsis>` also works. Do not reach for `Text break=\"anywhere\"` to make a chip wrap.",
|
|
53
53
|
"name": "children",
|
|
54
54
|
"type": "ReactNode"
|
|
55
55
|
},
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"subParts": [
|
|
75
75
|
"StatusBadge"
|
|
76
76
|
],
|
|
77
|
-
"tagline": "Plain or lifecycle badge. Use `variant` for static chips, or `status` to auto-map lifecycle keys to semantic tone + icon. Labels never wrap.",
|
|
77
|
+
"tagline": "Plain or lifecycle badge. Use `variant` for static chips, or `status` to auto-map lifecycle keys to semantic tone + icon. Labels never wrap: a label wider than its container ellipsizes, with the full text as a hover `title` (gh#1101).",
|
|
78
78
|
"usage": [
|
|
79
79
|
"DO pick the correct variant semantically: `success` (approved/paid), `warning` (pending/overdue), `destructive` (rejected/error), `secondary` (neutral category), `outline` (subtle label), `default` (primary accent). Never force a colour just for aesthetics — agents and screen readers read the variant as intent.",
|
|
80
80
|
"DO use `status` for entity lifecycle statuses (active, draft, pending, cancelled, failed, scheduled, etc.) so the component resolves the correct tone, icon, and i18n label.",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
},
|
|
87
87
|
{
|
|
88
88
|
"defaultValue": "'default'",
|
|
89
|
-
"description": "Named collection contract — the SAME preset the Table primitive owns, forwarded to the table DataTable renders. 'default' emits NO attribute and matches no selector, so an existing DataTable is byte-identical. 'action-collection' is the canonical dense approval/action queue: below collapseBelow the desktop INTRINSIC column widths give way to the token-owned column-PRIORITY measures (--table-action-collection-*) under table-layout: fixed, cells wrap, and the bordered surface drops its --table-surface-min-inline-size floor — so requester · target · reason · requested date · row actions all stay inside a 390px frame with no horizontal scroll. Mark each column with `priority` on its ColumnDef. Semantics are untouched (no display change, no role rewriting, no card swap), so header association, aria-sort and screen-reader table navigation are identical at 390 and 1440. Measured: table 1182 / 766 / 388px at 1440 / 1024 / 390, document scrollWidth === clientWidth at every width, LTR and RTL. 'stacked-record-collection' is the other direction, for a WIDE, HETEROGENEOUS record set that has no sensible narrow column measure: below collapseBelow the <thead> hides and every <tr> becomes a bordered key-value card (--table-stacked-collection-*). Each cell then carries its column's header inline above the value, DERIVED from the same ColumnDef.header the <th> uses — so the card cannot drift from the table, and a column with a deliberately empty header names itself with ariaLabel (gh#864). The labels are aria-hidden: the real <th> is still in the DOM and remains the accessible-name source, so screen-reader table navigation is unchanged at every width. Reach for this instead of building a parallel Card tree beside the table; two trees for one dataset means two sets of labels to keep in sync.",
|
|
89
|
+
"description": "Named collection contract — the SAME preset the Table primitive owns, forwarded to the table DataTable renders. 'default' emits NO attribute and matches no selector, so an existing DataTable is byte-identical. 'action-collection' is the canonical dense approval/action queue: below collapseBelow the desktop INTRINSIC column widths give way to the token-owned column-PRIORITY measures (--table-action-collection-*) under table-layout: fixed, cells wrap, and the bordered surface drops its --table-surface-min-inline-size floor — so requester · target · reason · requested date · row actions all stay inside a 390px frame with no horizontal scroll. Mark each column with `priority` on its ColumnDef. Semantics are untouched (no display change, no role rewriting, no card swap), so header association, aria-sort and screen-reader table navigation are identical at 390 and 1440. Measured: table 1182 / 766 / 388px at 1440 / 1024 / 390, document scrollWidth === clientWidth at every width, LTR and RTL. 'stacked-record-collection' is the other direction, for a WIDE, HETEROGENEOUS record set that has no sensible narrow column measure: below collapseBelow the <thead> hides and every <tr> becomes a bordered key-value card (--table-stacked-collection-*). Each cell then carries its column's header inline above the value, DERIVED from the same ColumnDef.header the <th> uses — so the card cannot drift from the table, and a column with a deliberately empty header names itself with ariaLabel (gh#864). In card mode the CARD owns the inline inset: a folded cell has no inline padding of its own (--table-stacked-collection-cell-padding-x, default 0), and an EMPTY cell (content null) prints no label and drops out of the card (gh#1102). The labels are aria-hidden: the real <th> is still in the DOM and remains the accessible-name source, so screen-reader table navigation is unchanged at every width. Reach for this instead of building a parallel Card tree beside the table; two trees for one dataset means two sets of labels to keep in sync.",
|
|
90
90
|
"name": "preset",
|
|
91
91
|
"type": "'default' | 'action-collection' | 'stacked-record-collection'"
|
|
92
92
|
},
|
|
@@ -164,9 +164,9 @@
|
|
|
164
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
|
-
"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.",
|
|
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. The detail cell is inset like any cell (antd) and wraps (white-space: normal) — retune the inset with --table-row-expanded-padding; flush: true drops it for a detail that owns its inset (a nested table, a ListRow list). Do NOT wrap the detail in Card/CardContent or Flex pad for spacing (gh#1083).",
|
|
168
168
|
"name": "expandable",
|
|
169
|
-
"type": "{ expandedRowRender?: (row, index, expanded) => ReactNode; rowExpandable?: (row) => boolean; defaultExpandAllRows?: boolean; expandedRowKeys?: string[]; onExpandedRowsChange?: (keys) => void; expandRowByClick?: boolean; columnTitle?: ReactNode }"
|
|
169
|
+
"type": "{ expandedRowRender?: (row, index, expanded) => ReactNode; rowExpandable?: (row) => boolean; defaultExpandAllRows?: boolean; expandedRowKeys?: string[]; onExpandedRowsChange?: (keys) => void; expandRowByClick?: boolean; columnTitle?: ReactNode; flush?: boolean }"
|
|
170
170
|
},
|
|
171
171
|
{
|
|
172
172
|
"description": "Footer totals row (antd summary), rendered in a real <tfoot> so it keeps the column widths and the screen-reader row navigation. Receives the rows currently rendered (post sort/filter/page), so a page total and a grand total are both expressible. Compose the return with <TableRow>/<TableCell> from the Table primitive.",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
},
|
|
70
70
|
{
|
|
71
71
|
"defaultValue": "\"default\"",
|
|
72
|
-
"description": "Named collection contract. \"default\" emits no attribute and keeps the plain table. \"action-collection\" is the canonical dense approval/action queue: the desktop INTRINSIC column widths (which make a five-column queue wider than its card and force a horizontal scroll at 390) are replaced by table-layout: fixed plus the token-owned column PRIORITY measures (--table-action-collection-*), and cells wrap. Mark each column with `priority` on its TableHead AND its TableCell. Semantics are untouched — no display change, no role rewriting, no card transformation — so header association, aria-sort and screen-reader table navigation are identical at 390 and 1440. \"stacked-record-collection\" is the other direction, for a WIDE, HETEROGENEOUS record set with no sensible narrow column measure: below collapseBelow the <thead> hides and every <tr> becomes a bordered key-value card (--table-stacked-collection-*). Give each TableCell a `label` — its column header — because the <th> association it normally reads from is the thing that just went away; DataTable derives that label from ColumnDef.header for you (gh#864). The label is aria-hidden and the real <th> stays in the DOM, so the accessible name and table navigation are unchanged.",
|
|
72
|
+
"description": "Named collection contract. \"default\" emits no attribute and keeps the plain table. \"action-collection\" is the canonical dense approval/action queue: the desktop INTRINSIC column widths (which make a five-column queue wider than its card and force a horizontal scroll at 390) are replaced by table-layout: fixed plus the token-owned column PRIORITY measures (--table-action-collection-*), and cells wrap. Mark each column with `priority` on its TableHead AND its TableCell. Semantics are untouched — no display change, no role rewriting, no card transformation — so header association, aria-sort and screen-reader table navigation are identical at 390 and 1440. \"stacked-record-collection\" is the other direction, for a WIDE, HETEROGENEOUS record set with no sensible narrow column measure: below collapseBelow the <thead> hides and every <tr> becomes a bordered key-value card (--table-stacked-collection-*). Give each TableCell a `label` — its column header — because the <th> association it normally reads from is the thing that just went away; DataTable derives that label from ColumnDef.header for you (gh#864). In card mode the CARD owns the inline inset: a folded cell has no inline padding of its own (--table-stacked-collection-cell-padding-x, default 0), and an EMPTY cell (content null) prints no label and drops out of the card (gh#1102). The label is aria-hidden and the real <th> stays in the DOM, so the accessible name and table navigation are unchanged.",
|
|
73
73
|
"name": "preset",
|
|
74
74
|
"type": "\"default\" | \"action-collection\" | \"stacked-record-collection\""
|
|
75
75
|
},
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
},
|
|
50
50
|
{
|
|
51
51
|
"defaultValue": "\"normal\"",
|
|
52
|
-
"description": "Whitespace handling. 'normal' is CSS's own behaviour (newlines and space runs collapse) and stays the default. 'pre-wrap' is for text a PERSON typed — a plain-text note, an issue description, a pasted log — where the line breaks and the indentation are CONTENT: it keeps both, still wraps long lines at the container edge, and breaks an over-long unbroken token (a URL, an id) instead of overflowing. Use it INSTEAD of `className=\"whitespace-pre-wrap\"`. Precedence is explicit: `truncate` is a single-line contract and wins (dev builds warn); `clamp` COMPOSES with it, showing the first N preserved lines. Not for rendered Markdown/HTML — that is `Prose`, which styles rendered elements and does nothing to whitespace.",
|
|
52
|
+
"description": "Whitespace handling. 'normal' is CSS's own behaviour (newlines and space runs collapse) and stays the default; passed explicitly it also releases a `nowrap` the text inherits (a table cell's, gh#1083). 'pre-wrap' is for text a PERSON typed — a plain-text note, an issue description, a pasted log — where the line breaks and the indentation are CONTENT: it keeps both, still wraps long lines at the container edge, and breaks an over-long unbroken token (a URL, an id) instead of overflowing. Use it INSTEAD of `className=\"whitespace-pre-wrap\"`. Precedence is explicit: `truncate` is a single-line contract and wins (dev builds warn); `clamp` COMPOSES with it, showing the first N preserved lines. Not for rendered Markdown/HTML — that is `Prose`, which styles rendered elements and does nothing to whitespace.",
|
|
53
53
|
"name": "whitespace",
|
|
54
54
|
"type": "\"normal\" | \"pre-wrap\""
|
|
55
55
|
},
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
{
|
|
2
|
+
"example": "import { TextDiff } from \"@godxjp/ui/data-display\";\n\n<TextDiff before={row.previous_original} after={original} lang=\"ja\" />\n\n<TextDiff mode=\"split\" granularity=\"line\" before={previousBody} after={body} />",
|
|
3
|
+
"group": "data-display",
|
|
4
|
+
"importPath": "@godxjp/ui/data-display",
|
|
5
|
+
"name": "TextDiff",
|
|
6
|
+
"props": [
|
|
7
|
+
{
|
|
8
|
+
"description": "The earlier text (the original a translation was written against, the saved version).",
|
|
9
|
+
"name": "before",
|
|
10
|
+
"required": true,
|
|
11
|
+
"type": "string"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"description": "The current text.",
|
|
15
|
+
"name": "after",
|
|
16
|
+
"required": true,
|
|
17
|
+
"type": "string"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"defaultValue": "\"inline\"",
|
|
21
|
+
"description": "inline — one flow with removals and additions in place (GitHub's unified view). split — two columns, before | after, with changed hunks aligned row by row and localized column headings.",
|
|
22
|
+
"name": "mode",
|
|
23
|
+
"type": "\"inline\" | \"split\""
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"defaultValue": "\"auto\"",
|
|
27
|
+
"description": "The unit a change is measured in. auto = Intl.Segmenter words, with Han/Hiragana/Katakana/Hangul runs cut per character (no spaces to split on, and a dictionary word boundary moves when one particle changes). word = Intl.Segmenter words in `lang`. char = one grapheme cluster per token. line = whole lines.",
|
|
28
|
+
"name": "granularity",
|
|
29
|
+
"type": "\"auto\" | \"word\" | \"char\" | \"line\""
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"defaultValue": "true",
|
|
33
|
+
"description": "Fold long unchanged runs of lines behind a localized 'show N unchanged lines' button.",
|
|
34
|
+
"name": "collapseUnchanged",
|
|
35
|
+
"type": "boolean"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"defaultValue": "2",
|
|
39
|
+
"description": "Unchanged lines kept visible beside each change when folding (git's -U<n>).",
|
|
40
|
+
"name": "contextLines",
|
|
41
|
+
"type": "number"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"defaultValue": "4000000",
|
|
45
|
+
"description": "LCS cost cap (tokens before × tokens after). Past it the changed middle is one removal plus one addition instead of freezing the tab.",
|
|
46
|
+
"name": "maxCells",
|
|
47
|
+
"type": "number"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"description": "Heading of the before column in split mode. Default: localized 'Before'.",
|
|
51
|
+
"name": "beforeLabel",
|
|
52
|
+
"type": "ReactNode"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"description": "Heading of the after column in split mode. Default: localized 'After'.",
|
|
56
|
+
"name": "afterLabel",
|
|
57
|
+
"type": "ReactNode"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"description": "BCP-47 language of the text — set on the element (screen-reader pronunciation, CJK font selection) and used as the Intl.Segmenter locale.",
|
|
61
|
+
"name": "lang",
|
|
62
|
+
"type": "string"
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
"related": [
|
|
66
|
+
"CodeBlock — shows ONE preformatted text; TextDiff shows how two versions differ.",
|
|
67
|
+
"Text — `delete` / `mark` style a run you already chose; TextDiff decides the runs and announces them.",
|
|
68
|
+
"Timeline — the list of revisions; TextDiff is what one revision changed."
|
|
69
|
+
],
|
|
70
|
+
"rules": [],
|
|
71
|
+
"storyPath": "data-display/TextDiff.stories.tsx",
|
|
72
|
+
"tagline": "What changed between two versions of a text — removed runs in <del>, added runs in <ins>, inline or side by side, per line / word / character, with CJK cut per character and long unchanged runs folded.",
|
|
73
|
+
"usage": [
|
|
74
|
+
"DO import from `@godxjp/ui/data-display`: `import { TextDiff } from \"@godxjp/ui/data-display\";`",
|
|
75
|
+
"DO pass the two raw strings — the component tokenizes, diffs (LCS) and renders. Use the exported `diffText(before, after, { granularity, lang })` only when you need the runs themselves (a change count, a plain-text export).",
|
|
76
|
+
"DO pass `lang` for the text's language, not the UI's: a Japanese original in an English UI still needs lang=\"ja\".",
|
|
77
|
+
"DO use mode=\"split\" when there is room for two columns and the texts are long; inline for a drawer, a list row or a narrow panel.",
|
|
78
|
+
"DON'T hand-roll a diff from `Text delete` / `Text mark` — those carry no spoken start/end label, so a screen reader reads the old and new words run together.",
|
|
79
|
+
"DON'T colour a run without its mark: removals are struck through and additions underlined, plus a visually hidden start/end label — colour is never the only carrier (WCAG 1.4.1)."
|
|
80
|
+
],
|
|
81
|
+
"useCases": [
|
|
82
|
+
"A translation drawer: what changed in the original since this translation was written (old original → current original).",
|
|
83
|
+
"A document or wiki page revision history: one revision against the previous one.",
|
|
84
|
+
"A settings or template audit log: the previous value of a long text field against the new one."
|
|
85
|
+
]
|
|
86
|
+
}
|
|
@@ -239,7 +239,7 @@
|
|
|
239
239
|
{
|
|
240
240
|
"group": "data-display",
|
|
241
241
|
"name": "Badge",
|
|
242
|
-
"tagline": "Plain or lifecycle badge. Use `variant` for static chips, or `status` to auto-map lifecycle keys to semantic tone + icon. Labels never wrap."
|
|
242
|
+
"tagline": "Plain or lifecycle badge. Use `variant` for static chips, or `status` to auto-map lifecycle keys to semantic tone + icon. Labels never wrap: a label wider than its container ellipsizes, with the full text as a hover `title` (gh#1101)."
|
|
243
243
|
},
|
|
244
244
|
{
|
|
245
245
|
"group": "data-display",
|
|
@@ -251,6 +251,11 @@
|
|
|
251
251
|
"name": "Swatch",
|
|
252
252
|
"tagline": "A READ-ONLY sample of ONE colour a person chose — a brand's primary_color, a calendar category, a tag tint. The colour is a VALUE on the element, never a token in a stylesheet."
|
|
253
253
|
},
|
|
254
|
+
{
|
|
255
|
+
"group": "data-display",
|
|
256
|
+
"name": "TextDiff",
|
|
257
|
+
"tagline": "What changed between two versions of a text — removed runs in <del>, added runs in <ins>, inline or side by side, per line / word / character, with CJK cut per character and long unchanged runs folded."
|
|
258
|
+
},
|
|
254
259
|
{
|
|
255
260
|
"group": "data-display",
|
|
256
261
|
"name": "FeatureList",
|
package/agent/components.json
CHANGED
|
@@ -2668,7 +2668,7 @@
|
|
|
2668
2668
|
},
|
|
2669
2669
|
{
|
|
2670
2670
|
"defaultValue": "\"normal\"",
|
|
2671
|
-
"description": "Whitespace handling. 'normal' is CSS's own behaviour (newlines and space runs collapse) and stays the default. 'pre-wrap' is for text a PERSON typed — a plain-text note, an issue description, a pasted log — where the line breaks and the indentation are CONTENT: it keeps both, still wraps long lines at the container edge, and breaks an over-long unbroken token (a URL, an id) instead of overflowing. Use it INSTEAD of `className=\"whitespace-pre-wrap\"`. Precedence is explicit: `truncate` is a single-line contract and wins (dev builds warn); `clamp` COMPOSES with it, showing the first N preserved lines. Not for rendered Markdown/HTML — that is `Prose`, which styles rendered elements and does nothing to whitespace.",
|
|
2671
|
+
"description": "Whitespace handling. 'normal' is CSS's own behaviour (newlines and space runs collapse) and stays the default; passed explicitly it also releases a `nowrap` the text inherits (a table cell's, gh#1083). 'pre-wrap' is for text a PERSON typed — a plain-text note, an issue description, a pasted log — where the line breaks and the indentation are CONTENT: it keeps both, still wraps long lines at the container edge, and breaks an over-long unbroken token (a URL, an id) instead of overflowing. Use it INSTEAD of `className=\"whitespace-pre-wrap\"`. Precedence is explicit: `truncate` is a single-line contract and wins (dev builds warn); `clamp` COMPOSES with it, showing the first N preserved lines. Not for rendered Markdown/HTML — that is `Prose`, which styles rendered elements and does nothing to whitespace.",
|
|
2672
2672
|
"name": "whitespace",
|
|
2673
2673
|
"type": "\"normal\" | \"pre-wrap\""
|
|
2674
2674
|
},
|
|
@@ -3465,7 +3465,7 @@
|
|
|
3465
3465
|
},
|
|
3466
3466
|
{
|
|
3467
3467
|
"defaultValue": "'default'",
|
|
3468
|
-
"description": "Named collection contract — the SAME preset the Table primitive owns, forwarded to the table DataTable renders. 'default' emits NO attribute and matches no selector, so an existing DataTable is byte-identical. 'action-collection' is the canonical dense approval/action queue: below collapseBelow the desktop INTRINSIC column widths give way to the token-owned column-PRIORITY measures (--table-action-collection-*) under table-layout: fixed, cells wrap, and the bordered surface drops its --table-surface-min-inline-size floor — so requester · target · reason · requested date · row actions all stay inside a 390px frame with no horizontal scroll. Mark each column with `priority` on its ColumnDef. Semantics are untouched (no display change, no role rewriting, no card swap), so header association, aria-sort and screen-reader table navigation are identical at 390 and 1440. Measured: table 1182 / 766 / 388px at 1440 / 1024 / 390, document scrollWidth === clientWidth at every width, LTR and RTL. 'stacked-record-collection' is the other direction, for a WIDE, HETEROGENEOUS record set that has no sensible narrow column measure: below collapseBelow the <thead> hides and every <tr> becomes a bordered key-value card (--table-stacked-collection-*). Each cell then carries its column's header inline above the value, DERIVED from the same ColumnDef.header the <th> uses — so the card cannot drift from the table, and a column with a deliberately empty header names itself with ariaLabel (gh#864). The labels are aria-hidden: the real <th> is still in the DOM and remains the accessible-name source, so screen-reader table navigation is unchanged at every width. Reach for this instead of building a parallel Card tree beside the table; two trees for one dataset means two sets of labels to keep in sync.",
|
|
3468
|
+
"description": "Named collection contract — the SAME preset the Table primitive owns, forwarded to the table DataTable renders. 'default' emits NO attribute and matches no selector, so an existing DataTable is byte-identical. 'action-collection' is the canonical dense approval/action queue: below collapseBelow the desktop INTRINSIC column widths give way to the token-owned column-PRIORITY measures (--table-action-collection-*) under table-layout: fixed, cells wrap, and the bordered surface drops its --table-surface-min-inline-size floor — so requester · target · reason · requested date · row actions all stay inside a 390px frame with no horizontal scroll. Mark each column with `priority` on its ColumnDef. Semantics are untouched (no display change, no role rewriting, no card swap), so header association, aria-sort and screen-reader table navigation are identical at 390 and 1440. Measured: table 1182 / 766 / 388px at 1440 / 1024 / 390, document scrollWidth === clientWidth at every width, LTR and RTL. 'stacked-record-collection' is the other direction, for a WIDE, HETEROGENEOUS record set that has no sensible narrow column measure: below collapseBelow the <thead> hides and every <tr> becomes a bordered key-value card (--table-stacked-collection-*). Each cell then carries its column's header inline above the value, DERIVED from the same ColumnDef.header the <th> uses — so the card cannot drift from the table, and a column with a deliberately empty header names itself with ariaLabel (gh#864). In card mode the CARD owns the inline inset: a folded cell has no inline padding of its own (--table-stacked-collection-cell-padding-x, default 0), and an EMPTY cell (content null) prints no label and drops out of the card (gh#1102). The labels are aria-hidden: the real <th> is still in the DOM and remains the accessible-name source, so screen-reader table navigation is unchanged at every width. Reach for this instead of building a parallel Card tree beside the table; two trees for one dataset means two sets of labels to keep in sync.",
|
|
3469
3469
|
"name": "preset",
|
|
3470
3470
|
"type": "'default' | 'action-collection' | 'stacked-record-collection'"
|
|
3471
3471
|
},
|
|
@@ -3543,9 +3543,9 @@
|
|
|
3543
3543
|
"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 } }"
|
|
3544
3544
|
},
|
|
3545
3545
|
{
|
|
3546
|
-
"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.",
|
|
3546
|
+
"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. The detail cell is inset like any cell (antd) and wraps (white-space: normal) — retune the inset with --table-row-expanded-padding; flush: true drops it for a detail that owns its inset (a nested table, a ListRow list). Do NOT wrap the detail in Card/CardContent or Flex pad for spacing (gh#1083).",
|
|
3547
3547
|
"name": "expandable",
|
|
3548
|
-
"type": "{ expandedRowRender?: (row, index, expanded) => ReactNode; rowExpandable?: (row) => boolean; defaultExpandAllRows?: boolean; expandedRowKeys?: string[]; onExpandedRowsChange?: (keys) => void; expandRowByClick?: boolean; columnTitle?: ReactNode }"
|
|
3548
|
+
"type": "{ expandedRowRender?: (row, index, expanded) => ReactNode; rowExpandable?: (row) => boolean; defaultExpandAllRows?: boolean; expandedRowKeys?: string[]; onExpandedRowsChange?: (keys) => void; expandRowByClick?: boolean; columnTitle?: ReactNode; flush?: boolean }"
|
|
3549
3549
|
},
|
|
3550
3550
|
{
|
|
3551
3551
|
"description": "Footer totals row (antd summary), rendered in a real <tfoot> so it keeps the column widths and the screen-reader row navigation. Receives the rows currently rendered (post sort/filter/page), so a page total and a grand total are both expressible. Compose the return with <TableRow>/<TableCell> from the Table primitive.",
|
|
@@ -4081,7 +4081,7 @@
|
|
|
4081
4081
|
"type": "React.ComponentType<{ className?: string }> | null"
|
|
4082
4082
|
},
|
|
4083
4083
|
{
|
|
4084
|
-
"description": "Badge label. When omitted with status, Badge renders the translated lifecycle label or raw status.",
|
|
4084
|
+
"description": "Badge label. When omitted with status, Badge renders the translated lifecycle label or raw status. LONG LABEL CONTRACT (gh#1101): the chip is `max-inline-size: 100%` of its container and never wraps; the label ellipsizes and, when it was cut, shows the full text as a native `title` on hover (antd `Typography ellipsis`). A caller's own `title` on the Badge wins. So a Badge in a fixed-width DataTable cell or a narrow Card stays inside it with no extra props; `<Badge><Text ellipsis>` also works. Do not reach for `Text break=\"anywhere\"` to make a chip wrap.",
|
|
4085
4085
|
"name": "children",
|
|
4086
4086
|
"type": "ReactNode"
|
|
4087
4087
|
},
|
|
@@ -4106,7 +4106,7 @@
|
|
|
4106
4106
|
"subParts": [
|
|
4107
4107
|
"StatusBadge"
|
|
4108
4108
|
],
|
|
4109
|
-
"tagline": "Plain or lifecycle badge. Use `variant` for static chips, or `status` to auto-map lifecycle keys to semantic tone + icon. Labels never wrap.",
|
|
4109
|
+
"tagline": "Plain or lifecycle badge. Use `variant` for static chips, or `status` to auto-map lifecycle keys to semantic tone + icon. Labels never wrap: a label wider than its container ellipsizes, with the full text as a hover `title` (gh#1101).",
|
|
4110
4110
|
"usage": [
|
|
4111
4111
|
"DO pick the correct variant semantically: `success` (approved/paid), `warning` (pending/overdue), `destructive` (rejected/error), `secondary` (neutral category), `outline` (subtle label), `default` (primary accent). Never force a colour just for aesthetics — agents and screen readers read the variant as intent.",
|
|
4112
4112
|
"DO use `status` for entity lifecycle statuses (active, draft, pending, cancelled, failed, scheduled, etc.) so the component resolves the correct tone, icon, and i18n label.",
|
|
@@ -4209,6 +4209,92 @@
|
|
|
4209
4209
|
"A table cell whose column is 'colour' — one sample per row, named by the row header."
|
|
4210
4210
|
]
|
|
4211
4211
|
},
|
|
4212
|
+
{
|
|
4213
|
+
"example": "import { TextDiff } from \"@godxjp/ui/data-display\";\n\n<TextDiff before={row.previous_original} after={original} lang=\"ja\" />\n\n<TextDiff mode=\"split\" granularity=\"line\" before={previousBody} after={body} />",
|
|
4214
|
+
"group": "data-display",
|
|
4215
|
+
"importPath": "@godxjp/ui/data-display",
|
|
4216
|
+
"name": "TextDiff",
|
|
4217
|
+
"props": [
|
|
4218
|
+
{
|
|
4219
|
+
"description": "The earlier text (the original a translation was written against, the saved version).",
|
|
4220
|
+
"name": "before",
|
|
4221
|
+
"required": true,
|
|
4222
|
+
"type": "string"
|
|
4223
|
+
},
|
|
4224
|
+
{
|
|
4225
|
+
"description": "The current text.",
|
|
4226
|
+
"name": "after",
|
|
4227
|
+
"required": true,
|
|
4228
|
+
"type": "string"
|
|
4229
|
+
},
|
|
4230
|
+
{
|
|
4231
|
+
"defaultValue": "\"inline\"",
|
|
4232
|
+
"description": "inline — one flow with removals and additions in place (GitHub's unified view). split — two columns, before | after, with changed hunks aligned row by row and localized column headings.",
|
|
4233
|
+
"name": "mode",
|
|
4234
|
+
"type": "\"inline\" | \"split\""
|
|
4235
|
+
},
|
|
4236
|
+
{
|
|
4237
|
+
"defaultValue": "\"auto\"",
|
|
4238
|
+
"description": "The unit a change is measured in. auto = Intl.Segmenter words, with Han/Hiragana/Katakana/Hangul runs cut per character (no spaces to split on, and a dictionary word boundary moves when one particle changes). word = Intl.Segmenter words in `lang`. char = one grapheme cluster per token. line = whole lines.",
|
|
4239
|
+
"name": "granularity",
|
|
4240
|
+
"type": "\"auto\" | \"word\" | \"char\" | \"line\""
|
|
4241
|
+
},
|
|
4242
|
+
{
|
|
4243
|
+
"defaultValue": "true",
|
|
4244
|
+
"description": "Fold long unchanged runs of lines behind a localized 'show N unchanged lines' button.",
|
|
4245
|
+
"name": "collapseUnchanged",
|
|
4246
|
+
"type": "boolean"
|
|
4247
|
+
},
|
|
4248
|
+
{
|
|
4249
|
+
"defaultValue": "2",
|
|
4250
|
+
"description": "Unchanged lines kept visible beside each change when folding (git's -U<n>).",
|
|
4251
|
+
"name": "contextLines",
|
|
4252
|
+
"type": "number"
|
|
4253
|
+
},
|
|
4254
|
+
{
|
|
4255
|
+
"defaultValue": "4000000",
|
|
4256
|
+
"description": "LCS cost cap (tokens before × tokens after). Past it the changed middle is one removal plus one addition instead of freezing the tab.",
|
|
4257
|
+
"name": "maxCells",
|
|
4258
|
+
"type": "number"
|
|
4259
|
+
},
|
|
4260
|
+
{
|
|
4261
|
+
"description": "Heading of the before column in split mode. Default: localized 'Before'.",
|
|
4262
|
+
"name": "beforeLabel",
|
|
4263
|
+
"type": "ReactNode"
|
|
4264
|
+
},
|
|
4265
|
+
{
|
|
4266
|
+
"description": "Heading of the after column in split mode. Default: localized 'After'.",
|
|
4267
|
+
"name": "afterLabel",
|
|
4268
|
+
"type": "ReactNode"
|
|
4269
|
+
},
|
|
4270
|
+
{
|
|
4271
|
+
"description": "BCP-47 language of the text — set on the element (screen-reader pronunciation, CJK font selection) and used as the Intl.Segmenter locale.",
|
|
4272
|
+
"name": "lang",
|
|
4273
|
+
"type": "string"
|
|
4274
|
+
}
|
|
4275
|
+
],
|
|
4276
|
+
"related": [
|
|
4277
|
+
"CodeBlock — shows ONE preformatted text; TextDiff shows how two versions differ.",
|
|
4278
|
+
"Text — `delete` / `mark` style a run you already chose; TextDiff decides the runs and announces them.",
|
|
4279
|
+
"Timeline — the list of revisions; TextDiff is what one revision changed."
|
|
4280
|
+
],
|
|
4281
|
+
"rules": [],
|
|
4282
|
+
"storyPath": "data-display/TextDiff.stories.tsx",
|
|
4283
|
+
"tagline": "What changed between two versions of a text — removed runs in <del>, added runs in <ins>, inline or side by side, per line / word / character, with CJK cut per character and long unchanged runs folded.",
|
|
4284
|
+
"usage": [
|
|
4285
|
+
"DO import from `@godxjp/ui/data-display`: `import { TextDiff } from \"@godxjp/ui/data-display\";`",
|
|
4286
|
+
"DO pass the two raw strings — the component tokenizes, diffs (LCS) and renders. Use the exported `diffText(before, after, { granularity, lang })` only when you need the runs themselves (a change count, a plain-text export).",
|
|
4287
|
+
"DO pass `lang` for the text's language, not the UI's: a Japanese original in an English UI still needs lang=\"ja\".",
|
|
4288
|
+
"DO use mode=\"split\" when there is room for two columns and the texts are long; inline for a drawer, a list row or a narrow panel.",
|
|
4289
|
+
"DON'T hand-roll a diff from `Text delete` / `Text mark` — those carry no spoken start/end label, so a screen reader reads the old and new words run together.",
|
|
4290
|
+
"DON'T colour a run without its mark: removals are struck through and additions underlined, plus a visually hidden start/end label — colour is never the only carrier (WCAG 1.4.1)."
|
|
4291
|
+
],
|
|
4292
|
+
"useCases": [
|
|
4293
|
+
"A translation drawer: what changed in the original since this translation was written (old original → current original).",
|
|
4294
|
+
"A document or wiki page revision history: one revision against the previous one.",
|
|
4295
|
+
"A settings or template audit log: the previous value of a long text field against the new one."
|
|
4296
|
+
]
|
|
4297
|
+
},
|
|
4212
4298
|
{
|
|
4213
4299
|
"docPath": "data-display/feature-list.tsx",
|
|
4214
4300
|
"example": "import { FeatureList } from \"@godxjp/ui/data-display\";\n\n<FeatureList\n items={[\n { state: \"included\", label: \"SSO\", description: \"SAML と OIDC\" },\n { state: \"limited\", label: \"API 呼び出し\", description: \"月 10,000 回まで\" },\n { state: \"excluded\", label: \"監査ログのエクスポート\" },\n ]}\n/>",
|
|
@@ -5175,7 +5261,7 @@
|
|
|
5175
5261
|
},
|
|
5176
5262
|
{
|
|
5177
5263
|
"defaultValue": "\"default\"",
|
|
5178
|
-
"description": "Named collection contract. \"default\" emits no attribute and keeps the plain table. \"action-collection\" is the canonical dense approval/action queue: the desktop INTRINSIC column widths (which make a five-column queue wider than its card and force a horizontal scroll at 390) are replaced by table-layout: fixed plus the token-owned column PRIORITY measures (--table-action-collection-*), and cells wrap. Mark each column with `priority` on its TableHead AND its TableCell. Semantics are untouched — no display change, no role rewriting, no card transformation — so header association, aria-sort and screen-reader table navigation are identical at 390 and 1440. \"stacked-record-collection\" is the other direction, for a WIDE, HETEROGENEOUS record set with no sensible narrow column measure: below collapseBelow the <thead> hides and every <tr> becomes a bordered key-value card (--table-stacked-collection-*). Give each TableCell a `label` — its column header — because the <th> association it normally reads from is the thing that just went away; DataTable derives that label from ColumnDef.header for you (gh#864). The label is aria-hidden and the real <th> stays in the DOM, so the accessible name and table navigation are unchanged.",
|
|
5264
|
+
"description": "Named collection contract. \"default\" emits no attribute and keeps the plain table. \"action-collection\" is the canonical dense approval/action queue: the desktop INTRINSIC column widths (which make a five-column queue wider than its card and force a horizontal scroll at 390) are replaced by table-layout: fixed plus the token-owned column PRIORITY measures (--table-action-collection-*), and cells wrap. Mark each column with `priority` on its TableHead AND its TableCell. Semantics are untouched — no display change, no role rewriting, no card transformation — so header association, aria-sort and screen-reader table navigation are identical at 390 and 1440. \"stacked-record-collection\" is the other direction, for a WIDE, HETEROGENEOUS record set with no sensible narrow column measure: below collapseBelow the <thead> hides and every <tr> becomes a bordered key-value card (--table-stacked-collection-*). Give each TableCell a `label` — its column header — because the <th> association it normally reads from is the thing that just went away; DataTable derives that label from ColumnDef.header for you (gh#864). In card mode the CARD owns the inline inset: a folded cell has no inline padding of its own (--table-stacked-collection-cell-padding-x, default 0), and an EMPTY cell (content null) prints no label and drops out of the card (gh#1102). The label is aria-hidden and the real <th> stays in the DOM, so the accessible name and table navigation are unchanged.",
|
|
5179
5265
|
"name": "preset",
|
|
5180
5266
|
"type": "\"default\" | \"action-collection\" | \"stacked-record-collection\""
|
|
5181
5267
|
},
|
package/agent/index.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"counts": {
|
|
3
3
|
"anti-ai-tells": 26,
|
|
4
|
-
"components":
|
|
4
|
+
"components": 179,
|
|
5
5
|
"patterns": 21,
|
|
6
6
|
"rules": 50,
|
|
7
|
-
"tokens":
|
|
7
|
+
"tokens": 2129,
|
|
8
8
|
"vocabulary": 14
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
11
|
{
|
|
12
12
|
"file": "components-index.json",
|
|
13
|
-
"note": "48 KB — name + group + tagline for all
|
|
13
|
+
"note": "48 KB — name + group + tagline for all 179. FETCH THIS FIRST, then fetch only the components you chose.",
|
|
14
14
|
"url": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components-index.json"
|
|
15
15
|
},
|
|
16
16
|
{
|
|
@@ -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.17.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": 1814,
|
|
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.17.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:
|
|
4
|
-
> 50 cardinal rules. This file is the entry point for AI agents. Catalog version 31.
|
|
3
|
+
> A Japanese-enterprise React design system: 179 components, 2129 design tokens,
|
|
4
|
+
> 50 cardinal rules. This file is the entry point for AI agents. Catalog version 31.17.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.17.0`). It is searchable and version-locked. These files exist for agents
|
|
8
8
|
that can only fetch URLs.
|
|
9
9
|
|
|
10
10
|
## Start
|
|
@@ -15,10 +15,10 @@ that can only fetch URLs.
|
|
|
15
15
|
## Catalog
|
|
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
|
-
- [components-index.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components-index.json): 48 KB — all
|
|
18
|
+
- [components-index.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components-index.json): 48 KB — all 179 components as name, group, tagline, plus `absorbed`: the names that do NOT exist and map to it (`Combobox` → `Select`).
|
|
19
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, 1814 `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.17.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.
|
package/agent/tokens.json
CHANGED
|
@@ -5651,6 +5651,36 @@
|
|
|
5651
5651
|
"tier": "component",
|
|
5652
5652
|
"value": "initial"
|
|
5653
5653
|
},
|
|
5654
|
+
{
|
|
5655
|
+
"description": "TextDiff (gh#1096) — the grounds under a removed and an added run. The INK stays the text colour: the mark that carries the meaning is the strike-through / underline plus a spoken label, so the tint only has to separate the run from its neighbours. The grounds read the status surface role (gh#866) and fall back to the tone at these alphas.",
|
|
5656
|
+
"name": "--text-diff-removed-background-alpha",
|
|
5657
|
+
"tier": "component",
|
|
5658
|
+
"value": "0.12"
|
|
5659
|
+
},
|
|
5660
|
+
{
|
|
5661
|
+
"description": "Data-display component tokens — small-by-design text knobs (rule #45/#46).",
|
|
5662
|
+
"name": "--text-diff-added-background-alpha",
|
|
5663
|
+
"tier": "component",
|
|
5664
|
+
"value": "0.16"
|
|
5665
|
+
},
|
|
5666
|
+
{
|
|
5667
|
+
"description": "The underline/strike weight — the resting hairline, so it survives forced-colors as ink.",
|
|
5668
|
+
"name": "--text-diff-mark-line-width",
|
|
5669
|
+
"tier": "component",
|
|
5670
|
+
"value": "var(--stroke-hairline)"
|
|
5671
|
+
},
|
|
5672
|
+
{
|
|
5673
|
+
"description": "Space between the before and after columns in split mode, and around a folded run.",
|
|
5674
|
+
"name": "--text-diff-space-gap",
|
|
5675
|
+
"tier": "component",
|
|
5676
|
+
"value": "var(--space-3)"
|
|
5677
|
+
},
|
|
5678
|
+
{
|
|
5679
|
+
"description": "Data-display component tokens — small-by-design text knobs (rule #45/#46).",
|
|
5680
|
+
"name": "--text-diff-space-inset",
|
|
5681
|
+
"tier": "component",
|
|
5682
|
+
"value": "var(--space-2)"
|
|
5683
|
+
},
|
|
5654
5684
|
{
|
|
5655
5685
|
"description": "Timeline accents — `initial` so the dot/line role defaults re-resolve under a scoped theme. ONE HUE down the whole progress column (gh#731): done, current and the travelled line all default to hsl(var(--primary)), the way Steps paints `finish` and `process`; current is told apart by its ring, not by a second role. To restore the pre-27.9 green/violet pairing, set the done dot's FILL and its INK together — the two roles have opposite ink polarity, so the fill alone leaves a near-white glyph on 若竹 green at 2.19:1 (gh#643): --timeline-dot-done-background: hsl(var(--success)); --timeline-dot-done-foreground: hsl(var(--success-foreground));",
|
|
5656
5686
|
"name": "--timeline-dot-done-background",
|
|
@@ -9059,6 +9089,12 @@
|
|
|
9059
9089
|
"tier": "component",
|
|
9060
9090
|
"value": "8rem"
|
|
9061
9091
|
},
|
|
9092
|
+
{
|
|
9093
|
+
"description": "Ceiling of the menu surface's intrinsic width (gh#1103). The surface is `width: max-content` so its width never depends on the provisional `left` it is first laid out at; this keeps a long label inside the viewport, less React Aria's default 12px container padding each side.",
|
|
9094
|
+
"name": "--dropdown-content-max-width",
|
|
9095
|
+
"tier": "component",
|
|
9096
|
+
"value": "calc(100vw - 1.5rem)"
|
|
9097
|
+
},
|
|
9062
9098
|
{
|
|
9063
9099
|
"description": "THE MENU SURFACE (gh#880). `.ui-dropdown-menu-content` painted `hsl(var(--popover))` with no knob, while `.ui-popover-content` — the same kind of floating panel, in the same portal — had `--popover-surface-background`. That asymmetry is the shape of defect this repo keeps paying for: the theme reaches two of the three menu surfaces and the third silently stays opaque. A DROPDOWN IS THE MOST OPAQUE MEMBER OF THE FAMILY, by the standard's own rule (docs/GLASSMORPHISM-STANDARD.md §4): it is small, it sits over arbitrary content, and a 7-line menu over a photograph is unreadable at a card's alpha. It therefore gets its OWN fill knob rather than sharing the popover's — the two are meant to be able to differ. default = hsl(var(--popover)) at the call site",
|
|
9064
9100
|
"name": "--dropdown-content-background",
|
|
@@ -11669,6 +11705,12 @@
|
|
|
11669
11705
|
"tier": "component",
|
|
11670
11706
|
"value": "initial"
|
|
11671
11707
|
},
|
|
11708
|
+
{
|
|
11709
|
+
"description": "Inset of the expanded detail cell (gh#1083). `initial` so the default — the cell's own padding, var(--table-cell-padding-y) var(--table-cell-space-x), which follows density — re-resolves at the call site. `expandable.flush` drops it.",
|
|
11710
|
+
"name": "--table-row-expanded-padding",
|
|
11711
|
+
"tier": "component",
|
|
11712
|
+
"value": "initial"
|
|
11713
|
+
},
|
|
11672
11714
|
{
|
|
11673
11715
|
"description": "Gap between the header checkbox and the `selections` dropdown trigger beside it.",
|
|
11674
11716
|
"name": "--table-selection-menu-gap",
|
|
@@ -11837,6 +11879,12 @@
|
|
|
11837
11879
|
"tier": "component",
|
|
11838
11880
|
"value": "var(--space-stack-xs)"
|
|
11839
11881
|
},
|
|
11882
|
+
{
|
|
11883
|
+
"description": "Inline inset of a folded cell inside its card (gh#1102). 0: the card's own --table-stacked-collection-card-padding-x is the inset, so a value line gets the card's full content width instead of losing the table's cell padding on both sides.",
|
|
11884
|
+
"name": "--table-stacked-collection-cell-padding-x",
|
|
11885
|
+
"tier": "component",
|
|
11886
|
+
"value": "0"
|
|
11887
|
+
},
|
|
11840
11888
|
{
|
|
11841
11889
|
"description": "Table component tokens: row height, cell padding.",
|
|
11842
11890
|
"name": "--table-stacked-collection-label-font-size",
|
|
@@ -105,6 +105,14 @@ const badgeToneClass = {
|
|
|
105
105
|
muted: cn("border-transparent", toneMutedClass),
|
|
106
106
|
neutral: cn("border-transparent", toneNeutralClass)
|
|
107
107
|
};
|
|
108
|
+
function titleTruncatedLabel(event) {
|
|
109
|
+
const label = event.currentTarget;
|
|
110
|
+
if (label.scrollWidth > label.clientWidth) {
|
|
111
|
+
label.title = label.textContent?.replace(/\s+/g, " ").trim() ?? "";
|
|
112
|
+
} else {
|
|
113
|
+
label.removeAttribute("title");
|
|
114
|
+
}
|
|
115
|
+
}
|
|
108
116
|
function Badge({
|
|
109
117
|
as: Element = "div",
|
|
110
118
|
className,
|
|
@@ -165,7 +173,15 @@ function Badge({
|
|
|
165
173
|
...props,
|
|
166
174
|
children: [
|
|
167
175
|
ResolvedIcon ? /* @__PURE__ */ jsx(ResolvedIcon, { "data-slot": "badge-icon", "aria-hidden": "true" }) : null,
|
|
168
|
-
resolvedChildren != null ? /* @__PURE__ */ jsx(
|
|
176
|
+
resolvedChildren != null ? /* @__PURE__ */ jsx(
|
|
177
|
+
"span",
|
|
178
|
+
{
|
|
179
|
+
ref: labelRef,
|
|
180
|
+
"data-slot": "badge-label",
|
|
181
|
+
onPointerEnter: props.title == null ? titleTruncatedLabel : void 0,
|
|
182
|
+
children: resolvedChildren
|
|
183
|
+
}
|
|
184
|
+
) : null,
|
|
169
185
|
onRemove ? /* @__PURE__ */ jsx(
|
|
170
186
|
"button",
|
|
171
187
|
{
|
|
@@ -1356,7 +1356,7 @@ DataTable.Content = function DataTableContent() {
|
|
|
1356
1356
|
{
|
|
1357
1357
|
className: "ui-data-table-expanded-row hover:bg-transparent",
|
|
1358
1358
|
"data-expanded-row": "",
|
|
1359
|
-
children: /* @__PURE__ */ jsx(TableCell, { colSpan: emptyColSpan, flush:
|
|
1359
|
+
children: /* @__PURE__ */ jsx(TableCell, { colSpan: emptyColSpan, flush: expandable.flush, children: expandable.expandedRowRender(original, rowIndex, true) })
|
|
1360
1360
|
}
|
|
1361
1361
|
) : null
|
|
1362
1362
|
] }, row.id);
|
|
@@ -412,7 +412,12 @@ const ImageRoot = React.forwardRef(function Image({
|
|
|
412
412
|
status: "loading"
|
|
413
413
|
});
|
|
414
414
|
const status = load.src === src ? load.status : "loading";
|
|
415
|
-
const setStatus = React.useCallback(
|
|
415
|
+
const setStatus = React.useCallback(
|
|
416
|
+
(next) => setLoad(
|
|
417
|
+
(prev) => prev.src === src && prev.status === "error" ? prev : { src, status: next }
|
|
418
|
+
),
|
|
419
|
+
[src]
|
|
420
|
+
);
|
|
416
421
|
const imgRef = React.useRef(null);
|
|
417
422
|
const setImgRef = React.useCallback(
|
|
418
423
|
(node) => {
|