@godxjp/ui 32.10.1 → 32.11.1
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/DESIGN.md +4 -4
- package/README.md +3 -3
- package/agent/DESIGN.md +4 -4
- package/agent/START-HERE.md +3 -3
- package/agent/components/BlockEditor.json +1 -1
- package/agent/components/DataTable.json +1 -1
- package/agent/components/LegalDocumentShell.json +2 -1
- package/agent/components/Markdown.json +1 -0
- package/agent/components/Prose.json +1 -0
- package/agent/components/SplitPane.json +1 -0
- package/agent/components/Table.json +1 -1
- package/agent/components.json +8 -4
- package/agent/index.json +5 -5
- package/agent/llms.txt +6 -6
- package/agent/tokens.json +6 -0
- package/dist/contracts/measurement.json +1 -1
- package/dist/styles/data-display-layout.css +5 -0
- package/dist/styles/layers.json +1 -1
- package/dist/styles/layout.css +26 -1
- package/dist/styles/table-layout.css +5 -0
- package/dist/styles.css +1 -1
- package/dist/tokens/semantic/layout.css +2 -0
- package/package.json +2 -2
package/DESIGN.md
CHANGED
|
@@ -104,7 +104,7 @@ Colour is scarce. Most of the screen is canvas, ink and hairline.
|
|
|
104
104
|
|
|
105
105
|
- One family. Hierarchy from size steps, weight 400/500/700 and `ink` vs `ink-muted`. Page title ~20px; anything larger belongs on a marketing page. One exception: a long-form document title (Reader) is ~22px, two steps above its ~17.6px section headings, because one step reads flat there.
|
|
106
106
|
- Body 14px / 1.7. Captions and meta 12.5px muted. `Text tabular` on every number, time and money column.
|
|
107
|
-
- Japanese prose: `Text break="phrase"` so lines break between phrases.
|
|
107
|
+
- Japanese prose: `Text break="phrase"` so lines break between phrases. `Prose`/`Markdown` and `LegalDocumentShell` bodies do this themselves under `lang="ja"`.
|
|
108
108
|
- Copy is quiet and factual: no praise, no alarm, no emoji, no em dash in UI strings. A success message states the fact (「承認しました」).
|
|
109
109
|
|
|
110
110
|
## Layout & Density
|
|
@@ -148,11 +148,11 @@ Header: record name as title, status `Badge` beside it, actions in `extra` (one
|
|
|
148
148
|
|
|
149
149
|
### Editor
|
|
150
150
|
|
|
151
|
-
Edit (or create) one document or record. Header: record name as title, status `Badge` beside it, a subtitle only for a fact such as when it was last saved, and ONE primary Save in `extra` (`Button type="submit" form=<form id>`), Cancel `outline` before it. Body: one `Form` in a `SplitPane`: the main column holds the title field and a large body editor (`BlockEditor`, or `Textarea autoSize`); the aside holds metadata fields and read-only facts in `Descriptions`. The change note goes either directly under the body (where the writer finishes) or last in the aside — pick one per app and keep it. Name each aside group with a `Heading level={2}` one step above its field labels. A part that is its own controlled component with its own `Form` (forms cannot nest) stays a separate form; the header Save then submits by handler (`onClick`) instead of `form=<id>`, still one Save. No Card per field group, no second Save at the bottom.
|
|
151
|
+
Edit (or create) one document or record. Header: record name as title, status `Badge` beside it, a subtitle only for a fact such as when it was last saved, and ONE primary Save in `extra` (`Button type="submit" form=<form id>`), Cancel `outline` before it. Body: one `Form` in a `SplitPane`: the main column holds the title field and a large body editor (`BlockEditor`, or `Textarea autoSize`); the aside holds metadata fields and read-only facts in `Descriptions`. The change note goes either directly under the body (where the writer finishes) or last in the aside — pick one per app and keep it. Name each aside group with a `Heading level={2}` one step above its field labels. The main↔aside gap is `--split-pane-gap` (default 16px); set it once in the theme. A part that is its own controlled component with its own `Form` (forms cannot nest) stays a separate form; the header Save then submits by handler (`onClick`) instead of `form=<id>`, still one Save. No Card per field group, no second Save at the bottom.
|
|
152
152
|
|
|
153
153
|
### Reader
|
|
154
154
|
|
|
155
|
-
A long-form document to read. The document owns the page's one `<h1>`: `PageContainer` gets `breadcrumb` and `extra` (Edit) and no `title`. `LegalDocumentShell` draws the reading column: title two steps above the section headings, one metadata line (version, date with `dateKind="updated"` for a revision), the contents rail, and prose at a reading measure
|
|
155
|
+
A long-form document to read. The document owns the page's one `<h1>`: `PageContainer` gets `breadcrumb` and `extra` (Edit) and no `title`. `LegalDocumentShell` draws the reading column: title two steps above the section headings, one metadata line (version, date with `dateKind="updated"` for a revision), the contents rail, and prose at a reading measure (Japanese breaks between phrases under `lang="ja"`; stacked, a contents entry hugs its label). No Card around the article, no subtitle, no icon per heading.
|
|
156
156
|
|
|
157
157
|
### Settings
|
|
158
158
|
|
|
@@ -215,5 +215,5 @@ A list whose rows are decisions. Show requester, target, reason, submitted time;
|
|
|
215
215
|
- `card-per-section` counts Cards per file, so a screen split across components can pass with a Card around every section.
|
|
216
216
|
- Exemplar previews deploy on release tags, so they can lag `main`. On GitHub Pages a showcase URL answers HTTP 404 and renders through `404.html`, so open it in a browser; a plain fetch sees the 404.
|
|
217
217
|
- Dark theme (`data-theme="dark"`) is supported; the exemplars are reviewed in light.
|
|
218
|
-
- From 640px up, `BlockEditor` text does not share the keyline of the `Input` above it: measured at 768/1024/1280, input text 13px inside its frame, editor text 57px inside (Δ44px), because the ⋮⋮/+ handles (two 24px targets) sit in a start gutter inside the frame. Aligning the text would put the handles outside the field border, where a content column 24px from the viewport edge has no room. Below 640px the gutter collapses (C05). Accepted, not a defect to fix in the app.
|
|
218
|
+
- From 640px up, `BlockEditor` text does not share the keyline of the `Input` above it: measured at 768/1024/1280, input text 13px inside its frame, editor text 57px inside (Δ44px), because the ⋮⋮/+ handles (two 24px targets) sit in a start gutter inside the frame. Aligning the text would put the handles outside the field border, where a content column 24px from the viewport edge has no room. Below 640px the gutter collapses (C05). `--block-editor-gutter-inline-size` sets the gutter width; it cannot close the gap, because the handles live inside it. Accepted, not a defect to fix in the app.
|
|
219
219
|
- On narrow screens the `PageContainer` title steps down (≈17.6px) while body h2 stays ≈15.7px — one step apart. A document page not built on `LegalDocumentShell` keeps only that step on phones; there is no intermediate page-title size yet.
|
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ npm i @godxjp/ui
|
|
|
18
18
|
|
|
19
19
|
<!-- agent-catalog-counts:start -->
|
|
20
20
|
|
|
21
|
-
The catalog — 162 components,
|
|
21
|
+
The catalog — 162 components, 2204 tokens, 43 cardinal rules — is published in two forms from one
|
|
22
22
|
source. **Entry point for either: [`AGENTS.md`](AGENTS.md).**
|
|
23
23
|
<!-- agent-catalog-counts:end -->
|
|
24
24
|
|
|
@@ -51,12 +51,12 @@ static files straight from this public repo — no hosting, no deploy step:
|
|
|
51
51
|
| --- | --- | --- |
|
|
52
52
|
| [`agent/START-HERE.md`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/START-HERE.md) | 11 KB | **read first** — self-contained: the four rules, the token override model, a page that passes review |
|
|
53
53
|
| [`agent/llms.txt`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/llms.txt) | 3 KB | the [llms.txt](https://llmstxt.org/) entry point |
|
|
54
|
-
| [`agent/DESIGN.md`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/DESIGN.md) |
|
|
54
|
+
| [`agent/DESIGN.md`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/DESIGN.md) | 17 KB | the visual spec: tokens, colour scarcity, admin screen anatomy, do/don't |
|
|
55
55
|
| [`agent/index.json`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/index.json) | 3 KB | manifest: version, counts, every file's URL |
|
|
56
56
|
| [`agent/components-index.json`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components-index.json) | 48 KB | all 162 as name + group + tagline — **fetch this first** |
|
|
57
57
|
| [`agent/components/<Name>.json`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components/Select.json) | 1 KB–37 KB | one file per component, each with its `importPath` — **this is the route to take** |
|
|
58
58
|
| [`agent/components.json`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components.json) | 1.2 MB | all 162 entries in one file — most URL fetchers truncate this silently; prefer the per-component files |
|
|
59
|
-
| [`agent/tokens.json`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/tokens.json) |
|
|
59
|
+
| [`agent/tokens.json`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/tokens.json) | 849 KB | all 2204 design tokens, their values and why they exist |
|
|
60
60
|
| [`agent/vocabulary.json`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/vocabulary.json) | 7 KB | the controlled prop vocabulary |
|
|
61
61
|
| [`agent/rules.json`](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/rules.json) | 21 KB | the 43 cardinal rules |
|
|
62
62
|
<!-- prettier-ignore-end -->
|
package/agent/DESIGN.md
CHANGED
|
@@ -104,7 +104,7 @@ Colour is scarce. Most of the screen is canvas, ink and hairline.
|
|
|
104
104
|
|
|
105
105
|
- One family. Hierarchy from size steps, weight 400/500/700 and `ink` vs `ink-muted`. Page title ~20px; anything larger belongs on a marketing page. One exception: a long-form document title (Reader) is ~22px, two steps above its ~17.6px section headings, because one step reads flat there.
|
|
106
106
|
- Body 14px / 1.7. Captions and meta 12.5px muted. `Text tabular` on every number, time and money column.
|
|
107
|
-
- Japanese prose: `Text break="phrase"` so lines break between phrases.
|
|
107
|
+
- Japanese prose: `Text break="phrase"` so lines break between phrases. `Prose`/`Markdown` and `LegalDocumentShell` bodies do this themselves under `lang="ja"`.
|
|
108
108
|
- Copy is quiet and factual: no praise, no alarm, no emoji, no em dash in UI strings. A success message states the fact (「承認しました」).
|
|
109
109
|
|
|
110
110
|
## Layout & Density
|
|
@@ -148,11 +148,11 @@ Header: record name as title, status `Badge` beside it, actions in `extra` (one
|
|
|
148
148
|
|
|
149
149
|
### Editor
|
|
150
150
|
|
|
151
|
-
Edit (or create) one document or record. Header: record name as title, status `Badge` beside it, a subtitle only for a fact such as when it was last saved, and ONE primary Save in `extra` (`Button type="submit" form=<form id>`), Cancel `outline` before it. Body: one `Form` in a `SplitPane`: the main column holds the title field and a large body editor (`BlockEditor`, or `Textarea autoSize`); the aside holds metadata fields and read-only facts in `Descriptions`. The change note goes either directly under the body (where the writer finishes) or last in the aside — pick one per app and keep it. Name each aside group with a `Heading level={2}` one step above its field labels. A part that is its own controlled component with its own `Form` (forms cannot nest) stays a separate form; the header Save then submits by handler (`onClick`) instead of `form=<id>`, still one Save. No Card per field group, no second Save at the bottom.
|
|
151
|
+
Edit (or create) one document or record. Header: record name as title, status `Badge` beside it, a subtitle only for a fact such as when it was last saved, and ONE primary Save in `extra` (`Button type="submit" form=<form id>`), Cancel `outline` before it. Body: one `Form` in a `SplitPane`: the main column holds the title field and a large body editor (`BlockEditor`, or `Textarea autoSize`); the aside holds metadata fields and read-only facts in `Descriptions`. The change note goes either directly under the body (where the writer finishes) or last in the aside — pick one per app and keep it. Name each aside group with a `Heading level={2}` one step above its field labels. The main↔aside gap is `--split-pane-gap` (default 16px); set it once in the theme. A part that is its own controlled component with its own `Form` (forms cannot nest) stays a separate form; the header Save then submits by handler (`onClick`) instead of `form=<id>`, still one Save. No Card per field group, no second Save at the bottom.
|
|
152
152
|
|
|
153
153
|
### Reader
|
|
154
154
|
|
|
155
|
-
A long-form document to read. The document owns the page's one `<h1>`: `PageContainer` gets `breadcrumb` and `extra` (Edit) and no `title`. `LegalDocumentShell` draws the reading column: title two steps above the section headings, one metadata line (version, date with `dateKind="updated"` for a revision), the contents rail, and prose at a reading measure
|
|
155
|
+
A long-form document to read. The document owns the page's one `<h1>`: `PageContainer` gets `breadcrumb` and `extra` (Edit) and no `title`. `LegalDocumentShell` draws the reading column: title two steps above the section headings, one metadata line (version, date with `dateKind="updated"` for a revision), the contents rail, and prose at a reading measure (Japanese breaks between phrases under `lang="ja"`; stacked, a contents entry hugs its label). No Card around the article, no subtitle, no icon per heading.
|
|
156
156
|
|
|
157
157
|
### Settings
|
|
158
158
|
|
|
@@ -215,5 +215,5 @@ A list whose rows are decisions. Show requester, target, reason, submitted time;
|
|
|
215
215
|
- `card-per-section` counts Cards per file, so a screen split across components can pass with a Card around every section.
|
|
216
216
|
- Exemplar previews deploy on release tags, so they can lag `main`. On GitHub Pages a showcase URL answers HTTP 404 and renders through `404.html`, so open it in a browser; a plain fetch sees the 404.
|
|
217
217
|
- Dark theme (`data-theme="dark"`) is supported; the exemplars are reviewed in light.
|
|
218
|
-
- From 640px up, `BlockEditor` text does not share the keyline of the `Input` above it: measured at 768/1024/1280, input text 13px inside its frame, editor text 57px inside (Δ44px), because the ⋮⋮/+ handles (two 24px targets) sit in a start gutter inside the frame. Aligning the text would put the handles outside the field border, where a content column 24px from the viewport edge has no room. Below 640px the gutter collapses (C05). Accepted, not a defect to fix in the app.
|
|
218
|
+
- From 640px up, `BlockEditor` text does not share the keyline of the `Input` above it: measured at 768/1024/1280, input text 13px inside its frame, editor text 57px inside (Δ44px), because the ⋮⋮/+ handles (two 24px targets) sit in a start gutter inside the frame. Aligning the text would put the handles outside the field border, where a content column 24px from the viewport edge has no room. Below 640px the gutter collapses (C05). `--block-editor-gutter-inline-size` sets the gutter width; it cannot close the gap, because the handles live inside it. Accepted, not a defect to fix in the app.
|
|
219
219
|
- On narrow screens the `PageContainer` title steps down (≈17.6px) while body h2 stays ≈15.7px — one step apart. A document page not built on `LegalDocumentShell` keeps only that step on phones; there is no intermediate page-title size yet.
|
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` 32.
|
|
6
|
+
**This catalog describes `@godxjp/ui` 32.11.1.** 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.
|
|
@@ -61,7 +61,7 @@ screen anatomy, the visual target the rules below do not give you. Then fetch in
|
|
|
61
61
|
its `importPath`, and its examples. Fetch only the handful you picked in step 1.
|
|
62
62
|
3. `rules.json` — 43 cardinal rules. The ones about raw HTML and hardcoded colour are not
|
|
63
63
|
style advice.
|
|
64
|
-
4. `tokens.json` —
|
|
64
|
+
4. `tokens.json` — 2204 design tokens, each tagged with its `tier`. **If you were handed a
|
|
65
65
|
brand, read the 211 `foundation` entries first** — `--primary`, `--background`,
|
|
66
66
|
`--radius`, `--font-size-base` are the handful everything else derives from. The
|
|
67
67
|
1880 `component` entries are per-part knobs; reach for one only when a role is
|
|
@@ -149,7 +149,7 @@ has stopped following the brand.
|
|
|
149
149
|
| `tier` | count | what it is | set it? |
|
|
150
150
|
|---|---|---|---|
|
|
151
151
|
| `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.** The default `--primary` is a neutral placeholder: set it (`:root { --primary: <H> <S>% <L>%; }`, HSL components, no `hsl()` wrapper) or import a theme preset such as `@godxjp/ui/themes/godx.css` |
|
|
152
|
-
| `semantic` |
|
|
152
|
+
| `semantic` | 113 | 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 |
|
|
153
153
|
| `component` | 1880 | 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` |
|
|
154
154
|
|
|
155
155
|
A token whose `value` is `initial` is not empty and not broken: `initial` is the guaranteed-invalid
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"storyPath": "data-entry/block-editor.tsx",
|
|
81
81
|
"tagline": "Notion / note.com style block editor (sibling package `@godxjp/block-editor`, versioned with the kit) that reads and writes MARKDOWN through `@godxjp/markdown/codec`: what onValueChange returns is byte-for-byte normalize(body). `/` block menu at the caret, ⋮⋮ handle (drag, turn into, duplicate, move, delete), floating format toolbar, `[[` wikilink suggestions, paste / drop uploads through the host, IME-safe, ja / en / vi (gh#1156).",
|
|
82
82
|
"usage": [
|
|
83
|
-
"Below 40rem the handle gutter collapses to `--block-editor-compact-gutter-inline-size` (the frame inset, 12px) and the + / ⋮⋮ handle rises above the caret's block at its inline end (ADR C05): first line 56px → 12px from the inner edge at 390px. Touch: tap a block to show its handle; ⋮⋮ opens Move up / Move down / Duplicate / Delete. Keyboard: Mod+/ opens the same menu, Alt+Shift+↑↓ moves the block.",
|
|
83
|
+
"From 40rem up the + / ⋮⋮ handles sit in a start gutter INSIDE the frame, `--block-editor-gutter-inline-size` (default 2 × 24px targets + 8px = 56px); it tunes that width but cannot put the text on a sibling Input's keyline, because the handles live in it (DESIGN.md Known Gaps, gh#1310). Below 40rem the handle gutter collapses to `--block-editor-compact-gutter-inline-size` (the frame inset, 12px) and the + / ⋮⋮ handle rises above the caret's block at its inline end (ADR C05): first line 56px → 12px from the inner edge at 390px. Touch: tap a block to show its handle; ⋮⋮ opens Move up / Move down / Duplicate / Delete. Keyboard: Mod+/ opens the same menu, Alt+Shift+↑↓ moves the block.",
|
|
84
84
|
"Clicking a link (or Mod+K) opens a settings drawer: text, URL, title, open / remove. Clicking an image opens one for src, alt, title, replace (pickMedia / upload) and remove. Markdown stores no link target, so there is no target field. A link in the editor never navigates mid-edit.",
|
|
85
85
|
"YAML front matter shows as a Properties block at the top and round-trips verbatim; read it with frontmatterOf() from @godxjp/markdown/codec.",
|
|
86
86
|
"DO store the Markdown it emits — it is already canonical; compute `normalize()` server-side from the same codec to verify.",
|
|
@@ -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). 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.",
|
|
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). Every folded cell reads from the START: a column's `align`/`numeric` end or centre alignment belongs to the table, not the card, so a count sits under its label like every other field (gh#1310). 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
|
},
|
|
@@ -98,7 +98,8 @@
|
|
|
98
98
|
"DO give every section a URL-safe, page-unique `id` — it is simultaneously the <section id>, the contents href, the deep-link target and the aria-current key.",
|
|
99
99
|
"DO NOT hand-roll this from CenteredShell + SplitPane + `.legal-*` CSS. The geometry is the easy half; the scroll spy, hash offset, focus handoff and aria-current wiring are what the shell exists to own, and no token can express them.",
|
|
100
100
|
"DO NOT add a consumer `className` for the measure, the rail width, the section rhythm or the dividers — every one of those is a --legal-document-* token. Dividers default to `none` (rule #44): opt in with `--legal-document-toc-border: 1px solid hsl(var(--border))`.",
|
|
101
|
-
"DO NOT expect a viewport media query: the shell owns its query container, so the one-column ⇄ two-column split (56rem) is decided by the SHELL's own width. Below it the contents are a STATIC compact block (never pinned on a phone); above it they are a sticky rail."
|
|
101
|
+
"DO NOT expect a viewport media query: the shell owns its query container, so the one-column ⇄ two-column split (56rem) is decided by the SHELL's own width. Below it the contents are a STATIC compact block (never pinned on a phone) whose entries HUG their labels, so the active fill marks one entry rather than a full-column bar (gh#1310); above it they are a sticky rail.",
|
|
102
|
+
"DO set `lang` (AppProvider does, from the locale): under `:lang(ja)` the summary and section bodies break between Japanese PHRASES (`word-break: auto-phrase`, gh#1310), as `Text break=\"phrase\"` does; Vietnamese and English keep `word-break: normal`."
|
|
102
103
|
],
|
|
103
104
|
"useCases": [
|
|
104
105
|
"Hosted legal terms/privacy screen (SCR-005): <CenteredShell width=\"lg\" topbar={<Topbar …/>}><LegalDocumentShell title=\"利用規約\" version=\"2.4\" effectiveDate=\"2026-04-01\" contentsLabel=\"目次\" sections={sections} activeSection={active} onActiveSectionChange={setActive} documentNavigation={yourDocumentSwitcher} footerAction={<Button>同意する</Button>} /></CenteredShell>",
|
|
@@ -83,6 +83,7 @@
|
|
|
83
83
|
"storyPath": "data-display/markdown.tsx",
|
|
84
84
|
"tagline": "The one Markdown renderer for GoDX apps (sibling package `@godxjp/markdown`, versioned with the kit): GFM + GitHub heading anchors, one sanitiser schema (no raw HTML; http/https/mailto/relative URLs only), and ```mermaid drawn only after its SVG passes a fail-closed gate (gh#1108). Wrap it in `Prose`.",
|
|
85
85
|
"usage": [
|
|
86
|
+
"DO let the document language do Japanese line breaking: under `:lang(ja)` (AppProvider sets `<html lang>`) every prose paragraph and list item breaks between PHRASES — `word-break: auto-phrase` + `line-break: strict`, the `Text break=\"phrase\"` behaviour (gh#1310) — so 「新しく参加」 is not cut 「新し|く参加」. Latin and Vietnamese wrap unchanged; a phrase longer than the line still breaks inside itself. A browser without `auto-phrase` keeps its own CJK breaking.",
|
|
86
87
|
"Table of contents: outline(markdown) from @godxjp/markdown/codec returns { depth, text, id }[] with exactly the ids <Markdown> writes — feed it to the kit Anchor. YAML front matter is kept verbatim and never rendered; frontmatterOf(markdown) returns it (gh#1163).",
|
|
87
88
|
"DO `<Prose><Markdown>{body}</Markdown></Prose>` for every rendered body (wiki page, issue, mail).",
|
|
88
89
|
"DO record `MARKDOWN_FORMAT` and `RENDERER_VERSION` on stored versions.",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"storyPath": "data-display/prose.tsx",
|
|
49
49
|
"tagline": "Typography for rendered content (Markdown, CMS bodies, issue descriptions): styles the semantic HTML inside it from the tokens, with no opinion about where the HTML comes from. To RENDER Markdown, use the sibling package `@godxjp/markdown` inside it — `<Prose><Markdown>{body}</Markdown></Prose>` — the one GFM renderer + sanitiser + Mermaid gate shared by every GoDX app; do not assemble react-markdown + rehype-sanitize per app (gh#1108). Tables: `@godxjp/markdown` wraps each in `.ui-prose-table-scroll`, which Prose scrolls horizontally (focusable only while it overflows), and table cells keep their words whole — a short code like `F02` never breaks (gh#1131).",
|
|
50
50
|
"usage": [
|
|
51
|
+
"DO let the document language do Japanese line breaking: under `:lang(ja)` (AppProvider sets `<html lang>`) every prose paragraph and list item breaks between PHRASES — `word-break: auto-phrase` + `line-break: strict`, the `Text break=\"phrase\"` behaviour (gh#1310) — so 「新しく参加」 is not cut 「新し|く参加」. Latin and Vietnamese wrap unchanged; a phrase longer than the line still breaks inside itself. A browser without `auto-phrase` keeps its own CJK breaking.",
|
|
51
52
|
"DO import from `@godxjp/ui/data-display`: `import { Prose } from \"@godxjp/ui/data-display\";`",
|
|
52
53
|
"DO wrap the OUTPUT of your Markdown pipeline (react-markdown + remark-gfm + rehype-sanitize), a sanitised CMS string via `dangerouslySetInnerHTML`, or plain JSX. Prose styles descendants: h1..h4, p, ul/ol/li, blockquote, code, pre, table/th/td, a, img, hr.",
|
|
53
54
|
"DO keep soft line breaks the pipeline's job (remark-breaks or the renderer's `breaks` option). Prose does not turn single newlines into `<br>`; it is typography, not parsing.",
|
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
"DO: reach for `fill` when the pane is an app-shell surface rather than a block in a scrolling page — a chat transcript whose composer stays pinned to the bottom, a full-height table beside a detail rail. It is the supported way to say \"be as tall as what is left\"; a consumer that instead styles the pane's wrapper divs from outside (`[&>*]`, `[&>*>*]`) is targeting this component's internal DOM by position and will break the day another wrapper appears.",
|
|
57
57
|
"DO: set `stackOrder=\"aside-first\"` when the aside is what a phone user needs first — an issue's properties / agent card above its comment thread. DON'T render the aside twice (once above, once beside) or reorder with a CSS `order` override: the prop already puts it first in the DOM, so focus order follows the stacked screen, and restores the side-by-side placement once the pane splits.",
|
|
58
58
|
"DO: choose `asideWidth=\"sm\"` for compact detail panels (filters, quick stats, key-value summaries) and the default `asideWidth=\"md\"` for richer panels (forms, timelines, long metadata lists).",
|
|
59
|
+
"DO: tune the main ↔ aside distance with the `--split-pane-gap` token (default `--space-stack-md`, 16px, split and stacked) — set it once in theme.css to the column step your design grid reads between panes, e.g. `--split-pane-gap: var(--space-inline-xl)` so an editor's aside sits further from the text than its paragraphs sit from each other (gh#1310). DON'T override `gap` on the pane's wrapper from outside.",
|
|
59
60
|
"DO: wrap SplitPane inside `PageContainer` or `PageContainer.Inset` — SplitPane provides no page padding of its own. It is a grid primitive, not a page scaffold.",
|
|
60
61
|
"DO: close a collapsible rail with `aside={null}` — a Slack-style thread, a Linear-style detail panel — rather than swapping `<SplitPane aside={<Thread />}>{page}</SplitPane>` for a bare `{page}`. Both look the same on screen; only the prop keeps `children` mounted. The conditional swap changes the DEPTH of `{page}` in the React tree, so React remounts it: measured in a consumer as a message list jumping from scrollTop 400 to the bottom the instant a thread opened, losing the reader's place and any component state below it.",
|
|
61
62
|
"DON'T: leave `SplitPane` mounted with an empty `aside={<div />}` to avoid that remount — an empty aside still reserves its rail, leaving a blank 20-30rem column. `aside={null}` removes the element AND the column (the pane sets `data-aside=\"closed\"` on itself, so the collapse is one CSS rule, not a call-site width override).",
|
|
@@ -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). 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.",
|
|
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). Every folded cell reads from the START: a column's `align`/`numeric` end or centre alignment belongs to the table, not the card, so a count sits under its label like every other field (gh#1310). 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
|
},
|
package/agent/components.json
CHANGED
|
@@ -2220,6 +2220,7 @@
|
|
|
2220
2220
|
"DO: reach for `fill` when the pane is an app-shell surface rather than a block in a scrolling page — a chat transcript whose composer stays pinned to the bottom, a full-height table beside a detail rail. It is the supported way to say \"be as tall as what is left\"; a consumer that instead styles the pane's wrapper divs from outside (`[&>*]`, `[&>*>*]`) is targeting this component's internal DOM by position and will break the day another wrapper appears.",
|
|
2221
2221
|
"DO: set `stackOrder=\"aside-first\"` when the aside is what a phone user needs first — an issue's properties / agent card above its comment thread. DON'T render the aside twice (once above, once beside) or reorder with a CSS `order` override: the prop already puts it first in the DOM, so focus order follows the stacked screen, and restores the side-by-side placement once the pane splits.",
|
|
2222
2222
|
"DO: choose `asideWidth=\"sm\"` for compact detail panels (filters, quick stats, key-value summaries) and the default `asideWidth=\"md\"` for richer panels (forms, timelines, long metadata lists).",
|
|
2223
|
+
"DO: tune the main ↔ aside distance with the `--split-pane-gap` token (default `--space-stack-md`, 16px, split and stacked) — set it once in theme.css to the column step your design grid reads between panes, e.g. `--split-pane-gap: var(--space-inline-xl)` so an editor's aside sits further from the text than its paragraphs sit from each other (gh#1310). DON'T override `gap` on the pane's wrapper from outside.",
|
|
2223
2224
|
"DO: wrap SplitPane inside `PageContainer` or `PageContainer.Inset` — SplitPane provides no page padding of its own. It is a grid primitive, not a page scaffold.",
|
|
2224
2225
|
"DO: close a collapsible rail with `aside={null}` — a Slack-style thread, a Linear-style detail panel — rather than swapping `<SplitPane aside={<Thread />}>{page}</SplitPane>` for a bare `{page}`. Both look the same on screen; only the prop keeps `children` mounted. The conditional swap changes the DEPTH of `{page}` in the React tree, so React remounts it: measured in a consumer as a message list jumping from scrollTop 400 to the bottom the instant a thread opened, losing the reader's place and any component state below it.",
|
|
2225
2226
|
"DON'T: leave `SplitPane` mounted with an empty `aside={<div />}` to avoid that remount — an empty aside still reserves its rail, leaving a blank 20-30rem column. `aside={null}` removes the element AND the column (the pane sets `data-aside=\"closed\"` on itself, so the collapse is one CSS rule, not a call-site width override).",
|
|
@@ -2463,7 +2464,8 @@
|
|
|
2463
2464
|
"DO give every section a URL-safe, page-unique `id` — it is simultaneously the <section id>, the contents href, the deep-link target and the aria-current key.",
|
|
2464
2465
|
"DO NOT hand-roll this from CenteredShell + SplitPane + `.legal-*` CSS. The geometry is the easy half; the scroll spy, hash offset, focus handoff and aria-current wiring are what the shell exists to own, and no token can express them.",
|
|
2465
2466
|
"DO NOT add a consumer `className` for the measure, the rail width, the section rhythm or the dividers — every one of those is a --legal-document-* token. Dividers default to `none` (rule #44): opt in with `--legal-document-toc-border: 1px solid hsl(var(--border))`.",
|
|
2466
|
-
"DO NOT expect a viewport media query: the shell owns its query container, so the one-column ⇄ two-column split (56rem) is decided by the SHELL's own width. Below it the contents are a STATIC compact block (never pinned on a phone); above it they are a sticky rail."
|
|
2467
|
+
"DO NOT expect a viewport media query: the shell owns its query container, so the one-column ⇄ two-column split (56rem) is decided by the SHELL's own width. Below it the contents are a STATIC compact block (never pinned on a phone) whose entries HUG their labels, so the active fill marks one entry rather than a full-column bar (gh#1310); above it they are a sticky rail.",
|
|
2468
|
+
"DO set `lang` (AppProvider does, from the locale): under `:lang(ja)` the summary and section bodies break between Japanese PHRASES (`word-break: auto-phrase`, gh#1310), as `Text break=\"phrase\"` does; Vietnamese and English keep `word-break: normal`."
|
|
2467
2469
|
],
|
|
2468
2470
|
"useCases": [
|
|
2469
2471
|
"Hosted legal terms/privacy screen (SCR-005): <CenteredShell width=\"lg\" topbar={<Topbar …/>}><LegalDocumentShell title=\"利用規約\" version=\"2.4\" effectiveDate=\"2026-04-01\" contentsLabel=\"目次\" sections={sections} activeSection={active} onActiveSectionChange={setActive} documentNavigation={yourDocumentSwitcher} footerAction={<Button>同意する</Button>} /></CenteredShell>",
|
|
@@ -3459,7 +3461,7 @@
|
|
|
3459
3461
|
},
|
|
3460
3462
|
{
|
|
3461
3463
|
"defaultValue": "'default'",
|
|
3462
|
-
"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.",
|
|
3464
|
+
"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). Every folded cell reads from the START: a column's `align`/`numeric` end or centre alignment belongs to the table, not the card, so a count sits under its label like every other field (gh#1310). 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.",
|
|
3463
3465
|
"name": "preset",
|
|
3464
3466
|
"type": "'default' | 'action-collection' | 'stacked-record-collection'"
|
|
3465
3467
|
},
|
|
@@ -5004,6 +5006,7 @@
|
|
|
5004
5006
|
"storyPath": "data-display/markdown.tsx",
|
|
5005
5007
|
"tagline": "The one Markdown renderer for GoDX apps (sibling package `@godxjp/markdown`, versioned with the kit): GFM + GitHub heading anchors, one sanitiser schema (no raw HTML; http/https/mailto/relative URLs only), and ```mermaid drawn only after its SVG passes a fail-closed gate (gh#1108). Wrap it in `Prose`.",
|
|
5006
5008
|
"usage": [
|
|
5009
|
+
"DO let the document language do Japanese line breaking: under `:lang(ja)` (AppProvider sets `<html lang>`) every prose paragraph and list item breaks between PHRASES — `word-break: auto-phrase` + `line-break: strict`, the `Text break=\"phrase\"` behaviour (gh#1310) — so 「新しく参加」 is not cut 「新し|く参加」. Latin and Vietnamese wrap unchanged; a phrase longer than the line still breaks inside itself. A browser without `auto-phrase` keeps its own CJK breaking.",
|
|
5007
5010
|
"Table of contents: outline(markdown) from @godxjp/markdown/codec returns { depth, text, id }[] with exactly the ids <Markdown> writes — feed it to the kit Anchor. YAML front matter is kept verbatim and never rendered; frontmatterOf(markdown) returns it (gh#1163).",
|
|
5008
5011
|
"DO `<Prose><Markdown>{body}</Markdown></Prose>` for every rendered body (wiki page, issue, mail).",
|
|
5009
5012
|
"DO record `MARKDOWN_FORMAT` and `RENDERER_VERSION` on stored versions.",
|
|
@@ -5158,7 +5161,7 @@
|
|
|
5158
5161
|
"storyPath": "data-entry/block-editor.tsx",
|
|
5159
5162
|
"tagline": "Notion / note.com style block editor (sibling package `@godxjp/block-editor`, versioned with the kit) that reads and writes MARKDOWN through `@godxjp/markdown/codec`: what onValueChange returns is byte-for-byte normalize(body). `/` block menu at the caret, ⋮⋮ handle (drag, turn into, duplicate, move, delete), floating format toolbar, `[[` wikilink suggestions, paste / drop uploads through the host, IME-safe, ja / en / vi (gh#1156).",
|
|
5160
5163
|
"usage": [
|
|
5161
|
-
"Below 40rem the handle gutter collapses to `--block-editor-compact-gutter-inline-size` (the frame inset, 12px) and the + / ⋮⋮ handle rises above the caret's block at its inline end (ADR C05): first line 56px → 12px from the inner edge at 390px. Touch: tap a block to show its handle; ⋮⋮ opens Move up / Move down / Duplicate / Delete. Keyboard: Mod+/ opens the same menu, Alt+Shift+↑↓ moves the block.",
|
|
5164
|
+
"From 40rem up the + / ⋮⋮ handles sit in a start gutter INSIDE the frame, `--block-editor-gutter-inline-size` (default 2 × 24px targets + 8px = 56px); it tunes that width but cannot put the text on a sibling Input's keyline, because the handles live in it (DESIGN.md Known Gaps, gh#1310). Below 40rem the handle gutter collapses to `--block-editor-compact-gutter-inline-size` (the frame inset, 12px) and the + / ⋮⋮ handle rises above the caret's block at its inline end (ADR C05): first line 56px → 12px from the inner edge at 390px. Touch: tap a block to show its handle; ⋮⋮ opens Move up / Move down / Duplicate / Delete. Keyboard: Mod+/ opens the same menu, Alt+Shift+↑↓ moves the block.",
|
|
5162
5165
|
"Clicking a link (or Mod+K) opens a settings drawer: text, URL, title, open / remove. Clicking an image opens one for src, alt, title, replace (pickMedia / upload) and remove. Markdown stores no link target, so there is no target field. A link in the editor never navigates mid-edit.",
|
|
5163
5166
|
"YAML front matter shows as a Properties block at the top and round-trips verbatim; read it with frontmatterOf() from @godxjp/markdown/codec.",
|
|
5164
5167
|
"DO store the Markdown it emits — it is already canonical; compute `normalize()` server-side from the same codec to verify.",
|
|
@@ -5218,6 +5221,7 @@
|
|
|
5218
5221
|
"storyPath": "data-display/prose.tsx",
|
|
5219
5222
|
"tagline": "Typography for rendered content (Markdown, CMS bodies, issue descriptions): styles the semantic HTML inside it from the tokens, with no opinion about where the HTML comes from. To RENDER Markdown, use the sibling package `@godxjp/markdown` inside it — `<Prose><Markdown>{body}</Markdown></Prose>` — the one GFM renderer + sanitiser + Mermaid gate shared by every GoDX app; do not assemble react-markdown + rehype-sanitize per app (gh#1108). Tables: `@godxjp/markdown` wraps each in `.ui-prose-table-scroll`, which Prose scrolls horizontally (focusable only while it overflows), and table cells keep their words whole — a short code like `F02` never breaks (gh#1131).",
|
|
5220
5223
|
"usage": [
|
|
5224
|
+
"DO let the document language do Japanese line breaking: under `:lang(ja)` (AppProvider sets `<html lang>`) every prose paragraph and list item breaks between PHRASES — `word-break: auto-phrase` + `line-break: strict`, the `Text break=\"phrase\"` behaviour (gh#1310) — so 「新しく参加」 is not cut 「新し|く参加」. Latin and Vietnamese wrap unchanged; a phrase longer than the line still breaks inside itself. A browser without `auto-phrase` keeps its own CJK breaking.",
|
|
5221
5225
|
"DO import from `@godxjp/ui/data-display`: `import { Prose } from \"@godxjp/ui/data-display\";`",
|
|
5222
5226
|
"DO wrap the OUTPUT of your Markdown pipeline (react-markdown + remark-gfm + rehype-sanitize), a sanitised CMS string via `dangerouslySetInnerHTML`, or plain JSX. Prose styles descendants: h1..h4, p, ul/ol/li, blockquote, code, pre, table/th/td, a, img, hr.",
|
|
5223
5227
|
"DO keep soft line breaks the pipeline's job (remark-breaks or the renderer's `breaks` option). Prose does not turn single newlines into `<br>`; it is typography, not parsing.",
|
|
@@ -5454,7 +5458,7 @@
|
|
|
5454
5458
|
},
|
|
5455
5459
|
{
|
|
5456
5460
|
"defaultValue": "\"default\"",
|
|
5457
|
-
"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.",
|
|
5461
|
+
"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). Every folded cell reads from the START: a column's `align`/`numeric` end or centre alignment belongs to the table, not the card, so a count sits under its label like every other field (gh#1310). The label is aria-hidden and the real <th> stays in the DOM, so the accessible name and table navigation are unchanged.",
|
|
5458
5462
|
"name": "preset",
|
|
5459
5463
|
"type": "\"default\" | \"action-collection\" | \"stacked-record-collection\""
|
|
5460
5464
|
},
|
package/agent/index.json
CHANGED
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
"components": 162,
|
|
5
5
|
"patterns": 24,
|
|
6
6
|
"rules": 43,
|
|
7
|
-
"tokens":
|
|
7
|
+
"tokens": 2204,
|
|
8
8
|
"vocabulary": 14
|
|
9
9
|
},
|
|
10
10
|
"design": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/DESIGN.md",
|
|
11
11
|
"files": [
|
|
12
12
|
{
|
|
13
13
|
"file": "DESIGN.md",
|
|
14
|
-
"note": "
|
|
14
|
+
"note": "17 KB — the visual spec: tokens, colour scarcity, admin screen anatomy (list, detail, form, settings, dashboard), do/don't. Read before composing a screen.",
|
|
15
15
|
"url": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/DESIGN.md"
|
|
16
16
|
},
|
|
17
17
|
{
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"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.",
|
|
55
55
|
"read": {
|
|
56
56
|
"live": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/index.json",
|
|
57
|
-
"pinned": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/v32.
|
|
57
|
+
"pinned": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/v32.11.1/agent/index.json"
|
|
58
58
|
},
|
|
59
59
|
"source": "mcp/src/data — the same data @godxjp/ui-mcp serves — plus the foundation and semantic token tiers, read from src/tokens/*.css",
|
|
60
60
|
"start": "https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/START-HERE.md",
|
|
@@ -63,10 +63,10 @@
|
|
|
63
63
|
"counts": {
|
|
64
64
|
"component": 1880,
|
|
65
65
|
"foundation": 211,
|
|
66
|
-
"semantic":
|
|
66
|
+
"semantic": 113
|
|
67
67
|
},
|
|
68
68
|
"foundation": "the seeds a consumer is invited to set — --primary, --background, --radius",
|
|
69
69
|
"semantic": "named roles that follow the seeds — --ring, --text-link, --overlay-background"
|
|
70
70
|
},
|
|
71
|
-
"version": "32.
|
|
71
|
+
"version": "32.11.1"
|
|
72
72
|
}
|
package/agent/llms.txt
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
# @godxjp/ui
|
|
2
2
|
|
|
3
|
-
> A Japanese-enterprise React design system: 162 components,
|
|
4
|
-
> 43 cardinal rules. This file is the entry point for AI agents. Catalog version 32.
|
|
3
|
+
> A Japanese-enterprise React design system: 162 components, 2204 design tokens,
|
|
4
|
+
> 43 cardinal rules. This file is the entry point for AI agents. Catalog version 32.11.1.
|
|
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@32.
|
|
7
|
+
(`npx @godxjp/ui-mcp@32.11.1`). It is searchable and version-locked. These files exist for agents
|
|
8
8
|
that can only fetch URLs.
|
|
9
9
|
|
|
10
10
|
## Start
|
|
11
11
|
|
|
12
12
|
- [START-HERE.md](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/START-HERE.md): the whole contract — the four rules, the token override model, a page that passes review. Read this first; it is self-contained.
|
|
13
13
|
- [index.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/index.json): version, counts, and the URL of every file.
|
|
14
|
-
- [DESIGN.md](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/DESIGN.md):
|
|
14
|
+
- [DESIGN.md](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/DESIGN.md): 17 KB — the visual spec: tokens, colour scarcity, admin screen anatomy (list, detail, form, settings, dashboard), do/don't. Read it before composing a screen.
|
|
15
15
|
|
|
16
16
|
## Catalog
|
|
17
17
|
|
|
@@ -19,7 +19,7 @@ that can only fetch URLs.
|
|
|
19
19
|
- [components-index.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components-index.json): 48 KB — all 162 components as name, group, tagline, plus `absorbed`: the names that do NOT exist and map to it (`Combobox` → `Select`).
|
|
20
20
|
- [components/<Name>.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/components/Select.json): one file per component (1 KB–37 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.
|
|
21
21
|
- [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.
|
|
22
|
-
- [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),
|
|
22
|
+
- [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), 113 `semantic` roles, 1880 `component` knobs.
|
|
23
23
|
- [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.
|
|
24
24
|
- [rules.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/rules.json): 43 cardinal rules.
|
|
25
25
|
- [anti-ai-tells.json](https://raw.githubusercontent.com/godx-jp/godxjp-ui/main/agent/anti-ai-tells.json): 35 shapes that make generated UI look generated, each with its fix.
|
|
@@ -27,7 +27,7 @@ that can only fetch URLs.
|
|
|
27
27
|
## Pinning
|
|
28
28
|
|
|
29
29
|
Every URL above tracks `main`. To pin to the release a project actually installed, swap `main` for
|
|
30
|
-
the tag: `.../godx-jp/godxjp-ui/v32.
|
|
30
|
+
the tag: `.../godx-jp/godxjp-ui/v32.11.1/agent/...`. A catalog that does not match the installed
|
|
31
31
|
package describes props that are absent, or hides props that are present, and says nothing either way.
|
|
32
32
|
|
|
33
33
|
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
|
@@ -1547,6 +1547,12 @@
|
|
|
1547
1547
|
"tier": "semantic",
|
|
1548
1548
|
"value": "40rem"
|
|
1549
1549
|
},
|
|
1550
|
+
{
|
|
1551
|
+
"description": "SplitPane main ↔ aside gap (gh#1310, rule #45), split and stacked. Default = --space-stack-md, resolved at the call site so a density scope that re-derives the step still reaches it; a service sets the column step it reads between panes, e.g. var(--space-inline-xl).",
|
|
1552
|
+
"name": "--split-pane-gap",
|
|
1553
|
+
"tier": "semantic",
|
|
1554
|
+
"value": "initial"
|
|
1555
|
+
},
|
|
1550
1556
|
{
|
|
1551
1557
|
"description": "Bounded master viewport (gh#231). OPT-IN, chosen by the semantic `masterViewport` prop — `auto` (the default) applies NO bound, so every existing composition is unchanged. A real collection can be thousands of pixels tall; when the layout stacks, that pushes the detail far below the fold. The presets cap the collection's BLOCK size and scroll it inside the region instead. Sized as a whole number of nominal collection rows (2.5rem ≈ a compact list row) so a service theme retunes them in the same semantic unit the design grid uses. 320px — about 8 nominal rows",
|
|
1552
1558
|
"name": "--master-detail-master-viewport-compact",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$comment": "AUTO-GENERATED by scripts/gen-measurement-contract.mjs — do not edit. Read this instead of guessing: docs/MEASUREMENT-CONTRACT.md.",
|
|
3
|
-
"version": "32.
|
|
3
|
+
"version": "32.11.1",
|
|
4
4
|
"targetSize": {
|
|
5
5
|
"standard": "WCAG 2.2 SC 2.5.8 Target Size (Minimum), level AA — 24×24 CSS px",
|
|
6
6
|
"min": 24,
|
|
@@ -1306,6 +1306,11 @@
|
|
|
1306
1306
|
font-size: var(--prose-font-size-sm);
|
|
1307
1307
|
}
|
|
1308
1308
|
|
|
1309
|
+
.ui-prose :is(p, li):lang(ja) {
|
|
1310
|
+
word-break: auto-phrase;
|
|
1311
|
+
line-break: strict;
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1309
1314
|
.ui-prose[data-measure="narrow"] {
|
|
1310
1315
|
max-inline-size: var(--page-measure-narrow);
|
|
1311
1316
|
}
|
package/dist/styles/layers.json
CHANGED
package/dist/styles/layout.css
CHANGED
|
@@ -600,7 +600,7 @@
|
|
|
600
600
|
|
|
601
601
|
.ui-split-pane {
|
|
602
602
|
display: grid;
|
|
603
|
-
gap: var(--space-stack-md);
|
|
603
|
+
gap: var(--split-pane-gap, var(--space-stack-md));
|
|
604
604
|
grid-template-columns: minmax(0, 1fr);
|
|
605
605
|
}
|
|
606
606
|
|
|
@@ -1264,6 +1264,21 @@
|
|
|
1264
1264
|
font-weight: var(--font-weight-medium);
|
|
1265
1265
|
}
|
|
1266
1266
|
|
|
1267
|
+
:is(
|
|
1268
|
+
h1,
|
|
1269
|
+
h2,
|
|
1270
|
+
h3,
|
|
1271
|
+
h4,
|
|
1272
|
+
h5,
|
|
1273
|
+
h6,
|
|
1274
|
+
.ui-page-title,
|
|
1275
|
+
.ui-empty-state-title,
|
|
1276
|
+
.ui-empty-state-description
|
|
1277
|
+
):lang(ja) {
|
|
1278
|
+
word-break: auto-phrase;
|
|
1279
|
+
line-break: strict;
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1267
1282
|
.ui-empty-state-description {
|
|
1268
1283
|
font-size: var(--font-size-base);
|
|
1269
1284
|
color: hsl(var(--muted-foreground));
|
|
@@ -1658,6 +1673,11 @@
|
|
|
1658
1673
|
line-break: strict;
|
|
1659
1674
|
}
|
|
1660
1675
|
|
|
1676
|
+
.ui-legal-document-summary:lang(ja),
|
|
1677
|
+
.ui-legal-document-section-body:lang(ja) {
|
|
1678
|
+
word-break: auto-phrase;
|
|
1679
|
+
}
|
|
1680
|
+
|
|
1661
1681
|
.ui-legal-document-summary {
|
|
1662
1682
|
color: hsl(var(--legal-document-summary-foreground, var(--muted-foreground)));
|
|
1663
1683
|
}
|
|
@@ -1686,6 +1706,7 @@
|
|
|
1686
1706
|
.ui-legal-document-toc-list {
|
|
1687
1707
|
display: flex;
|
|
1688
1708
|
flex-direction: column;
|
|
1709
|
+
align-items: start;
|
|
1689
1710
|
gap: var(--legal-document-toc-gap);
|
|
1690
1711
|
margin: 0;
|
|
1691
1712
|
padding: 0;
|
|
@@ -1769,6 +1790,10 @@
|
|
|
1769
1790
|
overflow-y: auto;
|
|
1770
1791
|
}
|
|
1771
1792
|
|
|
1793
|
+
.ui-legal-document-toc-list {
|
|
1794
|
+
align-items: stretch;
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1772
1797
|
.ui-legal-document-content {
|
|
1773
1798
|
grid-column: 2;
|
|
1774
1799
|
grid-row: 2;
|
|
@@ -1051,6 +1051,8 @@
|
|
|
1051
1051
|
padding-inline: var(--table-stacked-collection-cell-padding-x);
|
|
1052
1052
|
white-space: normal;
|
|
1053
1053
|
overflow-wrap: anywhere;
|
|
1054
|
+
|
|
1055
|
+
text-align: start;
|
|
1054
1056
|
}
|
|
1055
1057
|
|
|
1056
1058
|
[data-collapse-below="sm"] [data-slot="table-cell"]:empty,
|
|
@@ -1102,6 +1104,7 @@
|
|
|
1102
1104
|
padding-inline: var(--table-stacked-collection-cell-padding-x);
|
|
1103
1105
|
white-space: normal;
|
|
1104
1106
|
overflow-wrap: anywhere;
|
|
1107
|
+
text-align: start;
|
|
1105
1108
|
}
|
|
1106
1109
|
|
|
1107
1110
|
[data-collapse-below="md"] [data-slot="table-cell"]:empty,
|
|
@@ -1153,6 +1156,7 @@
|
|
|
1153
1156
|
padding-inline: var(--table-stacked-collection-cell-padding-x);
|
|
1154
1157
|
white-space: normal;
|
|
1155
1158
|
overflow-wrap: anywhere;
|
|
1159
|
+
text-align: start;
|
|
1156
1160
|
}
|
|
1157
1161
|
|
|
1158
1162
|
[data-collapse-below="lg"] [data-slot="table-cell"]:empty,
|
|
@@ -1204,6 +1208,7 @@
|
|
|
1204
1208
|
padding-inline: var(--table-stacked-collection-cell-padding-x);
|
|
1205
1209
|
white-space: normal;
|
|
1206
1210
|
overflow-wrap: anywhere;
|
|
1211
|
+
text-align: start;
|
|
1207
1212
|
}
|
|
1208
1213
|
|
|
1209
1214
|
[data-collapse-below="xl"] [data-slot="table-cell"]:empty,
|