@godxjp/ui 33.9.1 → 33.11.2

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 (43) hide show
  1. package/DESIGN.md +10 -7
  2. package/README.md +3 -3
  3. package/agent/DESIGN.md +10 -7
  4. package/agent/START-HERE.md +4 -4
  5. package/agent/components/Cascader.json +1 -0
  6. package/agent/components/DatePicker.json +1 -0
  7. package/agent/components/Input.json +1 -0
  8. package/agent/components/NumberInput.json +1 -0
  9. package/agent/components/PasswordInput.json +1 -0
  10. package/agent/components/SearchInput.json +1 -0
  11. package/agent/components/Select.json +1 -0
  12. package/agent/components/TimePicker.json +1 -0
  13. package/agent/components/Topbar.json +8 -2
  14. package/agent/components/TopbarItem.json +7 -1
  15. package/agent/components/TreeSelect.json +1 -0
  16. package/agent/components.json +24 -3
  17. package/agent/index.json +5 -5
  18. package/agent/llms.txt +6 -6
  19. package/agent/tokens.json +54 -36
  20. package/dist/components/data-entry/input.js +16 -1
  21. package/dist/components/data-entry/search-input.js +1 -1
  22. package/dist/components/layout/topbar-item.d.ts +1 -0
  23. package/dist/components/layout/topbar-item.js +9 -4
  24. package/dist/components/layout/topbar.d.ts +1 -1
  25. package/dist/components/layout/topbar.js +25 -3
  26. package/dist/contracts/measurement.json +1 -1
  27. package/dist/props/components/layout.prop.d.ts +13 -0
  28. package/dist/props/registry.d.ts +9 -1
  29. package/dist/props/registry.js +10 -0
  30. package/dist/styles/control.css +131 -3
  31. package/dist/styles/layers.json +1 -1
  32. package/dist/styles/shell-layout.css +38 -0
  33. package/dist/styles.css +1 -1
  34. package/dist/tokens/components/card.css +3 -3
  35. package/dist/tokens/components/control.css +8 -5
  36. package/dist/tokens/components/form.css +1 -1
  37. package/dist/tokens/components/shell.css +3 -0
  38. package/dist/tokens/components/table.css +1 -1
  39. package/dist/tokens/foundation.css +11 -11
  40. package/dist/tokens/semantic/layout.css +3 -3
  41. package/docs/TOKENS.md +73 -1
  42. package/package.json +2 -2
  43. package/scripts/visual-audit.mjs +33 -3
@@ -8,7 +8,7 @@
8
8
 
9
9
  --card-space-header-y: var(--space-stack-sm);
10
10
 
11
- --card-space-body-y: var(--space-section-active);
11
+ --card-space-body-y: var(--space-6);
12
12
 
13
13
  --card-space-solo-y: initial;
14
14
 
@@ -17,7 +17,7 @@
17
17
  --card-space-divided-y: var(--card-space-header-y);
18
18
 
19
19
  --card-space-gap: var(--space-stack-xs);
20
- --card-title-font-size: var(--font-size-base);
20
+ --card-title-font-size: calc(var(--font-size-base) * var(--font-size-ratio));
21
21
  --card-title-line-height: var(--line-height-tight);
22
22
  --card-title-font-weight: var(--font-weight-semibold);
23
23
  --card-description-font-size: var(--font-size-sm, var(--font-size-base));
@@ -32,7 +32,7 @@
32
32
  --card-header-border-bottom: initial;
33
33
  --card-radius: initial;
34
34
 
35
- --card-shadow: initial;
35
+ --card-shadow: none;
36
36
 
37
37
  --card-glow: 0 0 0 0 transparent;
