@multiplatform.one/forms 7.28.0 → 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 (90) 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 +32 -22
  5. package/dist/cjs/Button/index.native.js +40 -23
  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 +33 -23
  24. package/dist/esm/Button/index.mjs.map +1 -1
  25. package/dist/esm/Button/index.native.js +41 -24
  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 +33 -23
  48. package/dist/jsx/Button/index.mjs.map +1 -1
  49. package/dist/jsx/Button/index.native.js +40 -23
  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.disabledReasonInk.spec.tsx +134 -0
  71. package/src/Button/Button.disabledWash.spec.tsx +206 -0
  72. package/src/Button/Button.outlinedAccentInk.spec.tsx +152 -0
  73. package/src/Button/Button.stories.tsx +22 -6
  74. package/src/Button/index.tsx +70 -31
  75. package/src/Chip/index.tsx +9 -4
  76. package/src/ContextualSaveBar/UnsavedChangesDialog.spec.tsx +50 -3
  77. package/src/ContextualSaveBar/UnsavedChangesDialog.tsx +26 -2
  78. package/src/fields/Geolocation/index.tsx +3 -1
  79. package/src/shared/focusManagement.ts +40 -1
  80. package/types/AdaptivePopup/index.d.ts.map +1 -1
  81. package/types/Button/index.d.ts.map +1 -1
  82. package/types/Chip/index.d.ts +1 -1
  83. package/types/Chip/index.d.ts.map +1 -1
  84. package/types/ContextualSaveBar/UnsavedChangesDialog.d.ts.map +1 -1
  85. package/types/fields/Checkbox/index.d.ts +3 -3
  86. package/types/fields/Geolocation/index.d.ts.map +1 -1
  87. package/types/fields/RadioGroup/index.d.ts +2 -2
  88. package/types/fields/ToggleGroup/index.d.ts +1 -1
  89. package/types/shared/focusManagement.d.ts +19 -0
  90. package/types/shared/focusManagement.d.ts.map +1 -1
@@ -7,7 +7,7 @@ import {
7
7
  ensureFocusVisibleRing,
8
8
  } from "@multiplatform.one/theme";
9
9
  import { Button as TamaguiButton, Paragraph, XStack, YStack, useTheme } from "tamagui";
10
- import { Button } from "./index";
10
+ import { Button, type ButtonProps } from "./index";
11
11
  import { useState } from "react";
12
12
 
13
13
  const pressed = (name: string) => () => action(name)();
