@godxjp/ui 28.5.0 → 28.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/components/data-display/data-table.d.ts +10 -2
  2. package/dist/components/data-display/data-table.js +12 -5
  3. package/dist/components/data-display/scroll-area.js +16 -2
  4. package/dist/components/data-display/service-launcher-card.d.ts +25 -0
  5. package/dist/components/data-display/table.d.ts +38 -1
  6. package/dist/components/data-display/table.js +57 -39
  7. package/dist/components/data-entry/field.d.ts +1 -1
  8. package/dist/components/data-entry/field.js +35 -4
  9. package/dist/components/data-entry/form-field.js +29 -12
  10. package/dist/components/data-entry/input.d.ts +1 -1
  11. package/dist/components/layout/index.d.ts +1 -1
  12. package/dist/components/layout/nav-list.d.ts +9 -1
  13. package/dist/components/layout/nav-list.js +22 -11
  14. package/dist/components/layout/sidebar.d.ts +16 -2
  15. package/dist/components/layout/sidebar.js +1 -0
  16. package/dist/components/navigation/app-setting-picker.js +20 -3
  17. package/dist/components/ui/password-input.d.ts +1 -1
  18. package/dist/components/ui/table.js +1 -0
  19. package/dist/contracts/measurement.json +1 -1
  20. package/dist/i18n/messages/en.json +5 -1
  21. package/dist/i18n/messages/ja.json +5 -1
  22. package/dist/i18n/messages/vi.json +5 -1
  23. package/dist/lib/control-styles.d.ts +18 -3
  24. package/dist/lib/control-styles.js +1 -1
  25. package/dist/lib/hooks.d.ts +23 -0
  26. package/dist/lib/hooks.js +27 -0
  27. package/dist/props/components/data-display.prop.d.ts +14 -0
  28. package/dist/props/components/data-entry.prop.d.ts +36 -2
  29. package/dist/props/components/layout.prop.d.ts +16 -5
  30. package/dist/props/registry.d.ts +2 -2
  31. package/dist/props/registry.js +10 -2
  32. package/dist/styles/control.css +12 -0
  33. package/dist/styles/data-display-layout.css +25 -2
  34. package/dist/styles/dialog-layout.css +12 -0
  35. package/dist/styles/form-layout.css +22 -0
  36. package/dist/styles/layout.css +1 -2
  37. package/dist/styles/navigation-layout.css +18 -19
  38. package/dist/tokens/components/data-display.css +2 -1
  39. package/dist/tokens/components/feedback.css +2 -0
  40. package/dist/tokens/components/form.css +2 -0
  41. package/dist/tokens/components/navigation.css +2 -0
  42. package/docs/COMPOSITION-VS-COMPONENT.md +3 -0
  43. package/docs/DESIGN-AUTHORITY.md +25 -5
  44. package/docs/FRAME-COVERAGE-REPORT.md +1 -1
  45. package/docs/data-display/collapsible.tsx +5 -5
  46. package/docs/data-display/descriptions.tsx +188 -109
  47. package/docs/data-display/legend.tsx +17 -4
  48. package/docs/data-display/scroll-area.tsx +106 -5
  49. package/docs/data-display/service-launcher-card.tsx +275 -115
  50. package/docs/data-display/stat-card.tsx +319 -64
  51. package/docs/data-entry/form.tsx +700 -6
  52. package/docs/data-entry/input.tsx +663 -53
  53. package/docs/data-entry/radio-group.tsx +216 -2
  54. package/docs/data-entry/switch.tsx +210 -4
  55. package/docs/data-entry/upload-crop-dialog.tsx +24 -25
  56. package/docs/layout/nav-list.tsx +556 -35
  57. package/package.json +9 -7
  58. package/scripts/visual-audit.mjs +29 -1
@@ -95,6 +95,32 @@ function collectInPage() {
95
95
  const cs = getComputedStyle(el);
96
96
  return r.width > 0 && r.height > 0 && cs.visibility !== "hidden" && cs.display !== "none";
97
97
  };
98
+ // `visible` above is ELEMENT-LOCAL — it reads the node's own box and its own visibility/display,
99
+ // and an ancestor can still clip the node out of the rendered page entirely. The visually-hidden
100
+ // idiom (Tailwind `sr-only`, react-aria `<VisuallyHidden>`) is exactly that: a 1x1 container with
101
+ // `overflow: hidden` + `clip: rect(0 0 0 0)` wrapping a FULL-SIZE child. The child's own
102
+ // getBoundingClientRect stays full size, so an element-local test calls it visible.
103
+ //
104
+ // gh#818: every `<Select>` carries react-aria's native `<select>` in one of those containers —
105
+ // the form-submit + browser-autofill fallback, `aria-hidden`, `tabindex="-1"`, painted nowhere.
106
+ // Its box is the width of its concatenated option labels (85x22 for a locale picker), so
107
+ // `target-size-min` reported one per Select on every consumer page, and the consumer read it as
108
+ // a second, undersized language control sitting beside the styled trigger. Measured in Chromium:
109
+ // `document.elementFromPoint` at that `<select>`'s own centre never returns the select, and at
110
+ // the trigger's centre +/-11px it returns the trigger — there is one target, not two.
111
+ //
112
+ // SC 2.5.8 bounds TARGETS: "the region of the display that will accept a pointer action". A node
113
+ // clipped to a 1px sliver accepts none at any size, so it is not a target and must not be
114
+ // measured as one — enlarging it would be the wrong fix twice over.
115
+ const clippedAway = (el) => {
116
+ for (let a = el.parentElement; a; a = a.parentElement) {
117
+ const cs = getComputedStyle(a);
118
+ if (cs.overflow === "visible" && cs.clip === "auto" && cs.clipPath === "none") continue;
119
+ const r = a.getBoundingClientRect();
120
+ if (r.width <= 1 || r.height <= 1) return true;
121
+ }
122
+ return false;
123
+ };
98
124
 
99
125
  // Accent surfaces — buttons / primary CTAs / banners whose background carries colour.
100
126
  const accents = [];
@@ -116,7 +142,9 @@ function collectInPage() {
116
142
  for (const el of document.querySelectorAll(
117
143
  "a[href], button, [role=button], input:not([type=hidden]), select, [tabindex]:not([tabindex='-1'])",
118
144
  )) {
119
- if (!visible(el)) continue;
145
+ // Dropped BEFORE the list is built, not filtered after: a node nobody can point at must not
146
+ // count as a neighbour either, or it spends the Spacing exception of the real target it sits on.
147
+ if (!visible(el) || clippedAway(el)) continue;
120
148
  const r = el.getBoundingClientRect();
121
149
  const name = (el.getAttribute("aria-label") || el.textContent || "").trim().slice(0, 40);
122
150
  rawTargets.push({