38
38
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  :root {
4
4
  --control-height-compact: var(--band-height-sm);
5
- --control-height-default: var(--band-height-md);
5
+ --control-height-default: var(--band-height-lg);
6
6
  --control-height-comfortable: var(--band-height-xl);
7
7
  --control-padding-x-compact: var(--space-2);
8
8
  --control-padding-x-default: var(--space-3);
@@ -22,7 +22,7 @@
22
22
  --control-gap-sm: var(--space-inline-xs);
23
23
  --control-radius: var(--radius);
24
24
 
25
- --button-radius: var(--radius-md, calc(var(--radius) / var(--radius-ratio)));
25
+ --button-radius: var(--radius);
26
26
 
27
27
  --button-default-background: initial;
28
28
  --button-destructive-background: initial;
@@ -37,7 +37,7 @@
37
37
 
38
38
  --control-font-size: var(--font-size-base);
39
39
  --control-border-width: initial;
40
- --control-shadow: var(--shadow-xs);
40
+ --control-shadow: none;
41
41
  --control-icon-size: calc(var(--icon-size-md) * var(--scaling));
42
42
  --control-icon-size-sm: calc(var(--icon-size-sm) * var(--scaling));
43
43
 
@@ -107,7 +107,7 @@
107
107
  --toggle-focus-ring-width: initial;
108
108
  --toggle-focus-ring-alpha: 1;
109
109
 
110
- --control-focus-ring-width: initial;
110
+ --control-focus-ring-width: var(--stroke-md);
111
111
 
112
112
  --rating-focus-ring-offset: 2px;
113
113
 
@@ -234,6 +234,8 @@
234
234
 
235
235
  --control-affix-inset-inline-end: var(--space-2);
236
236
  --control-affix-action-size: 1.5rem;
237
+
238
+ --control-affix-touch-target-size: var(--band-height-xl);
237
239
  --control-affix-action-radius: initial;
238
240
  --control-affix-icon-size: var(--icon-size-md);
239
241
 
@@ -499,7 +501,8 @@
499
501
  --control-height-default: var(--band-height-xl);
500
502
 
501
503
  --search-input-end-padding: calc(
502
- var(--search-input-edge-inset) + var(--touch-target-min) / 2 + var(--band-height-xl) / 2
504
+ var(--search-input-edge-inset) + var(--touch-target-min) / 2 +
505
+ var(--control-affix-touch-target-size) / 2
503
506
  );
504
507
  }
505
508
  }
@@ -8,7 +8,7 @@
8
8
 
9
9
  --form-label-font-size: var(--control-label-font-size, var(--text-sm));
10
10
 
11
- --form-block-gap: var(--space-4);
11
+ --form-block-gap: var(--space-6);
12
12
 
13
13
  --form-feedback-icon-size: var(--icon-size-sm);
14
14
 
@@ -155,6 +155,9 @@
155
155
  --topbar-inset: 0px;
156
156
  --topbar-gap: var(--space-2);
157
157
 
158
+ --topbar-identity-max-inline-size: 40%;
159
+ --topbar-identity-min-text-inline-size: 3ch;
160
+
158
161
  --topbar-background-alpha: initial;
159
162
  --topbar-backdrop-blur-size: initial;
