diff --git a/packages/react-native/Libraries/Components/TextInput/TextInput.js b/packages/react-native/Libraries/Components/TextInput/TextInput.js index 8bd86ccc2f0..1e95eb6d44a 100644 --- a/packages/react-native/Libraries/Components/TextInput/TextInput.js +++ b/packages/react-native/Libraries/Components/TextInput/TextInput.js @@ -618,6 +618,9 @@ function InternalTextInput(props: TextInputProps): React.Node { // so omitting onBlur and onFocus pressability handlers here. const {onBlur, onFocus, ...eventHandlers} = usePressability(config); + const _accessibilityLabel = + props?.['aria-label'] ?? props?.accessibilityLabel; + let _accessibilityState; if ( accessibilityState != null || @@ -681,6 +684,7 @@ function InternalTextInput(props: TextInputProps): React.Node { {...otherProps} {...eventHandlers} acceptDragAndDropTypes={props.experimental_acceptDragAndDropTypes} + accessibilityLabel={_accessibilityLabel} accessibilityState={_accessibilityState} accessible={accessible} submitBehavior={submitBehavior} @@ -744,8 +748,9 @@ function InternalTextInput(props: TextInputProps): React.Node { {...otherProps} {...colorProps} {...eventHandlers} - accessibilityState={_accessibilityState} + accessibilityLabel={_accessibilityLabel} accessibilityLabelledBy={_accessibilityLabelledBy} + accessibilityState={_accessibilityState} accessible={accessible} acceptDragAndDropTypes={props.experimental_acceptDragAndDropTypes} autoCapitalize={autoCapitalize} diff --git a/packages/react-native/Libraries/Components/TextInput/__tests__/TextInput-test.js b/packages/react-native/Libraries/Components/TextInput/__tests__/TextInput-test.js index bf63d695721..a33757e1e15 100644 --- a/packages/react-native/Libraries/Components/TextInput/__tests__/TextInput-test.js +++ b/packages/react-native/Libraries/Components/TextInput/__tests__/TextInput-test.js @@ -432,6 +432,7 @@ jest.unmock('../TextInput'); expect(instance.toJSON()).toMatchInlineSnapshot(` +@property (nonatomic, weak) UIView *accessibilityFocusedView; + @end @implementation RCTModalHostViewComponentView { @@ -148,6 +150,7 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct( { BOOL shouldBePresented = !_isPresented && _shouldPresent && self.window; if (shouldBePresented) { + [self saveAccessibilityFocusedView]; self.viewController.presentationController.delegate = self; _isPresented = YES; @@ -179,6 +182,8 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct( if (eventEmitter) { eventEmitter->onDismiss(ModalHostViewEventEmitter::OnDismiss{}); } + + [self restoreAccessibilityFocusedView]; }]; } } @@ -207,6 +212,23 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct( [self ensurePresentedOnlyIfNeeded]; } +- (void)saveAccessibilityFocusedView +{ + id focusedElement = UIAccessibilityFocusedElement(nil); + if (focusedElement && [focusedElement isKindOfClass:[UIView class]]) { + self.accessibilityFocusedView = (UIView *)focusedElement; + } +} + +- (void)restoreAccessibilityFocusedView +{ + id viewToFocus = self.accessibilityFocusedView; + if (viewToFocus) { + UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, viewToFocus); + self.accessibilityFocusedView = nil; + } +} + #pragma mark - RCTFabricModalHostViewControllerDelegate - (void)boundsDidChange:(CGRect)newBounds diff --git a/packages/rn-tester/js/examples/TextInput/TextInputExample.android.js b/packages/rn-tester/js/examples/TextInput/TextInputExample.android.js index 930b241647b..eda21cd69be 100644 --- a/packages/rn-tester/js/examples/TextInput/TextInputExample.android.js +++ b/packages/rn-tester/js/examples/TextInput/TextInputExample.android.js @@ -451,6 +451,19 @@ const examples: Array = [ return ; }, }, + { + title: 'Accessibility', + render: function (): React.Node { + return ( + + accessibilityLabel prop + + aria-label prop + + + ); + }, + }, ]; module.exports = ({ diff --git a/packages/rn-tester/js/examples/TextInput/TextInputExample.ios.js b/packages/rn-tester/js/examples/TextInput/TextInputExample.ios.js index 62f9607de9e..0994b851ed0 100644 --- a/packages/rn-tester/js/examples/TextInput/TextInputExample.ios.js +++ b/packages/rn-tester/js/examples/TextInput/TextInputExample.ios.js @@ -1036,6 +1036,21 @@ const textInputExamples: Array = [ ); }, }, + { + title: 'Accessibility', + render: function (): React.Node { + return ( + + + + + + + + + ); + }, + }, ]; module.exports = ({