@@ -45,23 +45,39 @@ const meta: Meta<typeof Button> = {
45
45
  export default meta;
46
46
  type Story = StoryObj<typeof Button>;
47
47
 
48
- function DestructiveContrastExample({ disabled = false }: { disabled?: boolean }) {
48
+ function ContrastExample({ children = "Save", ...props }: ButtonProps) {
49
49
  const [presses, setPresses] = useState(0);
50
50
  return (
51
51
  <YStack data-lc-clicks={presses}>
52
- <Button error disabled={disabled} onPress={() => setPresses((value) => value + 1)}>
53
- Delete
52
+ <Button {...props} onPress={() => setPresses((value) => value + 1)}>
53
+ {children}
54
54
  </Button>
55
55
  </YStack>
56
56
  );
57
57
  }
58
58
 
59
59
  export const DestructiveEnabled: Story = {
60
- render: () => <DestructiveContrastExample />,
60
+ render: () => <ContrastExample error>Delete</ContrastExample>,
61
61
  };
62
62
 
63
63
  export const DestructiveDisabled: Story = {
64
- render: () => <DestructiveContrastExample disabled />,
64
+ render: () => (
65
+ <ContrastExample error disabled>
66
+ Delete
67
+ </ContrastExample>
68
+ ),
69
+ };
70
+
71
+ /** LC-40 sweeps each intent through args, enabled and disabled (MPO-433). */
72
+ export const IntentContrast: Story = {
73
+ argTypes: {
74
+ accent: { control: "boolean" },
75
+ warning: { control: "boolean" },
76
+ success: { control: "boolean" },
77
+ theme: { control: "text" },
78
+ disabled: { control: "boolean" },
79
+ },
80
+ render: (args) => <ContrastExample {...args} />,
65
81
  };
66
82
 
67
83
  export const Basic: Story = {
@@ -20,6 +20,8 @@ import {
20
20
  sizeRecipeForToken,
21
21
  sizeRecipeFromHeight,
22
22
  solidButtonIntents,
23
+ solidPaletteThemes,
24
+ useAccentOnSurface,
23
25
  useResolvedKnobs,
24
26
  type RecipeFamilyName,
25
27
  type SizeRecipe,
@@ -426,6 +428,7 @@ export function Button({
426
428
  // page-scope `$outlineColor` literal (DG-A11Y-01; see focusVisibleStyle).
427
429
  const parentScopeTheme = useTheme();
428
430
  const pageOutlineColor = parentScopeTheme.outlineColor?.val as string | undefined;
431
+ const hostAccentInk = useAccentOnSurface();
429
432
  const grouped = useControlGrouped();
430
433
  const sizeProp = (props as { size?: SizeTokens | number }).size;
431
434
  const resolvedSize = sizeProp ?? knobProps.sizeToken;
@@ -484,6 +487,32 @@ export function Button({
484
487
  };
485
488
 
486
489
  const activeThemeName = theme ?? intent;
490
+ const hostScoped = <T extends object>(fragment: T): T =>
491
+ Object.fromEntries(
492
+ Object.entries(fragment).map(([key, value]) => [
493
+ key,
494
+ typeof value === "string" && value.startsWith("$")
495
+ ? (parentScopeTheme[value.slice(1) as keyof typeof parentScopeTheme]?.val ?? value)
496
+ : value,
497
+ ]),
498
+ ) as T;
499
+ // LC-40 / MPO-433: a solid-palette theme has no wash tier, so the wash and
500
+ // its ink come from the host scope. Solid-intent ramps keep their own wash,
501
+ // where `$color11` misses 4.5:1 (light warning 4.48, success 4.27) and the
502
+ // hue's `$color12` text step clears it.
503
+ const washOnHost = Boolean(
504
+ isDisabled && activeThemeName && solidPaletteThemes.has(activeThemeName),
505
+ );
506
+ const disabledSurface = washOnHost
507
+ ? hostScoped(disabledState.surfaceKnobProps)
508
+ : disabledState.surfaceKnobProps;
509
+ const disabledText = washOnHost
510
+ ? hostScoped(disabledState.textKnobProps)
511
+ : activeThemeName &&
512
+ solidButtonIntents.has(activeThemeName) &&
513
+ disabledState.textKnobProps.color
514
+ ? { ...disabledState.textKnobProps, color: "$color12" }
515
+ : disabledState.textKnobProps;
487
516
  outlined = outlined ?? knobProps.outlined;
488
517
  const isLow = knobProps.textAccent === "low";
489
518
  const isMedium = knobProps.textAccent === "medium";
@@ -513,7 +542,16 @@ export function Button({
513
542
  // (measured 1.02–1.06:1 on the page in both schemes). At the default
514
543
  // textAccent (`high`, textColor undefined) the label must re-anchor to the
515
544
  // same readable text tier the frame uses.
516
- 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;
517
555
 
518
556
  const resolvedRole: ButtonActionRole | undefined = actionRole ?? (accent ? "primary" : undefined);
519
557
  const labelFromParts =
@@ -541,13 +579,15 @@ export function Button({
541
579
  {...knobProps.body}
542
580
  {...(nested ? knobProps.label : { fontSize: recipe.fontSize })}
543
581
  {...(textColor
544
- ? { color: textColor }
545
- : outlinedIntentInk
546
- ? { color: "$color11" }
582
+ ? outlinedOnHost
583
+ ? hostScoped({ color: textColor })
584
+ : { color: textColor }
585
+ : outlinedInk
586
+ ? { color: outlinedInk }
547
587
  : undefined)}
548
588
  // LC-40: on the washed disabled chrome the label leaves the on-fill
549
- // foreground and pins to the lowest AA tier (keepLabel keeps >=4.5:1).
550
- {...(isDisabled ? disabledState.textKnobProps : undefined)}
589
+ // foreground for the wash's AA ink (keepLabel keeps >=4.5:1).
590
+ {...(isDisabled ? disabledText : undefined)}
551
591
  // Boards measure ink.weight on the TEXT NODE, never the frame. The
552
592
  // prop is restated after the spreads because SizableText's size
553
593
  // variant otherwise leaks 500/600 over it (MPO-125: a literal 400
@@ -692,9 +732,7 @@ export function Button({
692
732
  // Solid-intent sub-themes carry the on-fill foreground as `$color`
693
733
  // (LC-05); outlined frames sit on the page, so re-anchor inherited
694
734
  // text/icon color (currentColor) to the hue's readable text tier.
695
- {...(outlined && intent && solidButtonIntents.has(intent)
696
- ? { color: "$color11" }
697
- : undefined)}
735
+ {...(outlinedInk ? { color: outlinedInk } : undefined)}
698
736
  // LC-40 DISABLED-VISIBLE: keepLabel washes the chrome (muted fill/
699
737
  // border) while label/glyphs re-anchor to the lowest AA text tier
700
738
  // (`color` inherits into currentColor icons); dimWhole dims the
@@ -702,8 +740,8 @@ export function Button({
702
740
  // whole-dim that dropped label contrast under AA.
703
741
  {...(isDisabled
704
742
  ? {
705
- ...disabledState.surfaceKnobProps,
706
- ...disabledState.textKnobProps,
743
+ ...disabledSurface,
744
+ ...disabledText,
707
745
  ...disabledState.assemblyKnobProps,
708
746
  }
709
747
  : undefined)}
@@ -784,11 +822,11 @@ export function Button({
784
822
  // control must not light up like a pressable one.
785
823
  hoverStyle: {
786
824
  backgroundColor: outlined ? "transparent" : "$background",
787
- ...disabledState.surfaceKnobProps,
825
+ ...disabledSurface,
788
826
  },
789
827
  pressStyle: {
790
828
  backgroundColor: outlined ? "transparent" : "$background",
791
- ...disabledState.surfaceKnobProps,
829
+ ...disabledSurface,
792
830
  },
793
831
  "data-mp-disabled-explained": "true",
794
832
  }
@@ -814,11 +852,20 @@ export function Button({
814
852
  </ButtonFrame>
815
853
  );
816
854
 
855
+ const themedButton = activeThemeName ? (
856
+ <Theme name={activeThemeName as ThemeName}>{buttonElement}</Theme>
857
+ ) : (
858
+ buttonElement
859
+ );
860
+
817
861
  // DG-ST-03 explain affordance: visible reason adjacent to the control —
818
862
  // discoverable by pointer, touch, keyboard, and SR (aria-describedby)
819
863
  // without any hover interaction (Axiom 12). "below" stacks (forms);
820
864
  // "inline" keeps toolbar rows on one shared control line, where the
821
865
  // stacked reason wrapped into cramped multi-line type under the button.
866
+ // The reason stays OUTSIDE the intent Theme: it is T-HELPER copy on the
867
+ // host surface, and inside it `$color11` is the intent's on-fill ramp
868
+ // (MPO-431: 1.17:1 on the light page under accent).
822
869
  const reasonText = explainedDisable ? (
823
870
  <SizableText
824
871
  id={reasonId}
@@ -830,26 +877,18 @@ export function Button({
830
877
  {disabledReason}
831
878
  </SizableText>
832
879
  ) : null;
833
- const explainedElement = explainedDisable ? (
834
- disabledReasonPlacement === "inline" ? (
835
- <XStack gap="$2" alignItems="center" flexShrink={1} data-mp-disabled-reason-wrapper="true">
836
- {buttonElement}
837
- {reasonText}
838
- </XStack>
839
- ) : (
840
- <YStack gap="$1" flexShrink={1} data-mp-disabled-reason-wrapper="true">
841
- {buttonElement}
842
- {reasonText}
843
- </YStack>
844
- )
880
+ if (!explainedDisable) return themedButton;
881
+ return disabledReasonPlacement === "inline" ? (
882
+ <XStack gap="$2" alignItems="center" flexShrink={1} data-mp-disabled-reason-wrapper="true">
883
+ {themedButton}
884
+ {reasonText}
885
+ </XStack>
845
886
  ) : (
846
- buttonElement
887
+ <YStack gap="$1" flexShrink={1} data-mp-disabled-reason-wrapper="true">
888
+ {themedButton}
889
+ {reasonText}
890
+ </YStack>
847
891
  );
848
-
849
- if (activeThemeName) {
850
- return <Theme name={activeThemeName as ThemeName}>{explainedElement}</Theme>;
851
- }
852
- return explainedElement;
853
892
  }
854
893
 
855
894
  Button.Icon = TamaguiButton.Icon;
@@ -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
+ });
@@ -1,9 +1,14 @@
1
- import { useResolvedKnobs, warnCancelDisabled } from "@multiplatform.one/theme";
1
+ import {
2
+ ensureKeyboardModalityTracking,
3
+ useResolvedKnobs,
4
+ warnCancelDisabled,
5
+ wasKeyboardFocus,
6
+ } from "@multiplatform.one/theme";
2
7
  import { useEffect } from "react";
3
8
  import { Dialog, Paragraph, XStack } from "tamagui";
4
9
  import { Button } from "../Button";
5
10
  import { formCommonColors } from "../shared/colorRamps";
6
- import { useReturnFocusOnClose } from "../shared/focusManagement";
11
+ import { DialogShowFocus, useReturnFocusOnClose } from "../shared/focusManagement";
7
12
  import { t } from "../shared/t";
8
13
 
9
14
  export interface UnsavedChangesDialogProps {
@@ -13,6 +18,22 @@ export interface UnsavedChangesDialogProps {
13
18
  onDiscard: () => void;
14
19
  }
15
20
 
21
+ /**
22
+ * Opens on Keep editing, the least destructive action, as tamagui's
23
+ * AlertDialog.Cancel does. Without it Chromium and WebKit's `<dialog>.show()`
24
+ * parks focus on the tabIndex -1 panel and Firefox on Keep editing (MPO-472).
25
+ * WebKit's show() also marks the panel :focus-visible, which a plain focus()
26
+ * would carry onto the button after a pointer open; the ring is keyboard-only
27
+ * (LC-71).
28
+ */
29
+ function focusKeepEditing(event: Event) {
30
+ const root = event.currentTarget as HTMLElement | null;
31
+ const keep = root?.querySelector<HTMLElement>("[data-mp-savebar-keep]");
32
+ if (!keep) return;
33
+ event.preventDefault();
34
+ keep.focus({ preventScroll: true, focusVisible: wasKeyboardFocus() } as FocusOptions);
35
+ }
36
+
16
37
  /**
17
38
  * Route-leave / Discard confirm (DG-OVL-02). Lives in forms so ContextualSaveBar
18
39
  * does not import `@multiplatform.one/components` (ConfirmDialog → forms Button
@@ -25,6 +46,7 @@ export function UnsavedChangesDialog({
25
46
  onDiscard,
26
47
  }: UnsavedChangesDialogProps) {
27
48
  const { knobProps } = useResolvedKnobs();
49
+ ensureKeyboardModalityTracking();
28
50
  useReturnFocusOnClose(open);
29
51
 
30
52
  useEffect(() => {
@@ -73,6 +95,7 @@ export function UnsavedChangesDialog({
73
95
  data-mp-savebar-guard=""
74
96
  onPointerDownOutside={(e) => e.preventDefault()}
75
97
  onInteractOutside={(e) => e.preventDefault()}
98
+ onOpenAutoFocus={focusKeepEditing}
76
99
  >
77
100
  <Dialog.Title {...knobProps.body} fontSize="$4">
78
101
  {t("Discard unsaved changes?")}
@@ -103,6 +126,7 @@ export function UnsavedChangesDialog({
103
126
  {t("Discard changes")}
104
127
  </Button>
105
128
  </XStack>
129
+ <DialogShowFocus onOpenAutoFocus={focusKeepEditing} />
106
130
  </Dialog.Content>
107
131
  </Dialog.Portal>
108
132
  </Dialog>
@@ -1420,7 +1420,9 @@ export function Geolocation({
1420
1420
  overflow="hidden"
1421
1421
  style={{ boxShadow: RESULTS_PANEL_SHADOW }}
1422
1422
  >
1423
- <ScrollView maxHeight={mapHeight * 1.5}>{renderResults(handlers)}</ScrollView>
1423
+ <ScrollView keyboardShouldPersistTaps="handled" maxHeight={mapHeight * 1.5}>
1424
+ {renderResults(handlers)}
1425
+ </ScrollView>
1424
1426
  </YStack>
1425
1427
  )
1426
1428
  ) : null;
@@ -15,6 +15,9 @@
15
15
  * focus INTO the sheet frame on open, keeps Tab cycling within it while
16
16
  * open (Tamagui Sheet has no focus scope), and treats focus left inside
17
17
  * the closed (offscreen-parked, still-mounted) frame as dropped.
18
+ * - `useDialogShowFocus(onOpenAutoFocus)` — runs a dialog's open focus when
19
+ * the browser's `<dialog>.show()` left focus on an element that is not a
20
+ * tab stop (MPO-470).
18
21
  *
19
22
  * Capture happens during RENDER, not in an effect: child effects (the Dialog
20
23
  * focus scope) run before parent effects, so an effect-time capture would
@@ -32,7 +35,7 @@
32
35
  */
33
36
 
34
37
  import { useEffect, useRef, type RefObject } from "react";
35
- import { isWeb } from "tamagui";
38
+ import { isWeb, useDialogContext } from "tamagui";
36
39
  import { wasKeyboardFocus } from "@multiplatform.one/theme";
37
40
 
38
41
  const FOCUSABLE =
@@ -164,3 +167,39 @@ export function useSheetModalFocus(
164
167
  };
165
168
  }, [open, frameRef, prevRef, generationRef, skipReturnFocusRef]);
166
169
  }
170
+
171
+ const DIALOG_SHOW_FOCUS_EVENT = "mp.dialogShowFocus";
172
+
173
+ /**
174
+ * Chromium and WebKit's `<dialog>.show()` focuses the first focusable
175
+ * descendant, so a tabIndex -1 surface or field frame takes focus; Firefox and
176
+ * the HTML spec take the first tab stop. Focus is then inside before tamagui's
177
+ * FocusScope checks, and its open auto-focus never fires. When focus sits on
178
+ * something that is not a tab stop, run `onOpenAutoFocus` against the content
179
+ * the way FocusScope would. Call it inside the Dialog. The content is found by
180
+ * its id because FocusScope clones it with its own ref, so a ref passed to
181
+ * `Dialog.Content` never attaches on web. Passive effects run after the
182
+ * portal's layout-effect `show()`, which is why this is not a layout effect.
183
+ */
184
+ export function useDialogShowFocus(onOpenAutoFocus: (event: Event) => void) {
185
+ const { open, contentId } = useDialogContext();
186
+ useEffect(() => {
187
+ if (!open || !contentId || !canUseDom()) return;
188
+ const content = document.getElementById(contentId);
189
+ const focused = document.activeElement;
190
+ if (!content || !(focused instanceof HTMLElement)) return;
191
+ if (!content.contains(focused) || focused.tabIndex >= 0) return;
192
+ content.addEventListener(DIALOG_SHOW_FOCUS_EVENT, onOpenAutoFocus, { once: true });
193
+ content.dispatchEvent(new CustomEvent(DIALOG_SHOW_FOCUS_EVENT, { cancelable: true }));
194
+ }, [open, contentId]);
195
+ }
196
+
197
+ /** `useDialogShowFocus` for a caller that renders the Dialog itself. */
198
+ export function DialogShowFocus({
199
+ onOpenAutoFocus,
200
+ }: {
201
+ onOpenAutoFocus: (event: Event) => void;
202
+ }): null {
203
+ useDialogShowFocus(onOpenAutoFocus);
204
+ return null;
205
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/AdaptivePopup/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAwB5D,MAAM,WAAW,kBAAkB;IACjC,4BAA4B;IAC5B,IAAI,EAAE,OAAO,CAAC;IACd,uCAAuC;IACvC,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,gFAAgF;IAChF,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,gCAAgC;IAChC,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,wCAAwC;IACxC,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,mBAAmB;IACnB,QAAQ,EAAE,SAAS,CAAC;IACpB;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,YAAY,CAAC;IAChD;;;;;OAKG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC3B,sDAAsD;IACtD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,kDAAkD;IAClD,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAkBD,MAAM,MAAM,yBAAyB,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEtE;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE;IAC7C,IAAI,CAAC,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,CAAC,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAClC,aAAa,EAAE,MAAM,CAAC;CACvB,GAAG,yBAAyB,CAK5B;AAmED,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,YAAY,EACZ,OAAO,EACP,KAAK,EACL,WAAW,EACX,QAAQ,EACR,IAAW,EACX,IAAe,EACf,eAAsB,EACtB,MAAM,EACN,QAAQ,GACT,EAAE,kBAAkB,2CAsTpB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/AdaptivePopup/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AA4B5D,MAAM,WAAW,kBAAkB;IACjC,4BAA4B;IAC5B,IAAI,EAAE,OAAO,CAAC;IACd,uCAAuC;IACvC,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,gFAAgF;IAChF,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,gCAAgC;IAChC,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,wCAAwC;IACxC,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,mBAAmB;IACnB,QAAQ,EAAE,SAAS,CAAC;IACpB;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,YAAY,CAAC;IAChD;;;;;OAKG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC3B,sDAAsD;IACtD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,kDAAkD;IAClD,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAkBD,MAAM,MAAM,yBAAyB,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEtE;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE;IAC7C,IAAI,CAAC,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,CAAC,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAClC,aAAa,EAAE,MAAM,CAAC;CACvB,GAAG,yBAAyB,CAK5B;AA6ED,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,YAAY,EACZ,OAAO,EACP,KAAK,EACL,WAAW,EACX,QAAQ,EACR,IAAW,EACX,IAAe,EACf,eAAsB,EACtB,MAAM,EACN,QAAQ,GACT,EAAE,kBAAkB,2CAwSpB"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Button/index.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Button/index.tsx"],"names":[],"mappings":"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"}
@@ -29,7 +29,7 @@ export interface ChipProps {
29
29
  */
30
30
  export declare const ChipFrame: import("tamagui").TamaguiComponent<import("@tamagui/web").TamaDefer, import("tamagui").TamaguiElement, import("@tamagui/core").RNTamaguiViewNonStyleProps, import("@tamagui/web").StackStyleBase, {
31
31
  size?: import("tamagui").SizeTokens | undefined;
32
- variant?: "outline" | "solid" | "subtle" | undefined;
32
+ variant?: "solid" | "outline" | "subtle" | undefined;
33
33
  }, import("@tamagui/web").StaticConfigPublic>;
34
34
  export declare const ChipText: import("tamagui").TamaguiComponent<import("@tamagui/web").TamaDefer, import("tamagui").TamaguiTextElement, import("@tamagui/core").RNTamaguiTextNonStyleProps, import("@tamagui/web").TextStylePropsBase, {
35
35
  size?: import("tamagui").SizeTokens | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Chip/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAC;AAGtD,OAAO,EAUL,KAAK,gBAAgB,EACrB,KAAK,aAAa,EACnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAe,QAAQ,EAAE,MAAM,SAAS,CAAC;AAMrD,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;AACzD,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAC3F,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEjD,gFAAgF;AAChF,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAC;AAE5E,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,SAAS,CAAC;IACpB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,+EAA+E;IAC/E,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,oEAAoE;IACpE,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC;AAqID;;;;GAIG;AACH,eAAO,MAAM,SAAS;;;6CA+BpB,CAAC;AAEH,eAAO,MAAM,QAAQ;;;6CAenB,CAAC;AAiBH,sFAAsF;AACtF,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAEnD;AAED;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAE/C;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE3D;AA2GD,wBAAgB,IAAI,CAAC,EACnB,QAAQ,EACR,IAAI,EACJ,OAAO,EAAE,WAAsB,EAC/B,KAAc,EACd,SAAS,EACT,QAAQ,EACR,QAAgB,EAChB,OAAO,EACP,IAAI,EACJ,aAAa,EACb,gBAA+B,GAChC,EAAE,SAAS,2CAsNX;AAED,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC,OAAO,SAAS,CAAC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Chip/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAC;AAGtD,OAAO,EAWL,KAAK,gBAAgB,EACrB,KAAK,aAAa,EACnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAe,QAAQ,EAAE,MAAM,SAAS,CAAC;AAMrD,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;AACzD,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAC3F,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEjD,gFAAgF;AAChF,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAC;AAE5E,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,SAAS,CAAC;IACpB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,+EAA+E;IAC/E,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,oEAAoE;IACpE,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC;AAqID;;;;GAIG;AACH,eAAO,MAAM,SAAS;;;6CA+BpB,CAAC;AAEH,eAAO,MAAM,QAAQ;;;6CAenB,CAAC;AAiBH,sFAAsF;AACtF,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAEnD;AAED;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAE/C;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE3D;AA2GD,wBAAgB,IAAI,CAAC,EACnB,QAAQ,EACR,IAAI,EACJ,OAAO,EAAE,WAAsB,EAC/B,KAAc,EACd,SAAS,EACT,QAAQ,EACR,QAAgB,EAChB,OAAO,EACP,IAAI,EACJ,aAAa,EACb,gBAA+B,GAChC,EAAE,SAAS,2CA0NX;AAED,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC,OAAO,SAAS,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"UnsavedChangesDialog.d.ts","sourceRoot":"","sources":["../../src/ContextualSaveBar/UnsavedChangesDialog.tsx"],"names":[],"mappings":"AAQA,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,IAAI,EACJ,UAAU,EACV,aAAa,EACb,SAAS,GACV,EAAE,yBAAyB,2CAoF3B"}
1
+ {"version":3,"file":"UnsavedChangesDialog.d.ts","sourceRoot":"","sources":["../../src/ContextualSaveBar/UnsavedChangesDialog.tsx"],"names":[],"mappings":"AAaA,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB;AAkBD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,IAAI,EACJ,UAAU,EACV,aAAa,EACb,SAAS,GACV,EAAE,yBAAyB,2CAuF3B"}