160
163
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  :root {
4
4
  --table-row-height-compact: var(--band-height-sm);
5
- --table-row-height-default: var(--band-height-md);
5
+ --table-row-height-default: var(--band-height-lg);
6
6
  --table-row-height-comfortable: var(--band-height-xl);
7
7
  --table-row-height: calc(var(--table-row-height-default) * var(--scaling));
8
8
  --table-cell-padding-y: var(--space-2);
@@ -30,7 +30,7 @@
30
30
 
31
31
  --border: 30 7% 93%;
32
32
 
33
- --input: 30 7% 53%;
33
+ --input: 30 7% 51%;
34
34
 
35
35
  --success: 146 40% 58%;
36
36
  --success-foreground: 48 8% 13%;
@@ -109,9 +109,9 @@
109
109
  --shadow-xs: 0 1px 1px 0 rgb(var(--shadow-color) / 0.04);
110
110
  --shadow-sm: 0 1px 2px 0 rgb(var(--shadow-color) / 0.05);
111
111
  --shadow-md:
112
- 0 4px 6px -1px rgb(var(--shadow-color) / 0.1), 0 2px 4px -2px rgb(var(--shadow-color) / 0.1);
112
+ 0 6px 16px -4px rgb(var(--shadow-color) / 0.08), 0 1px 3px 0 rgb(var(--shadow-color) / 0.08);
113
113
  --shadow-lg:
114
- 0 10px 15px -3px rgb(var(--shadow-color) / 0.1), 0 4px 6px -4px rgb(var(--shadow-color) / 0.1);
114
+ 0 12px 28px -6px rgb(var(--shadow-color) / 0.1), 0 2px 6px -2px rgb(var(--shadow-color) / 0.08);
115
115
  --shadow-xl:
116
116
  0 20px 25px -5px rgb(var(--shadow-color) / 0.1), 0 8px 10px -6px rgb(var(--shadow-color) / 0.1);
117
117
  --shadow-2xl: 0 25px 50px -12px rgb(var(--shadow-color) / 0.25);
@@ -125,12 +125,12 @@
125
125
  --brand-glow: initial;
126
126
 
127
127
  --focus-outline: 1;
128
- --focus-outline-weight: initial;
128
+ --focus-outline-weight: var(--stroke-md);
129
129
 
130
130
  --focus-outline-color: initial;
131
131
 
132
132
  --control-outline-width: calc(var(--stroke-md) * var(--focus-outline));
133
- --focus-outline-offset: 0px;
133
+ --focus-outline-offset: 2px;
134
134
 
135
135
  --focus-ring-color: initial;
136
136
 
@@ -263,9 +263,9 @@
263
263
  --phi-p1: calc(var(--phi-unit) * var(--ratio-phi));
264
264
  --phi-p2: calc(var(--phi-p1) * var(--ratio-phi));
265
265
 
266
- --duration-fast: 150ms;
267
- --duration-base: 250ms;
268
- --duration-slow: 500ms;
266
+ --duration-fast: 120ms;
267
+ --duration-base: 180ms;
268
+ --duration-slow: 320ms;
269
269
  --ease-standard: cubic-bezier(0.2, 0, 0, 1);
270
270
  --ease-emphasized: cubic-bezier(0.32, 0.72, 0, 1);
271
271
  --ease-decelerate: cubic-bezier(0, 0, 0, 1);
@@ -319,8 +319,8 @@
319
319
  --table-row-height: var(--table-row-height-default);
320
320
  --table-cell-padding-y: var(--space-2);
321
321
  --phi-unit: var(--space-4);
322
- --space-page-x: var(--space-6);
323
- --space-page-y: var(--space-6);
322
+ --space-page-x: var(--space-8);
323
+ --space-page-y: var(--space-8);
324
324
  --space-section: var(--space-4);
325
325
  --space-section-band: var(--space-20);
326
326
  --space-section-hero: var(--space-24);
@@ -364,7 +364,7 @@
364
364
 
365
365
  --border: 45 6% 19%;
366
366
 
367
- --input: 45 6% 47%;
367
+ --input: 45 6% 51%;
368
368
 
369
369
  --success: 146 45% 55%;
370
370
  --success-foreground: 48 9% 9%;
@@ -2,8 +2,8 @@
2
2
 
3
3
  :root {
4
4
 
5
- --space-page-x: var(--space-6);
6
- --space-page-y: var(--space-6);
5
+ --space-page-x: var(--space-8);
6
+ --space-page-y: var(--space-8);
7
7
  --space-section: var(--space-4);
8
8
 
9
9
  --space-section-band: var(--space-20);
@@ -46,7 +46,7 @@
46
46
  --space-page-compact-y: var(--space-4);
47
47
  --space-section-compact: var(--space-4);
48
48
 
49
- --overlay-background: rgb(0 0 0 / 0.5);
49
+ --overlay-background: rgb(0 0 0 / 0.4);
50
50
 
51
51
  --surface-recessed: hsl(var(--muted) / 0.4);
52
52
 
package/docs/TOKENS.md CHANGED
@@ -175,7 +175,7 @@ These two look like synonyms and are not. Keep them apart:
175
175
  | `--border` | Decorative chrome — table rules, card edges, section dividers, `<Separator>` | **None.** WCAG 2.2 SC 1.4.11 does not reach a divider; this system's dense JP grid depends on it staying quiet |
176
176
  | `--input` | The boundary that **is** the control — Input, Textarea, Select, outline Button, TagInput, composite date field, topbar search, and the Switch's unchecked track | **≥ 3:1** (SC 1.4.11 Non-text Contrast) against every surface a control sits on — page, card, popover, muted/secondary panel, striped and hovered rows |
177
177
 
178
- A field here has no fill of its own (`background: hsl(var(--background))`) and no shadow to speak of, so that 1px edge is the whole visual claim that you may type there. Current values: `30 7% 53%` light (3.47:1 on `--background`/`--card`, 3.18:1 on `--muted`) and `45 6% 47%` dark (4.22:1 on `--background`, 3.88:1 on `--card`/`--popover`, 3.17:1 on `--muted`).
178
+ A field here has no fill of its own (`background: hsl(var(--background))`) and no shadow to speak of, so that 1px edge is the whole visual claim that you may type there. Current values: `30 7% 51%` light and `45 6% 51%` dark. Both clear 3:1 on background, card, popover, muted and the full accent surface. The earlier 53% / 47% pair passed translucent table hover backgrounds but failed the full accent surface (2.91:1 / 2.69:1).
179
179
 
180
180
  **Re-theming rule:** a service theme that retints neutrals must move these two **independently** — setting `--input: var(--border)` re-opens the bug. `src/tokens/__tests__/input-boundary-contrast.test.ts` recomputes the ratios from `foundation.css` and fails below 3:1, and fails outright if the two roles are given the same value again.
181
181
 
@@ -482,3 +482,75 @@ It is reserved for `@container` / `@media` re-points. Everything static stays in
482
482
  ## MCP
483
483
 
484
484
  `godxjp_ui_guide` topic=`golden-ratio` · `tokens`
485
+
486
+ ## Second pass: hierarchy and rhythm
487
+
488
+ Fifteen existing token defaults build on the eight first-pass changes. Body stays 14px/1.7, labels and headings stay 500, with no Latin-style negative tracking on Japanese. Mobile gutters remain 16px. Zebra stays off; table numeric alignment and sidebar active styling are unchanged. Card header-to-body spacing grows to 24px; horizontal card/table insets and section gaps stay 16px so fixed-width date columns remain on one line. No new token or component API.
489
+
490
+ | Token | Previous | New |
491
+ |---|---|---|
492
+ | `--space-page-x` | `var(--space-6)` | `var(--space-8)` |
493
+ | `--space-page-y` | `var(--space-6)` | `var(--space-8)` |
494
+ | `--card-space-body-y` | `var(--space-section-active)` | `var(--space-6)` |
495
+ | `--page-title-font-size` | `var( --heading-h1, calc( var(--font-size-base) * var(--font-size-ratio) * var(--font-size-ratio) * var(--font-size-ratio) ) )` | `var( --heading-h1, calc( var(--font-size-base) * var(--font-size-ratio) * var(--font-size-ratio) * var(--font-size-ratio) ) )` |
496
+ | `--page-title-font-size-compact` | `var( --heading-h2, calc(var(--font-size-base) * var(--font-size-ratio) * var(--font-size-ratio)) )` | `var( --heading-h2, calc(var(--font-size-base) * var(--font-size-ratio) * var(--font-size-ratio)) )` |
497
+ | `--overlay-background` | `rgb(0 0 0 / 0.5)` | `rgb(0 0 0 / 0.4)` |
498
+ | `--card-title-font-size` | `var(--font-size-base)` | `calc(var(--font-size-base) * var(--font-size-ratio))` |
499
+ | `--card-shadow` | `initial` | `none` |
500
+ | `--form-field-row-gap` | `var(--space-3)` | `var(--space-3)` |
501
+ | `--form-block-gap` | `var(--space-4)` | `var(--space-6)` |
502
+ | `--control-height-default` | `var(--band-height-md)` | `var(--band-height-lg)` |
503
+ | `--control-focus-ring-width` | `initial` | `var(--stroke-md)` |
504
+ | `--table-row-height-default` | `var(--band-height-md)` | `var(--band-height-lg)` |
505
+ | `--focus-outline-weight` | `initial` | `var(--stroke-md)` |
506
+ | `--focus-outline-offset` | `0px` | `2px` |
507
+
508
+ ### Complete restoration (both passes)
509
+
510
+ Load after library and preset styles. The original input colors restore the original sub-3:1 accent-boundary limitation.
511
+
512
+ ```css
513
+ :root {
514
+ --space-page-x: var(--space-6);
515
+ --space-page-y: var(--space-6);
516
+ --card-space-body-y: var(--space-section-active);
517
+ --page-title-font-size: var( --heading-h1, calc( var(--font-size-base) * var(--font-size-ratio) * var(--font-size-ratio) * var(--font-size-ratio) ) );
518
+ --page-title-font-size-compact: var( --heading-h2, calc(var(--font-size-base) * var(--font-size-ratio) * var(--font-size-ratio)) );
519
+ --overlay-background: rgb(0 0 0 / 0.5);
520
+ --card-title-font-size: var(--font-size-base);
521
+ --card-shadow: initial;
522
+ --form-field-row-gap: var(--space-3);
523
+ --form-block-gap: var(--space-4);
524
+ --control-height-default: var(--band-height-md);
525
+ --control-focus-ring-width: initial;
526
+ --table-row-height-default: var(--band-height-md);
527
+ --focus-outline-weight: initial;
528
+ --focus-outline-offset: 0px;
529
+ --button-radius: var(--radius-md, calc(var(--radius) / var(--radius-ratio)));
530
+ --control-shadow: var(--shadow-xs);
531
+ --shadow-md: 0 4px 6px -1px rgb(var(--shadow-color) / 0.1), 0 2px 4px -2px rgb(var(--shadow-color) / 0.1);
532
+ --shadow-lg: 0 10px 15px -3px rgb(var(--shadow-color) / 0.1), 0 4px 6px -4px rgb(var(--shadow-color) / 0.1);
533
+ --duration-fast: 150ms;
534
+ --duration-base: 250ms;
535
+ --duration-slow: 500ms;
536
+ --input: 30 7% 53%;
537
+ }
538
+ .dark, :root[data-theme="dark"] { --input: 45 6% 47%; }
539
+
540
+ .ui-scale-fixed {
541
+ --space-page-x: var(--space-6);
542
+ --space-page-y: var(--space-6);
543
+ --space-section: var(--space-4);
544
+ }
545
+ ```
546
+
547
+ ### Input affix touch targets
548
+
549
+ `--control-affix-touch-target-size` defaults to `var(--band-height-xl)` (44px) and applies
550
+ only under `pointer: coarse`. It sizes the action box, not the glyph. Input reserves the measured
551
+ width of its complete trailing slot plus the existing inset and gap, including two adjacent
552
+ 44px actions in a 200px field. `--input-trailing-measured-size` is runtime measurement, not a
553
+ service override. `allowClear` still replaces the suffix; DatePicker and TimePicker still swap
554
+ clear and open actions. NumberInput lays out its two steppers horizontally on coarse pointers.
555
+ SearchInput retains its glyph centre while sharing this target token. Fine-pointer geometry is
556
+ unchanged. Override the token on the field or in the service theme; no new prop is required.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@godxjp/ui",
3
- "version": "33.9.1",
4
- "godxUiMcp": "33.9.1",
3
+ "version": "33.11.2",
4
+ "godxUiMcp": "33.11.2",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
@@ -453,9 +453,9 @@ export const PROBE_RULES = [
453
453
  id: "c04-compact-account-name",
454
454
  severity: "warn",
455
455
  category: "a11y",
456
- standard: `compact (<600px) bar shows no account name (${RC}); trigger name per WCAG 2.2 SC 4.1.2`,
456
+ standard: `compact (<600px) bar shows avatar-only or measured bounded shared-device identity (${RC}); trigger name per WCAG 2.2 SC 4.1.2`,
457
457
  kind: "probe",
458
- fix: "Below 600px the bar shows the avatar only: hide the account name (it belongs in the opened account menu) and make the avatar the trigger — accessible name + aria-haspopup, opening identity and account controls.",
458
+ fix: "Shared-device exception: Topbar identity with TopbarItem truncate keeps a bounded, ellipsised name and full title/accessible name. Otherwise below 600px the bar shows the avatar only: hide the account name (it belongs in the opened account menu) and make the avatar the trigger — accessible name + aria-haspopup, opening identity and account controls.",
459
459
  },
460
460
  {
461
461
  id: "c05-compact-editor-inset",
@@ -733,7 +733,7 @@ export function evaluateProbes(raw, { url, viewport }) {
733
733
  // C04 — compact account access without the name in the bar.
734
734
  const accounts = applies("c04-compact-account-name") ? raw.c04?.mapped || [] : [];
735
735
  for (const a of accounts) {
736
- if (a.nameVisible)
736
+ if (a.nameVisible && !a.compactIdentity)
737
737
  add(
738
738
  "c04-compact-account-name",
739
739
  a.element,
@@ -1158,7 +1158,37 @@ export function collectProbes(opts) {
1158
1158
  const pushAccount = (region, nameEl, avatar, t, nameText) => {
1159
1159
  if (avatar) accountAvatars.add(avatar);
1160
1160
  const text = nameText ?? (nameEl && shown(nameEl) ? snippet(nameEl.textContent) : "");
1161
+ const label = region.querySelector('[data-slot="topbar-item-label"]');
1162
+ const identity = region.closest('[data-slot="topbar-identity"]');
1163
+ const bar = identity?.closest('[data-slot="topbar"]');
1164
+ const r = region.getBoundingClientRect();
1165
+ const b = bar?.getBoundingClientRect();
1166
+ const l = label?.getBoundingClientRect();
1167
+ // An opt-in is not an exemption by itself: measure the visible label, bounded share,
1168
+ // containment, and full-name recovery. Old full-width labels still fail C04.
1169
+ const compactIdentity = !!(
1170
+ identity &&
1171
+ b &&
1172
+ label &&
1173
+ l &&
1174
+ text &&
1175
+ region.getAttribute("data-truncate") === "true" &&
1176
+ cs(label).textOverflow === "ellipsis" &&
1177
+ cs(label).whiteSpace === "nowrap" &&
1178
+ l.width > 1 &&
1179
+ l.height > 1 &&
1180
+ l.left >= r.left - 1 &&
1181
+ l.right <= r.right + 1 &&
1182
+ r.width <= b.width * 0.4 + 1 &&
1183
+ r.left >= b.left - 1 &&
1184
+ r.right <= b.right + 1 &&
1185
+ r.left >= -1 &&
1186
+ r.right <= width + 1 &&
1187
+ region.getAttribute("title")?.includes(label.textContent) &&
1188
+ accName(region).includes(label.textContent)
1189
+ );
1161
1190
  accounts.push({
1191
+ compactIdentity,
1162
1192
  element: desc(region),
1163
1193
  nameVisible: !!text,
1164
1194
  nameText: text,