@multiplatform.one/forms 7.28.1 → 7.29.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 (87) hide show
  1. package/dist/cjs/AdaptivePopup/index.cjs +19 -22
  2. package/dist/cjs/AdaptivePopup/index.native.js +19 -22
  3. package/dist/cjs/AdaptivePopup/index.native.js.map +1 -1
  4. package/dist/cjs/Button/index.cjs +11 -6
  5. package/dist/cjs/Button/index.native.js +11 -6
  6. package/dist/cjs/Button/index.native.js.map +1 -1
  7. package/dist/cjs/Chip/index.cjs +3 -2
  8. package/dist/cjs/Chip/index.native.js +4 -3
  9. package/dist/cjs/Chip/index.native.js.map +1 -1
  10. package/dist/cjs/ContextualSaveBar/UnsavedChangesDialog.cjs +14 -0
  11. package/dist/cjs/ContextualSaveBar/UnsavedChangesDialog.native.js +14 -0
  12. package/dist/cjs/ContextualSaveBar/UnsavedChangesDialog.native.js.map +1 -1
  13. package/dist/cjs/fields/Geolocation/index.cjs +1 -0
  14. package/dist/cjs/fields/Geolocation/index.native.js +1 -0
  15. package/dist/cjs/fields/Geolocation/index.native.js.map +1 -1
  16. package/dist/cjs/shared/focusManagement.cjs +28 -0
  17. package/dist/cjs/shared/focusManagement.native.js +38 -0
  18. package/dist/cjs/shared/focusManagement.native.js.map +1 -1
  19. package/dist/esm/AdaptivePopup/index.mjs +20 -23
  20. package/dist/esm/AdaptivePopup/index.mjs.map +1 -1
  21. package/dist/esm/AdaptivePopup/index.native.js +20 -23
  22. package/dist/esm/AdaptivePopup/index.native.js.map +1 -1
  23. package/dist/esm/Button/index.mjs +12 -7
  24. package/dist/esm/Button/index.mjs.map +1 -1
  25. package/dist/esm/Button/index.native.js +12 -7
  26. package/dist/esm/Button/index.native.js.map +1 -1
  27. package/dist/esm/Chip/index.mjs +4 -3
  28. package/dist/esm/Chip/index.mjs.map +1 -1
  29. package/dist/esm/Chip/index.native.js +5 -4
  30. package/dist/esm/Chip/index.native.js.map +1 -1
  31. package/dist/esm/ContextualSaveBar/UnsavedChangesDialog.mjs +16 -2
  32. package/dist/esm/ContextualSaveBar/UnsavedChangesDialog.mjs.map +1 -1
  33. package/dist/esm/ContextualSaveBar/UnsavedChangesDialog.native.js +16 -2
  34. package/dist/esm/ContextualSaveBar/UnsavedChangesDialog.native.js.map +1 -1
  35. package/dist/esm/fields/Geolocation/index.mjs +1 -0
  36. package/dist/esm/fields/Geolocation/index.mjs.map +1 -1
  37. package/dist/esm/fields/Geolocation/index.native.js +1 -0
  38. package/dist/esm/fields/Geolocation/index.native.js.map +1 -1
  39. package/dist/esm/shared/focusManagement.mjs +28 -2
  40. package/dist/esm/shared/focusManagement.mjs.map +1 -1
  41. package/dist/esm/shared/focusManagement.native.js +38 -2
  42. package/dist/esm/shared/focusManagement.native.js.map +1 -1
  43. package/dist/jsx/AdaptivePopup/index.mjs +20 -23
  44. package/dist/jsx/AdaptivePopup/index.mjs.map +1 -1
  45. package/dist/jsx/AdaptivePopup/index.native.js +19 -22
  46. package/dist/jsx/AdaptivePopup/index.native.js.map +1 -1
  47. package/dist/jsx/Button/index.mjs +12 -7
  48. package/dist/jsx/Button/index.mjs.map +1 -1
  49. package/dist/jsx/Button/index.native.js +11 -6
  50. package/dist/jsx/Button/index.native.js.map +1 -1
  51. package/dist/jsx/Chip/index.mjs +4 -3
  52. package/dist/jsx/Chip/index.mjs.map +1 -1
  53. package/dist/jsx/Chip/index.native.js +4 -3
  54. package/dist/jsx/Chip/index.native.js.map +1 -1
  55. package/dist/jsx/ContextualSaveBar/UnsavedChangesDialog.mjs +16 -2
  56. package/dist/jsx/ContextualSaveBar/UnsavedChangesDialog.mjs.map +1 -1
  57. package/dist/jsx/ContextualSaveBar/UnsavedChangesDialog.native.js +14 -0
  58. package/dist/jsx/ContextualSaveBar/UnsavedChangesDialog.native.js.map +1 -1
  59. package/dist/jsx/fields/Geolocation/index.mjs +1 -0
  60. package/dist/jsx/fields/Geolocation/index.mjs.map +1 -1
  61. package/dist/jsx/fields/Geolocation/index.native.js +1 -0
  62. package/dist/jsx/fields/Geolocation/index.native.js.map +1 -1
  63. package/dist/jsx/shared/focusManagement.mjs +28 -2
  64. package/dist/jsx/shared/focusManagement.mjs.map +1 -1
  65. package/dist/jsx/shared/focusManagement.native.js +38 -0
  66. package/dist/jsx/shared/focusManagement.native.js.map +1 -1
  67. package/package.json +8 -8
  68. package/src/AdaptivePopup/AdaptivePopup.spec.tsx +44 -1
  69. package/src/AdaptivePopup/index.tsx +19 -19
  70. package/src/Button/Button.outlinedAccentInk.spec.tsx +152 -0
  71. package/src/Button/index.tsx +18 -7
  72. package/src/Chip/index.tsx +9 -4
  73. package/src/ContextualSaveBar/UnsavedChangesDialog.spec.tsx +50 -3
  74. package/src/ContextualSaveBar/UnsavedChangesDialog.tsx +26 -2
  75. package/src/fields/Geolocation/index.tsx +3 -1
  76. package/src/shared/focusManagement.ts +40 -1
  77. package/types/AdaptivePopup/index.d.ts.map +1 -1
  78. package/types/Button/index.d.ts.map +1 -1
  79. package/types/Chip/index.d.ts +1 -1
  80. package/types/Chip/index.d.ts.map +1 -1
  81. package/types/ContextualSaveBar/UnsavedChangesDialog.d.ts.map +1 -1
  82. package/types/fields/Checkbox/index.d.ts +3 -3
  83. package/types/fields/Geolocation/index.d.ts.map +1 -1
  84. package/types/fields/RadioGroup/index.d.ts +2 -2
  85. package/types/fields/ToggleGroup/index.d.ts +1 -1
  86. package/types/shared/focusManagement.d.ts +19 -0
  87. package/types/shared/focusManagement.d.ts.map +1 -1
