@godxjp/ui 28.10.0 → 28.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/agent/START-HERE.md +2 -2
  2. package/agent/components/AppLauncher.json +10 -0
  3. package/agent/components/Attachments.json +27 -1
  4. package/agent/components/BranchScopePicker.json +10 -0
  5. package/agent/components/Cascader.json +5 -0
  6. package/agent/components/Checkbox.json +6 -0
  7. package/agent/components/CredentialReveal.json +21 -0
  8. package/agent/components/InputOTP.json +35 -0
  9. package/agent/components/PermissionMatrix.json +5 -0
  10. package/agent/components/SearchInput.json +5 -0
  11. package/agent/components/ServiceLauncherCard.json +10 -3
  12. package/agent/components/ServiceRolePanel.json +5 -0
  13. package/agent/components/Switch.json +6 -0
  14. package/agent/components/Tabs.json +10 -0
  15. package/agent/components/TimeRangePicker.json +5 -0
  16. package/agent/components/Transfer.json +5 -0
  17. package/agent/components/Upload.json +5 -0
  18. package/agent/components-index.json +1 -1
  19. package/agent/components.json +170 -4
  20. package/agent/index.json +3 -3
  21. package/agent/llms.txt +4 -4
  22. package/agent/tokens.json +30 -25
  23. package/dist/components/data-display/service-launcher-card.d.ts +19 -0
  24. package/dist/components/data-display/service-launcher-card.js +14 -1
  25. package/dist/components/data-entry/attachments.js +77 -33
  26. package/dist/components/ui/avatar.d.ts +1 -18
  27. package/dist/components/ui/avatar.js +1 -36
  28. package/dist/contracts/measurement.json +1 -1
  29. package/dist/i18n/messages/en.json +0 -530
  30. package/dist/i18n/messages/ja.json +0 -524
  31. package/dist/i18n/messages/vi.json +0 -524
  32. package/dist/lib/image-loading-status.d.ts +25 -0
  33. package/dist/lib/image-loading-status.js +41 -0
  34. package/dist/props/registry.d.ts +5 -1
  35. package/dist/props/registry.js +12 -1
  36. package/dist/styles/card-layout.css +6 -0
  37. package/dist/styles/control.css +2 -2
  38. package/dist/styles/data-entry-layout.css +245 -2
  39. package/dist/tokens/components/attachments.css +18 -9
  40. package/dist/tokens/components/segmented.css +2 -2
  41. package/docs/DESIGN-AUTHORITY.md +51 -0
  42. package/docs/assets/service-mark-rose.svg +6 -0
  43. package/docs/assets/service-mark-teal.svg +5 -0
  44. package/docs/data-display/service-launcher-card.tsx +232 -92
  45. package/docs/i18n/messages/en.json +699 -0
  46. package/docs/i18n/messages/ja.json +693 -0
  47. package/docs/i18n/messages/vi.json +693 -0
  48. package/docs/showcase/marketing-page.tsx +3 -2
  49. package/docs/showcase/table-pagination.tsx +18 -7
  50. package/docs/showcase/theme-customization.tsx +2 -1
  51. package/package.json +4 -3
@@ -1160,7 +1160,7 @@
1160
1160
  align-items: stretch;
1161
1161
  padding: var(--segmented-track-padding);
1162
1162
  border-radius: var(--segmented-track-radius);
1163
- background: hsl(var(--segmented-track-background));
1163
+ background: hsl(var(--segmented-track-background, var(--muted)));
1164
1164
  color: hsl(var(--segmented-item-color));
1165
1165
  font-size: var(--font-size-base);
1166
1166
  }
@@ -1196,7 +1196,7 @@
1196
1196
  }
1197
1197
 
