From f630c154c1cf16219efbd0f052019ea5bcfe14bd Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Tue, 23 Sep 2025 09:58:40 +1000 Subject: [PATCH] =?UTF-8?q?Revert=20"Revert=20"fix:=20Focus=20behaviour=20?= =?UTF-8?q?on=20inputs=20inside=20a=20FocusScope=20(#8498)"=20(=E2=80=A6"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 84ff482298bad45c9ae0ca63935213c1e387148e. --- .../@react-aria/autocomplete/src/useAutocomplete.ts | 5 ++++- packages/@react-aria/focus/src/FocusScope.tsx | 11 +++++++++++ packages/@react-aria/interactions/src/focusSafely.ts | 7 +++++++ .../@react-spectrum/combobox/test/ComboBox.test.js | 4 ++-- .../@react-spectrum/s2/stories/Dialog.stories.tsx | 9 ++++++--- 5 files changed, 30 insertions(+), 6 deletions(-) diff --git a/packages/@react-aria/autocomplete/src/useAutocomplete.ts b/packages/@react-aria/autocomplete/src/useAutocomplete.ts index 7f895a676b1..2cd204e2e15 100644 --- a/packages/@react-aria/autocomplete/src/useAutocomplete.ts +++ b/packages/@react-aria/autocomplete/src/useAutocomplete.ts @@ -13,7 +13,7 @@ import {AriaLabelingProps, BaseEvent, DOMProps, FocusableElement, FocusEvents, KeyboardEvents, Node, RefObject, ValueBase} from '@react-types/shared'; import {AriaTextFieldProps} from '@react-aria/textfield'; import {AutocompleteProps, AutocompleteState} from '@react-stately/autocomplete'; -import {CLEAR_FOCUS_EVENT, FOCUS_EVENT, getActiveElement, getOwnerDocument, isAndroid, isCtrlKeyPressed, isIOS, mergeProps, mergeRefs, useEffectEvent, useEvent, useLabels, useObjectRef, useSlotId} from '@react-aria/utils'; +import {CLEAR_FOCUS_EVENT, FOCUS_EVENT, getActiveElement, getOwnerDocument, getOwnerWindow, isAndroid, isCtrlKeyPressed, isIOS, mergeProps, mergeRefs, useEffectEvent, useEvent, useLabels, useObjectRef, useSlotId} from '@react-aria/utils'; import {dispatchVirtualBlur, dispatchVirtualFocus, getVirtuallyFocusedElement, moveVirtualFocus} from '@react-aria/focus'; import {getInteractionModality} from '@react-aria/interactions'; // @ts-ignore @@ -106,6 +106,9 @@ export function useAutocomplete(props: AriaAutocompleteOptions, state: Aut // 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(); + if (inputRef.current instanceof getOwnerWindow(inputRef.current).HTMLInputElement) { + 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 6dad540400a..a7b5108f0a9 100644 --- a/packages/@react-aria/focus/src/FocusScope.tsx +++ b/packages/@react-aria/focus/src/FocusScope.tsx @@ -15,6 +15,7 @@ import { getActiveElement, getEventTarget, getOwnerDocument, + getOwnerWindow, isAndroid, isChrome, isFocusable, @@ -371,6 +372,10 @@ 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(); + + if (focusedNode.current instanceof getOwnerWindow(focusedNode.current).HTMLInputElement) { + focusedNode.current.select(); + } } else if (activeScope && activeScope.current) { focusFirstInScope(activeScope.current); } @@ -399,6 +404,9 @@ function useFocusContainment(scopeRef: RefObject, contain?: bo if (target && target.isConnected) { focusedNode.current = target; focusedNode.current?.focus(); + if (focusedNode.current instanceof getOwnerWindow(focusedNode.current).HTMLInputElement) { + focusedNode.current.select(); + } } else if (activeScope.current) { focusFirstInScope(activeScope.current); } @@ -486,6 +494,9 @@ function focusElement(element: FocusableElement | null, scroll = false) { } else if (element != null) { try { element.focus(); + if (element instanceof getOwnerWindow(element).HTMLInputElement) { + element.select(); + } } catch { // ignore } diff --git a/packages/@react-aria/interactions/src/focusSafely.ts b/packages/@react-aria/interactions/src/focusSafely.ts index 384f3f363f7..46d95d917cf 100644 --- a/packages/@react-aria/interactions/src/focusSafely.ts +++ b/packages/@react-aria/interactions/src/focusSafely.ts @@ -15,6 +15,7 @@ import { focusWithoutScrolling, getActiveElement, getOwnerDocument, + getOwnerWindow, runAfterTransition } from '@react-aria/utils'; import {getInteractionModality} from './useFocusVisible'; @@ -37,9 +38,15 @@ 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); + if (element instanceof getOwnerWindow(element).HTMLInputElement) { + element.select(); + } } }); } else { focusWithoutScrolling(element); + if (element instanceof getOwnerWindow(element).HTMLInputElement) { + element.select(); + } } } diff --git a/packages/@react-spectrum/combobox/test/ComboBox.test.js b/packages/@react-spectrum/combobox/test/ComboBox.test.js index 8a6b7ee6e54..913a527a04a 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 () { diff --git a/packages/@react-spectrum/s2/stories/Dialog.stories.tsx b/packages/@react-spectrum/s2/stories/Dialog.stories.tsx index e178ef0c56f..e4fdfcd4303 100644 --- a/packages/@react-spectrum/s2/stories/Dialog.stories.tsx +++ b/packages/@react-spectrum/s2/stories/Dialog.stories.tsx @@ -48,9 +48,12 @@ const ExampleRender = (args: ExampleRenderProps): ReactElement => ( 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