@@ -1,5 +1,5 @@
1
1
  import { useEffect, useRef } from "react";
2
- import { isWeb } from "tamagui";
2
+ import { isWeb, useDialogContext } from "tamagui";
3
3
  import { wasKeyboardFocus } from "@multiplatform.one/theme";
4
4
  const FOCUSABLE = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
5
5
  const canUseDom = () => isWeb && typeof document !== "undefined";
@@ -103,5 +103,31 @@ function useSheetModalFocus(open, frameRef, skipReturnFocusRef) {
103
103
  };
104
104
  }, [open, frameRef, prevRef, generationRef, skipReturnFocusRef]);
105
105
  }
106
- export { useReturnFocusOnClose, useSheetModalFocus };
106
+ const DIALOG_SHOW_FOCUS_EVENT = "mp.dialogShowFocus";
107
+ function useDialogShowFocus(onOpenAutoFocus) {
108
+ const {
109
+ open,
110
+ contentId
111
+ } = useDialogContext();
112
+ useEffect(() => {
113
+ if (!open || !contentId || !canUseDom()) return;
114
+ const content = document.getElementById(contentId);
115
+ const focused = document.activeElement;
116
+ if (!content || !(focused instanceof HTMLElement)) return;
117
+ if (!content.contains(focused) || focused.tabIndex >= 0) return;
118
+ content.addEventListener(DIALOG_SHOW_FOCUS_EVENT, onOpenAutoFocus, {
119
+ once: true
120
+ });
121
+ content.dispatchEvent(new CustomEvent(DIALOG_SHOW_FOCUS_EVENT, {
122
+ cancelable: true
123
+ }));
124
+ }, [open, contentId]);
125
+ }
126
+ function DialogShowFocus({
127
+ onOpenAutoFocus
128
+ }) {
129
+ useDialogShowFocus(onOpenAutoFocus);
130
+ return null;
131
+ }
132
+ export { DialogShowFocus, useDialogShowFocus, useReturnFocusOnClose, useSheetModalFocus };
107
133
  //# sourceMappingURL=focusManagement.mjs.map