1198
1198
  .ui-segmented-item[data-state="checked"] {
1199
- background: hsl(var(--segmented-item-selected-background));
1199
+ background: hsl(var(--segmented-item-selected-background, var(--background)));
1200
1200
 
1201
1201
  box-shadow:
1202
1202
  var(--segmented-item-selected-shadow),
@@ -1,7 +1,250 @@
1
1
  @layer components {
2
2
 
3
- .ui-attachments-input {
4
- min-block-size: var(--touch-target-min);
3
+ .ui-attachments {
4
+ position: relative;
5
+ inline-size: 100%;
6
+ }
7
+
8
+ .ui-attachments-list {
9
+ display: flex;
10
+ align-items: stretch;
11
+ gap: var(--attachments-gap);
12
+ margin: 0;
13
+ padding: 0;
14
+ list-style: none;
15
+ }
16
+
17
+ .ui-attachments-list > li {
18
+ position: relative;
19
+ display: flex;
20
+ flex: none;
21
+ min-inline-size: 0;
22
+ }
23
+
24
+ .ui-attachments-list[data-overflow="wrap"] {
25
+ flex-wrap: wrap;
26
+ }
27
+
28
+ .ui-attachments-list[data-overflow="scrollX"] {
29
+ flex-wrap: nowrap;
30
+ overflow-x: auto;
31
+ overflow-y: hidden;
32
+ }
33
+
34
+ .ui-attachments-list[data-overflow="scrollY"] {
35
+ flex-wrap: wrap;
36
+ overflow-x: hidden;
37
+ overflow-y: auto;
38
+ max-block-size: var(--attachments-card-block-size);
39
+ }
40
+
41
+ .ui-attachments-card {
42
+ position: relative;
43
+ display: flex;
44
+ align-items: center;
45
+ gap: var(--attachments-card-gap);
46
+ inline-size: var(--attachments-card-size);
47
+
48
+ max-inline-size: 100%;
49
+ block-size: var(--attachments-card-block-size);
50
+ padding-block: var(--space-3);
51
+ padding-inline: var(--space-4);
52
+ border: var(--stroke-hairline) solid transparent;
53
+ border-radius: var(--attachments-card-radius);
54
+ background-color: hsl(var(--muted));
55
+ overflow: hidden;
56
+ }
57
+
58
+ .ui-attachments-card-preview,
59
+ .ui-attachments-card-placeholder {
60
+ flex: none;
61
+ display: flex;
62
+ align-items: center;
63
+ justify-content: center;
64
+ inline-size: var(--icon-size-2xl);
65
+ block-size: var(--icon-size-2xl);
66
+ }
67
+
68
+ .ui-attachments-card-preview {
69
+ border-radius: var(--radius-md);
70
+ object-fit: cover;
71
+ }
72
+
73
+ .ui-attachments-card-placeholder {
74
+ color: hsl(var(--muted-foreground));
75
+ }
76
+
77
+ .ui-attachments-card-placeholder > svg {
78
+ inline-size: var(--icon-size-2xl);
79
+ block-size: var(--icon-size-2xl);
80
+ }
81
+
82
+ .ui-attachments-card-content {
83
+ display: flex;
84
+ flex: 1 1 auto;
85
+ min-inline-size: 0;
86
+ flex-direction: column;
87
+ justify-content: center;
88
+ }
89
+
90
+ .ui-attachments-card-name {
91
+ display: flex;
92
+ max-inline-size: 100%;
93
+ font-size: var(--font-size-base);
94
+ color: hsl(var(--foreground));
95
+ }
96
+
97
+ .ui-attachments-card-name-prefix {
98
+ flex: 0 1 auto;
99
+ min-inline-size: 0;
100
+ overflow: hidden;
101
+ text-overflow: ellipsis;
102
+ white-space: nowrap;
103
+ }
104
+
105
+ .ui-attachments-card-name-suffix {
106
+ flex: none;
107
+ }
108
+
109
+ .ui-attachments-card-meta {
110
+ overflow: hidden;
111
+ font-size: var(--font-size-xs, calc(var(--font-size-base) / var(--font-size-ratio)));
112
+ color: hsl(var(--muted-foreground));
113
+ text-overflow: ellipsis;
114
+ white-space: nowrap;
115
+ }
116
+
117
+ .ui-attachments-card[data-status="error"] {
118
+ border-color: hsl(var(--text-error));
119
+ }
120
+
121
+ .ui-attachments-card[data-status="error"] .ui-attachments-card-meta {
122
+ color: hsl(var(--text-error));
123
+ }
124
+
125
+ .ui-attachments-card-progress {
126
+ position: absolute;
127
+ inset-inline: 0;
128
+ inset-block-end: 0;
129
+ display: block;
130
+ }
131
+
132
+ .ui-attachments-card-remove {
133
+ flex: none;
134
+ }
135
+
136
+ .ui-attachments-card-remove > svg {
137
+ inline-size: var(--attachments-remove-icon-size);
138
+ block-size: var(--attachments-remove-icon-size);
139
+ }
140
+
141
+ .ui-attachments-upload-btn {
142
+ display: flex;
143
+ align-items: center;
144
+ justify-content: center;
145
+
146
+ inline-size: var(--attachments-card-block-size);
147
+ block-size: var(--attachments-card-block-size);
148
+ border: var(--stroke-hairline) dashed hsl(var(--border));
149
+ border-radius: var(--attachments-card-radius);
150
+ background-color: transparent;
151
+ color: hsl(var(--muted-foreground));
152
+ cursor: pointer;
153
+ transition:
154
+ border-color 150ms ease,
155
+ color 150ms ease;
156
+ }
157
+
158
+ .ui-attachments-upload-btn:hover:not(:disabled) {
159
+ border-color: hsl(var(--primary));
160
+ color: hsl(var(--primary));
161
+ }
162
+
163
+ .ui-attachments-upload-btn:disabled {
164
+ cursor: not-allowed;
165
+ opacity: 0.5;
166
+ }
167
+
168
+ .ui-attachments-upload-btn > svg {
169
+ inline-size: var(--icon-size-xl);
170
+ block-size: var(--icon-size-xl);
171
+ }
172
+
173
+ .ui-attachments-placeholder {
174
+ display: flex;
175
+ flex-direction: column;
176
+ align-items: center;
177
+ justify-content: center;
178
+ gap: var(--attachments-placeholder-gap);
179
+ padding: var(--attachments-placeholder-space-inset);
180
+ border: var(--stroke-md) dashed hsl(var(--border));
181
+ border-radius: var(--attachments-placeholder-radius);
182
+ background-color: hsl(var(--muted) / 0.4);
183
+ text-align: center;
184
+ cursor: pointer;
185
+ transition:
186
+ border-color 150ms ease,
187
+ background-color 150ms ease;
188
+ }
189
+
190
+ .ui-attachments-placeholder[data-drag-active="true"] {
191
+ border-color: hsl(var(--primary));
192
+ background-color: hsl(var(--primary) / 0.05);
193
+ }
194
+
195
+ .ui-attachments-placeholder:not([data-drag-active="true"]):hover {
196
+ border-color: hsl(var(--primary) / 0.5);
197
+ }
198
+
199
+ .ui-attachments-placeholder[data-disabled="true"] {
200
+ cursor: not-allowed;
201
+ opacity: 0.25;
202
+ pointer-events: none;
203
+ }
204
+
205
+ .ui-attachments-placeholder-icon {
206
+ display: flex;
207
+ color: hsl(var(--muted-foreground));
208
+ }
209
+
210
+ .ui-attachments-placeholder-icon > svg {
211
+ inline-size: var(--attachments-placeholder-icon-size);
212
+ block-size: var(--attachments-placeholder-icon-size);
213
+ }
214
+
215
+ .ui-attachments-placeholder-title {
216
+ font-size: var(--attachments-placeholder-title-font-size);
217
+ font-weight: var(--font-weight-medium);
218
+ color: hsl(var(--foreground));
219
+ }
220
+
221
+ .ui-attachments-placeholder-description {
222
+ font-size: var(--attachments-placeholder-description-font-size);
223
+ color: hsl(var(--muted-foreground));
224
+ }
225
+
226
+ .ui-attachments-drop-layer {
227
+ position: absolute;
228
+ inset: 0;
229
+ z-index: 1;
230
+ border: var(--stroke-md) dashed hsl(var(--primary));
231
+ border-radius: var(--attachments-placeholder-radius);
232
+ background: var(
233
+ --attachments-drop-overlay-background,
234
+ color-mix(in srgb, hsl(var(--background)) 85%, transparent)
235
+ );
236
+ opacity: 0;
237
+ pointer-events: none;
238
+ transition: opacity 150ms ease;
239
+ }
240
+
241
+ .ui-attachments-drop-layer[data-active="true"] {
242
+ opacity: 1;
243
+ backdrop-filter: blur(10px);
244
+ }
245
+
246
+ .ui-attachments-drop-layer[data-scope="viewport"] {
247
+ position: fixed;
5
248
  }
6
249
 
7
250
  .ui-combobox-content {
@@ -1,15 +1,24 @@
1
1
 
2
2
  :root {
3
+
3
4
  --attachments-gap: var(--space-2);
4
- --attachments-card-size: var(--upload-tile-size);
5
- --attachments-card-radius: var(--upload-tile-radius);
6
- --attachments-card-gap: var(--upload-tile-space-gap);
7
- --attachments-placeholder-space-inset: var(--upload-dropzone-space-inset);
8
- --attachments-placeholder-radius: var(--upload-dropzone-radius);
9
- --attachments-placeholder-icon-size: var(--upload-dropzone-icon-size);
10
- --attachments-placeholder-title-font-size: var(--font-size-sm, var(--font-size-base));
11
- --attachments-placeholder-description-font-size: var(--upload-dropzone-meta-font-size);
12
- --attachments-placeholder-gap: var(--space-2);
5
+
6
+ --attachments-card-size: 16.75rem;
7
+ --attachments-card-block-size: 4.25rem;
8
+ --attachments-card-radius: var(--radius-lg);
9
+ --attachments-card-gap: var(--space-3);
10
+
11
+ --attachments-placeholder-space-inset: var(--space-4);
12
+ --attachments-placeholder-radius: var(
13
+ --radius-lg
14
+ );
15
+
16
+ --attachments-placeholder-icon-size: var(--icon-size-3xl);
17
+ --attachments-placeholder-title-font-size: var(--font-size-base);
18
+ --attachments-placeholder-description-font-size: var(--font-size-sm, var(--font-size-base));
19
+ --attachments-placeholder-gap: var(--space-1);
20
+
13
21
  --attachments-drop-overlay-background: initial;
22
+
14
23
  --attachments-remove-icon-size: var(--upload-remove-icon-size);
15
24
  }
@@ -4,7 +4,7 @@
4
4
 
5
5
  --segmented-track-padding: calc(var(--space-1) / 2);
6
6
 
7
- --segmented-track-background: var(--muted);
7
+ --segmented-track-background: initial;
8
8
 
9
9
  --segmented-track-radius: var(--radius);
10
10
  --segmented-item-radius: var(--radius-md);
@@ -27,7 +27,7 @@
27
27
  --segmented-item-hover-background: initial;
28
28
  --segmented-item-active-background: var(--secondary);
29
29
 
30
- --segmented-item-selected-background: var(--background);
30
+ --segmented-item-selected-background: initial;
31
31
  --segmented-item-selected-shadow: var(--shadow-md);
32
32
 
33
33
  --segmented-item-selected-font-weight: var(--font-weight-medium);
@@ -463,11 +463,62 @@ expandable.expandedRowKeys` / `onExpandedRowsChange`. This library already mappe
463
463
  (`src/props/components/data-entry.prop.ts`) and in the MCP catalog. Revisit if a `Space`/compact
464
464
  primitive is ever ported — then antd's steer is followable and this becomes a migration.
465
465
 
466
+ - **`Attachments` is Ant Design X's card and tray, with five measured departures (gh#855).** The
467
+ component had shipped with NO stylesheet at all — fifteen slot classes, one rule, twelve tokens
468
+ read by nothing — so the port below is the first time it followed anything. Geometry was taken
469
+ from `@ant-design/x@2.9.0` (`es/attachments/style/index.js` for root/placeholder/drop-area,
470
+ `es/file-card/style/index.js` for list/card/overflow/remove), not from a screenshot. What was
471
+ NOT followed, and why:
472
+
473
+ 1. **The card's 268px is a CEILING, not a fixed width.** Ant X writes `width: 268` flat. At the
474
+ 320px viewport this repo sweeps, 268 plus the page gutter spills, and `check:frame-overflow`
475
+ is the gate that would have to be baselined around it. `inline-size` + `max-inline-size: 100%`
476
+ keeps Ant's box everywhere it fits and gives ground only where the alternative is a clip.
477
+ 2. **One leading box for a thumbnail AND a glyph.** Ant X has two card types — a 268x68 overview
478
+ card and a separate 68x68 image card — so a tray mixing a `.png` with a `.pdf` gets two
479
+ shapes. This library already decided that question for `Upload` (gh#720: "the image rows draw
480
+ their previewUrl as a thumbnail and every other row draws the glyph for its kind, on one row
481
+ height"), and a second answer in the same group would be the defect.
482
+ 3. **The remove ✕ is always visible, and in flow.** Ant X pins it absolutely outside the card
483
+ corner at `opacity: 0` until the card is hovered. A hover-only control has no touch
484
+ equivalent — worse, an `opacity: 0` button is still hit-testable, so a tablet user taps a
485
+ control they cannot see. `.ui-upload-tile-remove` already made this call. Always-visible in
486
+ turn removes the reason to position it outside the box, so it is the row's trailing item.
487
+ 4. **The placeholder mark is the icon scale's 40px step, not `fontSizeHeading2` (30px).** 30 is
488
+ not one of the nine steps gh#326 fixed, and its neighbours are 24 and 36 — equidistant. The
489
+ token keeps the value the frozen table in `src/tokens/__tests__/icon-size-scale.test.ts`
490
+ already records for it, which is `--upload-dropzone-icon-size`: the mark a reader meets this
491
+ surface beside. Same reasoning holds `--attachments-remove-icon-size` at 14px against Ant's
492
+ `fontSizeLG` = 16.
493
+ 5. **The placeholder carries a dashed border at rest; Ant X's is `transparent`.** Ant X's
494
+ placeholder sits INSIDE a `Sender`, which already draws the boundary. Here `Attachments` is
495
+ also used standalone, where a target with no edge is not a target — so it takes
496
+ `.ui-upload-dropzone`'s dashed edge.
497
+
498
+ Not ported, and named here so the gap is a decision rather than an oversight: Ant X's 8px
499
+ `::before`/`::after` scroll-edge gradients and their `ping-start`/`ping-end` state (they need a
500
+ scroll listener, and the clipped card already reads as "more this way"), and its full-screen
501
+ drop area — `getDropContainer` positions the layer `fixed`, but activation is still the
502
+ control's own dragenter, not the document's.
503
+
466
504
  **A knob that only a fork could reach is not parity either.** antd's `components`,
467
505
  `filterDropdown`, `classNames`/`styles` semantic maps and `prefixCls` all exist to let a consumer
468
506
  replace the rendered markup. This library answers that layer with tokens (cardinal rule #45), so
469
507
  those are deliberately NOT adopted — adopting them would re-open the hole the token tiers close.
470
508
 
509
+ **Except on `Attachments`, which carries them — recorded, not blessed (gh#857).**
510
+ `AttachmentsProp` declares `classNames`, `styles` and `rootClassName`, and `attachments.tsx`
511
+ forwards all three onto root, list, card, upload and placeholder. It is the ONLY semantic part map
512
+ in the package: `grep '^ classNames?:' src/props/components/*.prop.ts` matches this component and
513
+ nothing else. So the paragraph above is the standing ruling and this is a single-component
514
+ departure from it, surfaced when `check:mcp-prop-sync` stopped being blind to props declared after
515
+ a function type. The catalog said the opposite — "DON'T expect `styles`/`classNames` from Ant X" —
516
+ while the published `.d.ts` offered them, which is the worst of the three states: an agent reading
517
+ the catalog and an agent reading autocomplete got different answers. The catalog now states what
518
+ ships. Removing them is a breaking change to a public type and belongs to its own issue; until
519
+ then, `--attachments-*` is the supported route and this is not a pattern to copy onto a second
520
+ component.
521
+
471
522
  ## One `Dialog`, not two families — and the rule a consumer picks by
472
523
 
473
524
  **Status:** accepted · 2026-09-12 · gh#567
@@ -0,0 +1,6 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="240" height="96" viewBox="0 0 240 96" role="img">
2
+ <rect width="240" height="96" rx="12" fill="hsl(348 32% 42%)"/>
3
+ <rect x="24" y="30" width="36" height="36" rx="8" fill="hsl(348 32% 88%)"/>
4
+ <rect x="76" y="36" width="140" height="10" rx="5" fill="hsl(348 32% 88%)"/>
5
+ <rect x="76" y="54" width="96" height="10" rx="5" fill="hsl(348 32% 74%)"/>
6
+ </svg>
@@ -0,0 +1,5 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128" role="img">
2
+ <rect width="128" height="128" rx="28" fill="hsl(178 38% 34%)"/>
3
+ <path d="M40 78 L64 34 L88 78 Z" fill="hsl(178 38% 88%)"/>
4
+ <circle cx="64" cy="90" r="9" fill="hsl(178 38% 88%)"/>
5
+ </svg>