From f2d3953701a5fbb0de980d7a7d81c21aff8faf8c Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Mon, 7 Jul 2025 14:35:51 +1000 Subject: [PATCH 1/2] fix: Focus behaviour on inputs inside a FocusScope --- packages/@react-aria/autocomplete/src/useAutocomplete.ts | 1 + packages/@react-aria/focus/src/FocusScope.tsx | 3 +++ packages/@react-aria/interactions/src/focusSafely.ts | 2 ++ packages/@react-spectrum/s2/stories/Dialog.stories.tsx | 9 ++++++--- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/@react-aria/autocomplete/src/useAutocomplete.ts b/packages/@react-aria/autocomplete/src/useAutocomplete.ts index 6f700db89f3..c0440427200 100644 --- a/packages/@react-aria/autocomplete/src/useAutocomplete.ts +++ b/packages/@react-aria/autocomplete/src/useAutocomplete.ts @@ -91,6 +91,7 @@ export function useAutocomplete(props: AriaAutocompleteOptions, state: Autocompl // Ensure input is focused if the user clicks on the collection directly. if (!e.isTrusted && shouldUseVirtualFocus && inputRef.current && getActiveElement(getOwnerDocument(inputRef.current)) !== inputRef.current) { inputRef.current.focus(); + inputRef.current.select?.(); } let target = e.target as Element | null; diff --git a/packages/@react-aria/focus/src/FocusScope.tsx b/packages/@react-aria/focus/src/FocusScope.tsx index 65711ab9728..094b7fa9c2e 100644 --- a/packages/@react-aria/focus/src/FocusScope.tsx +++ b/packages/@react-aria/focus/src/FocusScope.tsx @@ -353,6 +353,7 @@ function useFocusContainment(scopeRef: RefObject, contain?: bo // restore focus to the previously focused node or the first tabbable element in the active scope. if (focusedNode.current) { focusedNode.current.focus(); + (focusedNode.current as HTMLInputElement).select?.(); } else if (activeScope && activeScope.current) { focusFirstInScope(activeScope.current); } @@ -381,6 +382,7 @@ function useFocusContainment(scopeRef: RefObject, contain?: bo if (target && target.isConnected) { focusedNode.current = target; focusedNode.current?.focus(); + (focusedNode.current as HTMLInputElement).select?.(); } else if (activeScope.current) { focusFirstInScope(activeScope.current); } @@ -468,6 +470,7 @@ function focusElement(element: FocusableElement | null, scroll = false) { } else if (element != null) { try { element.focus(); + (element as HTMLInputElement).select?.(); } catch { // ignore } diff --git a/packages/@react-aria/interactions/src/focusSafely.ts b/packages/@react-aria/interactions/src/focusSafely.ts index 384f3f363f7..7e739ec931c 100644 --- a/packages/@react-aria/interactions/src/focusSafely.ts +++ b/packages/@react-aria/interactions/src/focusSafely.ts @@ -37,9 +37,11 @@ export function focusSafely(element: FocusableElement): void { // If focus did not move and the element is still in the document, focus it. if (getActiveElement(ownerDocument) === lastFocusedElement && element.isConnected) { focusWithoutScrolling(element); + (element as HTMLInputElement).select?.(); } }); } else { focusWithoutScrolling(element); + (element as HTMLInputElement).select?.(); } } diff --git a/packages/@react-spectrum/s2/stories/Dialog.stories.tsx b/packages/@react-spectrum/s2/stories/Dialog.stories.tsx index e664d5a86bd..50ad1ea7589 100644 --- a/packages/@react-spectrum/s2/stories/Dialog.stories.tsx +++ b/packages/@react-spectrum/s2/stories/Dialog.stories.tsx @@ -43,9 +43,12 @@ export const Example = { Dialog title
Header
- {[...Array(args.paragraphs)].map((_, i) => -

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in

- )} + <> + {[...Array(args.paragraphs)].map((_, i) => +

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in

+ )} + +
Don't show this again
From a92bee67cfbd7f75ebfa327768390622dfde51d3 Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Tue, 8 Jul 2025 06:32:19 +1000 Subject: [PATCH 2/2] fix combobox tests --- packages/@react-spectrum/combobox/test/ComboBox.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@react-spectrum/combobox/test/ComboBox.test.js b/packages/@react-spectrum/combobox/test/ComboBox.test.js index 689075f92d4..3a3f16bb710 100644 --- a/packages/@react-spectrum/combobox/test/ComboBox.test.js +++ b/packages/@react-spectrum/combobox/test/ComboBox.test.js @@ -4398,7 +4398,7 @@ describe('ComboBox', function () { if (Method === 'escape key') { expect(button).toHaveAttribute('aria-labelledby', `${tree.getByText('Test').id} ${tree.getByText('Two').id}`); } else { - expect(button).toHaveAttribute('aria-labelledby', `${tree.getByText('Test').id} ${tree.getByText('Twor').id}`); + expect(button).toHaveAttribute('aria-labelledby', `${tree.getByText('Test').id} ${tree.getByText('r').id}`); } tree.unmount(); @@ -4412,7 +4412,7 @@ describe('ComboBox', function () { await performInteractions(tree); expect(() => tree.getByTestId('tray')).toThrow(); - expect(button).toHaveAttribute('aria-labelledby', `${tree.getByText('Test').id} ${tree.getByText('Twor').id}`); + expect(button).toHaveAttribute('aria-labelledby', `${tree.getByText('Test').id} ${tree.getByText('r').id}`); }); it('menutrigger=focus doesn\'t reopen the tray on close', async function () {