@@ -1 +1 @@
1
- {"version":3,"names":["useEffect","useRef","isWeb","wasKeyboardFocus","FOCUSABLE","canUseDom","document","focusIsDropped","insideEl","ae","activeElement","body","documentElement","contains","useCaptureOnOpen","open","prevRef","wasOpenRef","generationRef","current","restoreLater","insideRef","skipReturnFocusRef","generation","restore","target","isConnected","focus","preventScroll","focusVisible","requestAnimationFrame","setTimeout","useReturnFocusOnClose","useSheetModalFocus","frameRef","frame","addEventListener","focusIn","first","querySelector","innerRaf","raf","onKeyDown","e","key","focusables","Array","from","querySelectorAll","filter","el","offsetWidth","offsetHeight","length","preventDefault","last","shiftKey","cancelAnimationFrame","removeEventListener"],"sources":["../../../src/shared/focusManagement.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["useEffect","useRef","isWeb","useDialogContext","wasKeyboardFocus","FOCUSABLE","canUseDom","document","focusIsDropped","insideEl","ae","activeElement","body","documentElement","contains","useCaptureOnOpen","open","prevRef","wasOpenRef","generationRef","current","restoreLater","insideRef","skipReturnFocusRef","generation","restore","target","isConnected","focus","preventScroll","focusVisible","requestAnimationFrame","setTimeout","useReturnFocusOnClose","useSheetModalFocus","frameRef","frame","addEventListener","focusIn","first","querySelector","innerRaf","raf","onKeyDown","e","key","focusables","Array","from","querySelectorAll","filter","el","offsetWidth","offsetHeight","length","preventDefault","last","shiftKey","cancelAnimationFrame","removeEventListener","DIALOG_SHOW_FOCUS_EVENT","useDialogShowFocus","onOpenAutoFocus","contentId","content","getElementById","focused","HTMLElement","tabIndex","once","dispatchEvent","CustomEvent","cancelable","DialogShowFocus"],"sources":["../../../src/shared/focusManagement.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
@@ -24,6 +24,8 @@ var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
24
24
  }), mod);
25
25
  var focusManagement_exports = {};
26
26
  __export(focusManagement_exports, {
27
+ DialogShowFocus: () => DialogShowFocus,
28
+ useDialogShowFocus: () => useDialogShowFocus,
27
29
  useReturnFocusOnClose: () => useReturnFocusOnClose,
28
30
  useSheetModalFocus: () => useSheetModalFocus
29
31
  });
@@ -31,6 +33,15 @@ module.exports = __toCommonJS(focusManagement_exports);
31
33
  var import_react = require("react");
32
34
  var import_tamagui = require("tamagui");
33
35
  var import_theme = require("@multiplatform.one/theme");
36
+ function _instanceof(left, right) {
37
+ "@swc/helpers - instanceof";
38
+
39
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
40
+ return !!right[Symbol.hasInstance](left);
41
+ } else {
42
+ return left instanceof right;
43
+ }
44
+ }
34
45
  var FOCUSABLE = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
35
46
  var canUseDom = function canUseDom2() {
36
47
  return import_tamagui.isWeb && typeof document !== "undefined";
@@ -144,4 +155,31 @@ function useSheetModalFocus(open, frameRef, skipReturnFocusRef) {
144
155
  };
145
156
  }, [open, frameRef, prevRef, generationRef, skipReturnFocusRef]);
146
157
  }
158
+ var DIALOG_SHOW_FOCUS_EVENT = "mp.dialogShowFocus";
159
+ function useDialogShowFocus(onOpenAutoFocus) {
160
+ var {
161
+ open,
162
+ contentId
163
+ } = (0, import_tamagui.useDialogContext)();
164
+ (0, import_react.useEffect)(function () {
165
+ if (!open || !contentId || !canUseDom()) return;
166
+ var content = document.getElementById(contentId);
167
+ var focused = document.activeElement;
168
+ if (!content || !_instanceof(focused, HTMLElement)) return;
169
+ if (!content.contains(focused) || focused.tabIndex >= 0) return;
170
+ content.addEventListener(DIALOG_SHOW_FOCUS_EVENT, onOpenAutoFocus, {
171
+ once: true
172
+ });
173
+ content.dispatchEvent(new CustomEvent(DIALOG_SHOW_FOCUS_EVENT, {
174
+ cancelable: true
175
+ }));
176
+ }, [open, contentId]);
177
+ }
178
+ function DialogShowFocus(param) {
179
+ var {
180
+ onOpenAutoFocus
181
+ } = param;
182
+ useDialogShowFocus(onOpenAutoFocus);
183
+ return null;
184
+ }
147
185
  //# sourceMappingURL=focusManagement.native.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["__defProp","Object","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","from","except","desc","key","call","__toCommonJS","mod","value","focusManagement_exports","useReturnFocusOnClose","useSheetModalFocus","module","exports","import_react","require","import_tamagui","import_theme","FOCUSABLE","canUseDom","canUseDom2","isWeb","document","focusIsDropped","insideEl","ae","activeElement","body","documentElement","contains","useCaptureOnOpen","open","prevRef","useRef","wasOpenRef","generationRef","current","restoreLater","insideRef","skipReturnFocusRef","generation","restore","restore2","_ref","isConnected","focus","preventScroll","focusVisible","wasKeyboardFocus","requestAnimationFrame","setTimeout","useEffect","frameRef","frame","addEventListener"],"sources":["../../../src/shared/focusManagement.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["__defProp","Object","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","from","except","desc","key","call","__toCommonJS","mod","value","focusManagement_exports","DialogShowFocus","useDialogShowFocus","useReturnFocusOnClose","useSheetModalFocus","module","exports","import_react","require","import_tamagui","import_theme","_instanceof","left","right","Symbol","hasInstance","FOCUSABLE","canUseDom","canUseDom2","isWeb","document","focusIsDropped","insideEl","ae","activeElement","body","documentElement","contains","useCaptureOnOpen","open","prevRef","useRef","wasOpenRef","generationRef","current","restoreLater","insideRef","skipReturnFocusRef","generation","restore","restore2","_ref","isConnected","focus","preventScroll","focusVisible","wasKeyboardFocus","requestAnimationFrame","setTimeout","useEffect","frameRef","frame","addEventListener","focusIn","focusIn2","first","querySelector"],"sources":["../../../src/shared/focusManagement.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@multiplatform.one/forms",
3
- "version": "7.28.1",
3
+ "version": "7.29.0",
4
4
  "description": "Cross-platform form components with URL state management",
5
5
  "keywords": [
6
6
  "cross-platform",
@@ -57,10 +57,10 @@
57
57
  },
58
58
  "dependencies": {
59
59
  "@floating-ui/react": "^0.27.19",
60
- "@multiplatform.one/platform": "7.28.1",
61
- "@multiplatform.one/router": "7.28.1",
62
- "@multiplatform.one/table-primitives": "7.28.1",
63
- "@multiplatform.one/theme": "7.28.1",
60
+ "@multiplatform.one/platform": "7.29.0",
61
+ "@multiplatform.one/router": "7.29.0",
62
+ "@multiplatform.one/table-primitives": "7.29.0",
63
+ "@multiplatform.one/theme": "7.29.0",
64
64
  "@phosphor-icons/react": "^2.1.10",
65
65
  "@tamagui/get-font-sized": "2.7.6",
66
66
  "@tamagui/get-token": "2.7.6",
@@ -79,9 +79,9 @@
79
79
  "tamagui": "2.7.6"
80
80
  },
81
81
  "devDependencies": {
82
- "@multiplatform.one/config": "7.28.1",
83
- "@multiplatform.one/storybook": "7.28.1",
84
- "@multiplatform.one/test-utils": "7.28.1",
82
+ "@multiplatform.one/config": "7.29.0",
83
+ "@multiplatform.one/storybook": "7.29.0",
84
+ "@multiplatform.one/test-utils": "7.29.0",
85
85
  "@tamagui/build": "2.7.6",
86
86
  "@tamagui/config": "2.7.6",
87
87
  "@tamagui/vite-plugin": "2.7.6",
@@ -1,10 +1,11 @@
1
1
  import { afterEach, beforeEach, describe, expect, it } from "vitest";
2
2
  import { fireEvent, waitFor } from "@testing-library/react";
3
- import { renderWithProviders } from "@multiplatform.one/test-utils";
3
+ import { modelFirstFocusableShow, renderWithProviders } from "@multiplatform.one/test-utils";
4
4
  import { OVERLAY_BREAKPOINT } from "@multiplatform.one/theme";
5
5
  import { useState, type ReactNode } from "react";
6
6
  import { Text } from "tamagui";
7
7
  import { Button } from "../Button";
8
+ import { Input } from "../fields/Input";
8
9
  import { AdaptivePopup, pickAdaptivePopupFace } from "./index";
9
10
 
10
11
  /**
@@ -418,3 +419,45 @@ describe("AdaptivePopup drawer contract (LC-48 / DG-OVL-01 / overlay ground)", (
418
419
  expect(surface()?.getAttribute("data-drawer-attached-radius")).toBe("0");
419
420
  });
420
421
  });
422
+
423
+ // MPO-470: in Chromium and WebKit, <dialog>.show() focuses the first focusable
424
+ // descendant, which here is the tabindex=-1 surface itself (Firefox and the HTML
425
+ // spec take the first tab stop). FocusScope then saw focus inside and never ran
426
+ // the popup's field focus, so typing right after open went nowhere. jsdom has
427
+ // no show(), so modelFirstFocusableShow stands in for Chromium's.
428
+
429
+ describe("AdaptivePopup open focus behind <dialog>.show() (MPO-470)", () => {
430
+ let restoreShow = () => {};
431
+ beforeEach(() => {
432
+ setViewportWidth(1440);
433
+ restoreShow = modelFirstFocusableShow();
434
+ });
435
+ afterEach(() => restoreShow());
436
+
437
+ function FieldPopup({ face }: { face: "dialog" | "drawer" }) {
438
+ const [open, setOpen] = useState(false);
439
+ return (
440
+ <AdaptivePopup
441
+ open={open}
442
+ onOpenChange={setOpen}
443
+ face={face}
444
+ title="Edit Profile"
445
+ trigger={<Button>Open Popup</Button>}
446
+ >
447
+ <Input inputProps={{ "aria-label": "Name" }} />
448
+ </AdaptivePopup>
449
+ );
450
+ }
451
+
452
+ it.each(["dialog", "drawer"] as const)(
453
+ "%s: moves focus off the surface onto the first field",
454
+ async (face) => {
455
+ const result = renderWithProviders(<FieldPopup face={face} />);
456
+ press(result.container.querySelector("[role='button']") as Element);
457
+ await waitFor(() => expect(surface()?.getAttribute("data-adaptive-popup-mode")).toBe(face));
458
+ const field = document.querySelector("input[aria-label='Name']");
459
+ expect(field).not.toBeNull();
460
+ await waitFor(() => expect(document.activeElement).toBe(field));
461
+ },
462
+ );
463
+ });
@@ -17,7 +17,11 @@ import {
17
17
  } from "tamagui";
18
18
  import { X } from "@tamagui/lucide-icons-2";
19
19
  import { formCommonColors } from "../shared/colorRamps";
20
- import { useReturnFocusOnClose, useSheetModalFocus } from "../shared/focusManagement";
20
+ import {
21
+ DialogShowFocus,
22
+ useReturnFocusOnClose,
23
+ useSheetModalFocus,
24
+ } from "../shared/focusManagement";
21
25
  import { useSheetEscapeDismiss } from "../shared/useSheetEscapeDismiss";
22
26
  import { zIndex } from "../shared/zIndex";
23
27
  import { useViewportGtSm } from "../FloatingPanel";
@@ -158,6 +162,16 @@ function PopupCloseButton({ onPress }: { onPress: () => void }) {
158
162
  );
159
163
  }
160
164
 
165
+ function focusFirstField(event: Event) {
166
+ const root = event.currentTarget as HTMLElement | null;
167
+ const field = root?.querySelector<HTMLElement>(
168
+ "input, textarea, select, [contenteditable='true']",
169
+ );
170
+ if (!field) return;
171
+ event.preventDefault();
172
+ field.focus({ preventScroll: true });
173
+ }
174
+
161
175
  export function AdaptivePopup({
162
176
  open,
163
177
  onOpenChange,
@@ -398,15 +412,7 @@ export function AdaptivePopup({
398
412
  enterStyle={{ opacity: 0, x: slideFromEnd }}
399
413
  exitStyle={{ opacity: 0, x: slideFromEnd }}
400
414
  {...knobProps.panelPadding}
401
- onOpenAutoFocus={(event) => {
402
- const root = event.currentTarget as unknown as HTMLElement | null;
403
- const field = root?.querySelector<HTMLElement>(
404
- "input, textarea, select, [contenteditable='true']",
405
- );
406
- if (!field) return;
407
- event.preventDefault();
408
- field.focus({ preventScroll: true });
409
- }}
415
+ onOpenAutoFocus={focusFirstField}
410
416
  onCloseAutoFocus={(event) => {
411
417
  // LC-48: Dialog.Trigger is the wrapper View (tabIndex -1), not
412
418
  // the painted Button. Prevent Radix restoring there so
@@ -415,6 +421,7 @@ export function AdaptivePopup({
415
421
  }}
416
422
  >
417
423
  {body}
424
+ <DialogShowFocus onOpenAutoFocus={focusFirstField} />
418
425
  </Dialog.Content>
419
426
  </Dialog.Portal>
420
427
  </Dialog>
@@ -459,15 +466,7 @@ export function AdaptivePopup({
459
466
  maxHeight={maxHeight}
460
467
  width="90vw"
461
468
  {...knobProps.panelPadding}
462
- onOpenAutoFocus={(event) => {
463
- const root = event.currentTarget as unknown as HTMLElement | null;
464
- const field = root?.querySelector<HTMLElement>(
465
- "input, textarea, select, [contenteditable='true']",
466
- );
467
- if (!field) return;
468
- event.preventDefault();
469
- field.focus({ preventScroll: true });
470
- }}
469
+ onOpenAutoFocus={focusFirstField}
471
470
  onCloseAutoFocus={(event) => {
472
471
  // LC-48: Dialog.Trigger is the wrapper View (tabIndex -1), not
473
472
  // the painted Button. Prevent Radix restoring there so
@@ -476,6 +475,7 @@ export function AdaptivePopup({
476
475
  }}
477
476
  >
478
477
  {body}
478
+ <DialogShowFocus onOpenAutoFocus={focusFirstField} />
479
479
  </Dialog.Content>
480
480
  </Dialog.Portal>
481
481
  </Dialog>
@@ -0,0 +1,152 @@
1
+ /**
2
+ * @vitest-environment jsdom
3
+ *
4
+ * MPO-447: under fillStyle outlined a `theme="accent"` Button (the portal's
5
+ * Sign in) sits on its host with no fill, and its label kept the accent
6
+ * sub-theme's on-fill `$color`, 1.06:1 on the light page. The accent slot is
7
+ * solid by palette shape (defaults/accent.ts), so no step of its own ramp
8
+ * reads on the page in both schemes; MPO-40 re-anchored only the solid
9
+ * intents (error, warning, success) to `$color11`. The label and the frame's
10
+ * `color` (currentColor glyphs) now take the host's readable accent ink.
11
+ *
12
+ * The `accent` intent stays filled under an outlined preset (SB-E-01,
13
+ * intents.ts), so the knob channel only reaches `theme="accent"`; an explicit
14
+ * `outlined` prop reaches both.
15
+ *
16
+ * jsdom cascades no Tamagui CSS, so this reads what the nodes ask for: the
17
+ * atomic `_col-` class, the injected rule behind it, and for a `var(--token)`
18
+ * rule the house theme table of the scope that paints it.
19
+ */
20
+
21
+ import { cleanup, render, screen } from "@testing-library/react";
22
+ import {
23
+ aaTextContrastRatio,
24
+ createDefaultThemeConfig,
25
+ createThemesBuilder,
26
+ defaultAccentTheme,
27
+ defaultBaseTheme,
28
+ defaultBuilderOptions,
29
+ measureContrast,
30
+ Preset,
31
+ } from "@multiplatform.one/theme";
32
+ import type { ReactElement } from "react";
33
+ import { TamaguiProvider, YStack } from "tamagui";
34
+ import { afterEach, describe, expect, it } from "vitest";
35
+ import { Button, type ButtonProps } from "./index";
36
+
37
+ afterEach(cleanup);
38
+
39
+ const houseConfig = createDefaultThemeConfig();
40
+ const houseThemes = createThemesBuilder(
41
+ defaultBaseTheme,
42
+ defaultAccentTheme,
43
+ defaultBuilderOptions,
44
+ ).themes() as Record<string, Record<string, string>>;
45
+
46
+ const SCHEMES = ["light", "dark"] as const;
47
+ type Scheme = (typeof SCHEMES)[number];
48
+ const HOST_SURFACES = ["background", "color1", "color2"] as const;
49
+ const CASES: { name: string; props: Partial<ButtonProps>; knob: boolean }[] = [
50
+ {
51
+ name: 'theme="accent" under the fillStyle outlined knob',
52
+ props: { theme: "accent" },
53
+ knob: true,
54
+ },
55
+ { name: 'theme="accent" outlined', props: { theme: "accent", outlined: true }, knob: false },
56
+ { name: "accent outlined", props: { accent: true, outlined: true }, knob: false },
57
+ ];
58
+
59
+ function houseRender(ui: ReactElement, scheme: Scheme, knob: boolean) {
60
+ const body = <YStack backgroundColor="$background">{ui}</YStack>;
61
+ return render(
62
+ <TamaguiProvider config={houseConfig.tamagui} defaultTheme={scheme} disableInjectCSS>
63
+ {knob ? <Preset overrides={{ fillStyle: "outlined" }}>{body}</Preset> : body}
64
+ </TamaguiProvider>,
65
+ );
66
+ }
67
+
68
+ function injectedRuleValue(className: string, property: string): string {
69
+ for (const sheet of Array.from(document.styleSheets)) {
70
+ for (const rule of Array.from(sheet.cssRules)) {
71
+ if (!(rule instanceof CSSStyleRule)) continue;
72
+ if (!rule.selectorText.endsWith(`.${className}`)) continue;
73
+ const value = rule.style.getPropertyValue(property);
74
+ if (value) return value.trim();
75
+ }
76
+ }
77
+ throw new Error(`no injected ${property} rule for .${className}`);
78
+ }
79
+
80
+ /** The innermost Tamagui theme scope painting `el`, e.g. `accent_Button`. */
81
+ function scopeOf(el: Element): string | null {
82
+ for (let node: Element | null = el; node; node = node.parentElement) {
83
+ const names = Array.from(node.classList)
84
+ .filter((c) => c.startsWith("t_") && c !== "t_sub_theme")
85
+ .map((c) => c.slice(2))
86
+ .filter((c) => c !== "light" && c !== "dark");
87
+ if (names.length) return names.sort((a, b) => b.length - a.length)[0];
88
+ }
89
+ return null;
90
+ }
91
+
92
+ function resolveInScope(value: string, scheme: Scheme, scope: string | null): string {
93
+ const token = value.match(/^var\(--([\w-]+)\)$/)?.[1];
94
+ if (!token) return value;
95
+ const chain: string[] = [];
96
+ if (scope) {
97
+ const parts = scope.split("_");
98
+ for (let i = parts.length; i > 0; i--) chain.push(`${scheme}_${parts.slice(0, i).join("_")}`);
99
+ }
100
+ chain.push(scheme);
101
+ for (const name of chain) {
102
+ const hit = houseThemes[name]?.[token];
103
+ if (hit) return hit;
104
+ }
105
+ throw new Error(`--${token} resolves in none of ${chain.join(", ")}`);
106
+ }
107
+
108
+ function paintedColor(el: Element, scheme: Scheme): string {
109
+ const cls = Array.from(el.classList).find(
110
+ (c) => c.startsWith("_col-") && !/^_col-0(hover|active|focus|press)/.test(c),
111
+ );
112
+ if (!cls) throw new Error(`${el.tagName} carries no _col- class`);
113
+ return resolveInScope(injectedRuleValue(cls, "color"), scheme, scopeOf(el));
114
+ }
115
+
116
+ describe("MPO-447: an outlined accent Button's label reads on its host", () => {
117
+ for (const scheme of SCHEMES) {
118
+ for (const c of CASES) {
119
+ it(`${scheme} ${c.name}: label and glyph ink clear 4.5:1 on every host surface`, () => {
120
+ houseRender(<Button {...c.props}>Sign in</Button>, scheme, c.knob);
121
+ const label = screen.getByText("Sign in");
122
+ const frame = label.closest("[role=button]") as Element;
123
+ for (const [part, el] of [
124
+ ["label", label],
125
+ ["frame", frame],
126
+ ] as const) {
127
+ const ink = paintedColor(el, scheme);
128
+ for (const surface of HOST_SURFACES) {
129
+ const ground = houseThemes[scheme][surface];
130
+ const ratio = measureContrast({ foreground: ink, background: ground }).ratio;
131
+ expect(
132
+ ratio,
133
+ `${part} ${ink} on ${scheme}.${surface} ${ground}: ${ratio.toFixed(2)}:1`,
134
+ ).toBeGreaterThanOrEqual(aaTextContrastRatio);
135
+ }
136
+ }
137
+ });
138
+ }
139
+ }
140
+
141
+ for (const scheme of SCHEMES) {
142
+ for (const c of [
143
+ { name: 'theme="accent"', props: { theme: "accent" }, knob: false },
144
+ { name: "accent under the fillStyle outlined knob", props: { accent: true }, knob: true },
145
+ ] as const) {
146
+ it(`${scheme}: a filled ${c.name} Button keeps its on-fill label`, () => {
147
+ houseRender(<Button {...c.props}>Filled</Button>, scheme, c.knob);
148
+ expect(screen.getByText("Filled").className).toMatch(/_col-color\b/);
149
+ });
150
+ }
151
+ }
152
+ });
@@ -21,6 +21,7 @@ import {
21
21
  sizeRecipeFromHeight,
22
22
  solidButtonIntents,
23
23
  solidPaletteThemes,
24
+ useAccentOnSurface,
24
25
  useResolvedKnobs,
25
26
  type RecipeFamilyName,
26
27
  type SizeRecipe,
@@ -427,6 +428,7 @@ export function Button({
427
428
  // page-scope `$outlineColor` literal (DG-A11Y-01; see focusVisibleStyle).
428
429
  const parentScopeTheme = useTheme();
429
430
  const pageOutlineColor = parentScopeTheme.outlineColor?.val as string | undefined;
431
+ const hostAccentInk = useAccentOnSurface();
430
432
  const grouped = useControlGrouped();
431
433
  const sizeProp = (props as { size?: SizeTokens | number }).size;
432
434
  const resolvedSize = sizeProp ?? knobProps.sizeToken;
@@ -540,7 +542,16 @@ export function Button({
540
542
  // (measured 1.02–1.06:1 on the page in both schemes). At the default
541
543
  // textAccent (`high`, textColor undefined) the label must re-anchor to the
542
544
  // same readable text tier the frame uses.
543
- const outlinedIntentInk = Boolean(outlined && intent && solidButtonIntents.has(intent));
545
+ const outlinedIntentInk = Boolean(
546
+ outlined && activeThemeName && solidButtonIntents.has(activeThemeName),
547
+ );
548
+ // MPO-447: a solid-palette theme (accent) has no readable-on-page step at
549
+ // all, `$color11` included, so an outlined one takes its ink from the host:
550
+ // the accent that clears AA there, or host-scoped text under a textAccent.
551
+ const outlinedOnHost = Boolean(
552
+ outlined && activeThemeName && solidPaletteThemes.has(activeThemeName),
553
+ );
554
+ const outlinedInk = outlinedOnHost ? hostAccentInk : outlinedIntentInk ? "$color11" : undefined;
544
555
 
545
556
  const resolvedRole: ButtonActionRole | undefined = actionRole ?? (accent ? "primary" : undefined);
546
557
  const labelFromParts =
@@ -568,9 +579,11 @@ export function Button({
568
579
  {...knobProps.body}
569
580
  {...(nested ? knobProps.label : { fontSize: recipe.fontSize })}
570
581
  {...(textColor
571
- ? { color: textColor }
572
- : outlinedIntentInk
573
- ? { color: "$color11" }
582
+ ? outlinedOnHost
583
+ ? hostScoped({ color: textColor })
584
+ : { color: textColor }
585
+ : outlinedInk
586
+ ? { color: outlinedInk }
574
587
  : undefined)}
575
588
  // LC-40: on the washed disabled chrome the label leaves the on-fill
576
589
  // foreground for the wash's AA ink (keepLabel keeps >=4.5:1).
@@ -719,9 +732,7 @@ export function Button({
719
732
  // Solid-intent sub-themes carry the on-fill foreground as `$color`
720
733
  // (LC-05); outlined frames sit on the page, so re-anchor inherited
721
734
  // text/icon color (currentColor) to the hue's readable text tier.
722
- {...(outlined && intent && solidButtonIntents.has(intent)
723
- ? { color: "$color11" }
724
- : undefined)}
735
+ {...(outlinedInk ? { color: outlinedInk } : undefined)}
725
736
  // LC-40 DISABLED-VISIBLE: keepLabel washes the chrome (muted fill/
726
737
  // border) while label/glyphs re-anchor to the lowest AA text tier
727
738
  // (`color` inherits into currentColor icons); dimWhole dims the
@@ -10,6 +10,7 @@ import {
10
10
  resolveRadiusClass,
11
11
  sizeRecipeForToken,
12
12
  stackRadiusProps,
13
+ useLegibleInkOn,
13
14
  useResolvedKnobs,
14
15
  type GroupOrientation,
15
16
  type GroupPosition,
@@ -416,7 +417,10 @@ export function Chip({
416
417
  }
417
418
  };
418
419
 
419
- const textColor = colors.text;
420
+ // Selected paints the family's step 8, where step-12 ink misses AA in dark
421
+ // (#c2e6ff on #2870bd, 3.88:1); the fill keeps its ink only while it reads.
422
+ const selectedInk = useLegibleInkOn(colors.fill, colors.text);
423
+ const textColor = (selected ? selectedInk : colors.text) as ColorTokens;
420
424
  const borderColor = selected
421
425
  ? "transparent"
422
426
  : variant === "outline"
@@ -434,9 +438,10 @@ export function Chip({
434
438
  // 1.32:1 on the dark tint — the "invisible ✕" regression). useTheme gives
435
439
  // the scheme-aware value for the same step-12 ink the label uses.
436
440
  const theme = useTheme();
437
- const glyphInk =
438
- (theme as Record<string, { val?: string } | undefined>)[(textColor as string).replace("$", "")]
439
- ?.val ?? "currentColor";
441
+ const glyphInk = (textColor as string).startsWith("$")
442
+ ? ((theme as Record<string, { val?: string } | undefined>)[(textColor as string).slice(1)]
443
+ ?.val ?? "currentColor")
444
+ : (textColor as string);
440
445
  // Undifferentiated "Remove" fails when a row holds many chips (UX-019);
441
446
  // interpolate the label whenever it is a plain string.
442
447
  const dismissLabel =
@@ -7,9 +7,10 @@
7
7
  * outside click from dismissing a destructive confirm. Those are the parts a
8
8
  * refactor of the save bar would carry away without noticing.
9
9
  */
10
- import { cleanup, fireEvent } from "@testing-library/react";
11
- import { renderWithProviders } from "@multiplatform.one/test-utils";
12
- import { afterEach, describe, expect, it, vi } from "vitest";
10
+ import { cleanup, fireEvent, screen, waitFor } from "@testing-library/react";
11
+ import { modelFirstFocusableShow, renderWithProviders } from "@multiplatform.one/test-utils";
12
+ import { useState } from "react";
13
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
13
14
  import { UnsavedChangesDialog } from "./UnsavedChangesDialog";
14
15
 
15
16
  afterEach(cleanup);
@@ -165,3 +166,49 @@ describe("UnsavedChangesDialog", () => {
165
166
  expect(cssOf(dialog() as HTMLElement, "max-width")).toBe("440px");
166
167
  });
167
168
  });
169
+
170
+ // MPO-472: Chromium and WebKit's <dialog>.show() focuses the first focusable
171
+ // descendant, and the panel is tabindex=-1, so those two opened on the panel
172
+ // while Firefox and the HTML spec open on Keep editing, the first tab stop.
173
+ // Keep editing is the alertdialog's least destructive action, the one tamagui's
174
+ // AlertDialog.Cancel takes on open, so every browser opens there.
175
+ describe("UnsavedChangesDialog open focus", () => {
176
+ function LeavePage() {
177
+ const [open, setOpen] = useState(false);
178
+ return (
179
+ <>
180
+ <button type="button" onClick={() => setOpen(true)}>
181
+ Leave the page
182
+ </button>
183
+ <UnsavedChangesDialog
184
+ open={open}
185
+ fieldCount={2}
186
+ onKeepEditing={() => setOpen(false)}
187
+ onDiscard={() => setOpen(false)}
188
+ />
189
+ </>
190
+ );
191
+ }
192
+
193
+ it("opens on Keep editing", async () => {
194
+ renderWithProviders(<LeavePage />);
195
+ fireEvent.click(screen.getByRole("button", { name: "Leave the page" }));
196
+ await waitFor(() => expect(dialog()).not.toBeNull());
197
+ await waitFor(() => expect(document.activeElement).toBe(button("data-mp-savebar-keep")));
198
+ });
199
+
200
+ describe("behind <dialog>.show()", () => {
201
+ let restoreShow = () => {};
202
+ beforeEach(() => {
203
+ restoreShow = modelFirstFocusableShow();
204
+ });
205
+ afterEach(() => restoreShow());
206
+
207
+ it("moves focus off the panel onto Keep editing", async () => {
208
+ renderWithProviders(<LeavePage />);
209
+ fireEvent.click(screen.getByRole("button", { name: "Leave the page" }));
210
+ await waitFor(() => expect(dialog()).not.toBeNull());
211
+ await waitFor(() => expect(document.activeElement).toBe(button("data-mp-savebar-keep")));
212
+ });
213
+ });
214
+ });