diff --git a/packages/react-native/Libraries/Components/ScrollView/ScrollView.js b/packages/react-native/Libraries/Components/ScrollView/ScrollView.js index 4f3a4fe3bb8f..9138d5241937 100644 --- a/packages/react-native/Libraries/Components/ScrollView/ScrollView.js +++ b/packages/react-native/Libraries/Components/ScrollView/ScrollView.js @@ -685,7 +685,7 @@ type ScrollViewBaseProps = Readonly<{ /** @build-types emit-as-interface Nativewind compatibility */ export type ScrollViewProps = Readonly<{ - ...Omit, + ...Omit, ...ScrollViewPropsIOS, ...ScrollViewPropsAndroid, ...ScrollViewBaseProps, diff --git a/packages/react-native/Libraries/Components/TextInput/TextInput.flow.js b/packages/react-native/Libraries/Components/TextInput/TextInput.flow.js index d65f8a2cd864..a2762929a300 100644 --- a/packages/react-native/Libraries/Components/TextInput/TextInput.flow.js +++ b/packages/react-native/Libraries/Components/TextInput/TextInput.flow.js @@ -1058,7 +1058,10 @@ type TextInputBaseProps = Readonly<{ /** @build-types emit-as-interface Uniwind compatibility */ export type TextInputProps = Readonly<{ - ...Omit, + ...Omit< + ViewProps, + 'style' | 'accessibilityOrder' | 'experimental_accessibilityOrder', + >, ...TextInputIOSProps, ...TextInputAndroidProps, ...TextInputBaseProps, diff --git a/packages/react-native/Libraries/Components/View/ViewAccessibility.d.ts b/packages/react-native/Libraries/Components/View/ViewAccessibility.d.ts index 7b22fb120e8d..5783fd8227cd 100644 --- a/packages/react-native/Libraries/Components/View/ViewAccessibility.d.ts +++ b/packages/react-native/Libraries/Components/View/ViewAccessibility.d.ts @@ -47,6 +47,13 @@ export interface AccessibilityProps */ accessibilityState?: AccessibilityState | undefined; + /** + * Defines the order in which descendant elements receive accessibility focus. + * The elements in the array represent nativeID values for the respective + * descendant elements. + */ + accessibilityOrder?: ReadonlyArray | undefined; + /** * alias for accessibilityState * diff --git a/packages/react-native/Libraries/Components/View/ViewPropTypes.js b/packages/react-native/Libraries/Components/View/ViewPropTypes.js index 6c4be3a025ca..e6792a246607 100644 --- a/packages/react-native/Libraries/Components/View/ViewPropTypes.js +++ b/packages/react-native/Libraries/Components/View/ViewPropTypes.js @@ -507,6 +507,11 @@ type ViewBaseProps = Readonly<{ * The elements in the array represent nativeID values for the respective * descendant elements. */ + accessibilityOrder?: ?Array, + + /** + * Deprecated. Use accessibilityOrder instead. + */ experimental_accessibilityOrder?: ?Array, }>; diff --git a/packages/react-native/Libraries/NativeComponent/BaseViewConfig.android.js b/packages/react-native/Libraries/NativeComponent/BaseViewConfig.android.js index cdd9eceaead2..be87b03ecbd1 100644 --- a/packages/react-native/Libraries/NativeComponent/BaseViewConfig.android.js +++ b/packages/react-native/Libraries/NativeComponent/BaseViewConfig.android.js @@ -224,6 +224,7 @@ const validAttributesForNonEventProps = { accessibilityState: true, accessibilityActions: true, accessibilityValue: true, + accessibilityOrder: true, experimental_accessibilityOrder: true, importantForAccessibility: true, screenReaderFocusable: true, diff --git a/packages/react-native/Libraries/NativeComponent/BaseViewConfig.ios.js b/packages/react-native/Libraries/NativeComponent/BaseViewConfig.ios.js index d22a68642194..d8adb2f1e5fa 100644 --- a/packages/react-native/Libraries/NativeComponent/BaseViewConfig.ios.js +++ b/packages/react-native/Libraries/NativeComponent/BaseViewConfig.ios.js @@ -200,6 +200,7 @@ const validAttributesForNonEventProps = { accessibilityIgnoresInvertColors: true, accessibilityShowsLargeContentViewer: true, accessibilityLargeContentTitle: true, + accessibilityOrder: true, experimental_accessibilityOrder: true, accessibilityRespondsToUserInteraction: true, testID: true, diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.kt index 16176a0f29c2..32f909851449 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.kt @@ -159,7 +159,8 @@ public object ViewProps { public const val ACCESSIBILITY_ACTIONS: String = "accessibilityActions" public const val ACCESSIBILITY_VALUE: String = "accessibilityValue" public const val ACCESSIBILITY_LABELLED_BY: String = "accessibilityLabelledBy" - public const val ACCESSIBILITY_ORDER: String = "experimental_accessibilityOrder" + public const val ACCESSIBILITY_ORDER: String = "accessibilityOrder" + public const val EXPERIMENTAL_ACCESSIBILITY_ORDER: String = "experimental_accessibilityOrder" public const val IMPORTANT_FOR_ACCESSIBILITY: String = "importantForAccessibility" public const val SCREEN_READER_FOCUSABLE: String = "screenReaderFocusable" public const val ROLE: String = "role" diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.kt index 0893e134f4ea..38cd24c463c0 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.kt @@ -99,6 +99,15 @@ public open class ReactViewManager : ReactClippingViewManager() @ReactProp(name = ViewProps.ACCESSIBILITY_ORDER) public open fun setAccessibilityOrder(view: ReactViewGroup, nativeIds: ReadableArray?) { + updateAccessibilityOrder(view, nativeIds) + } + + @ReactProp(name = ViewProps.EXPERIMENTAL_ACCESSIBILITY_ORDER) + public open fun setExperimentalAccessibilityOrder(view: ReactViewGroup, nativeIds: ReadableArray?) { + updateAccessibilityOrder(view, nativeIds) + } + + private fun updateAccessibilityOrder(view: ReactViewGroup, nativeIds: ReadableArray?) { if (!ReactNativeFeatureFlags.enableAccessibilityOrder()) { return } diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp index f21c86773726..55787861b49b 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp @@ -52,8 +52,13 @@ AccessibilityProps::AccessibilityProps( : convertRawProp( context, rawProps, - "experimental_accessibilityOrder", - sourceProps.accessibilityOrder, + "accessibilityOrder", + convertRawProp( + context, + rawProps, + "experimental_accessibilityOrder", + sourceProps.accessibilityOrder, + {}), {})), accessibilityLabelledBy( ReactNativeFeatureFlags::enableCppPropsIteratorSetter() @@ -269,6 +274,7 @@ void AccessibilityProps::setProp( RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityState); RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityLabel); RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityOrder); + RAW_SET_PROP_SWITCH_CASE(accessibilityOrder, "experimental_accessibilityOrder"); RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityLabelledBy); RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityLiveRegion); RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityHint); diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp index e3b174156299..f5c57794e24e 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp @@ -914,7 +914,7 @@ folly::dynamic HostPlatformViewProps::getDiffProps( for (const auto& accessibilityChildId : accessibilityOrder) { accessibilityChildrenIds.push_back(accessibilityChildId); } - result["experimental_accessibilityOrder"] = accessibilityChildrenIds; + result["accessibilityOrder"] = accessibilityChildrenIds; } if (accessibilityLiveRegion != oldProps->accessibilityLiveRegion) { diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/tests/ViewTest.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/tests/ViewTest.cpp index e9aa7b30eff2..ca91c665fec4 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/tests/ViewTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/tests/ViewTest.cpp @@ -14,7 +14,9 @@ #include #include #include +#include #include +#include #include #include @@ -130,6 +132,44 @@ TEST_F(YogaDirtyFlagTest, changingNonLayoutSubPropsMustNotDirtyYogaNode) { static_cast(*newRootShadowNode).layoutIfNeeded()); } +TEST(ViewPropsTest, accessibilityOrderCanBeParsedFromStablePropName) { + ContextContainer contextContainer{}; + PropsParserContext parserContext{-1, contextContainer}; + + auto rawProps = RawProps(folly::dynamic::object( + "accessibilityOrder", + folly::dynamic::array("second", "first", "third"))); + auto parser = RawPropsParser(); + parser.prepare(); + rawProps.parse(parser); + + auto props = + ViewShadowNodeProps(parserContext, ViewShadowNodeProps(), rawProps); + + EXPECT_EQ( + props.accessibilityOrder, + (std::vector{"second", "first", "third"})); +} + +TEST(ViewPropsTest, accessibilityOrderCanBeParsedFromExperimentalPropName) { + ContextContainer contextContainer{}; + PropsParserContext parserContext{-1, contextContainer}; + + auto rawProps = RawProps(folly::dynamic::object( + "experimental_accessibilityOrder", + folly::dynamic::array("second", "first", "third"))); + auto parser = RawPropsParser(); + parser.prepare(); + rawProps.parse(parser); + + auto props = + ViewShadowNodeProps(parserContext, ViewShadowNodeProps(), rawProps); + + EXPECT_EQ( + props.accessibilityOrder, + (std::vector{"second", "first", "third"})); +} + TEST_F(YogaDirtyFlagTest, changingLayoutSubPropsMustDirtyYogaNode) { /* * Changing *layout* sub-props *must* dirty a Yoga node. diff --git a/packages/react-native/ReactNativeApi.d.ts b/packages/react-native/ReactNativeApi.d.ts index 48505ca1b824..54622ec41663 100644 --- a/packages/react-native/ReactNativeApi.d.ts +++ b/packages/react-native/ReactNativeApi.d.ts @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<5a7845e40bbce309e0e1ee96b903d651>> * * This file was generated by scripts/js-api/build-types/index.js. */ @@ -4381,7 +4381,7 @@ declare interface ScrollViewInstance ScrollViewImperativeMethods {} declare interface ScrollViewProps extends Readonly< - ViewProps & + Omit & ScrollViewPropsIOS & ScrollViewPropsAndroid & ScrollViewBaseProps @@ -5208,7 +5208,7 @@ declare type TextInputKeyPressEventData = Readonly< > declare interface TextInputProps extends Readonly< - Omit & + Omit & TextInputIOSProps & TextInputAndroidProps & TextInputBaseProps @@ -5599,6 +5599,7 @@ declare class ViewabilityHelper_default { } declare type ViewabilityHelperT = typeof ViewabilityHelper_default declare type ViewBaseProps = { + readonly accessibilityOrder?: Array readonly children?: React.ReactNode readonly collapsable?: boolean readonly collapsableChildren?: boolean @@ -5850,16 +5851,16 @@ export { AccessibilityValue, // cf8bcb74 ActionSheetIOS, // b558559e ActionSheetIOSOptions, // 1756eb5a - ActivityIndicator, // b2398ac8 + ActivityIndicator, // e372f110 ActivityIndicatorInstance, // a82dd4e7 - ActivityIndicatorProps, // 410756e8 + ActivityIndicatorProps, // 355a9c50 Alert, // 5bf12165 AlertButton, // bf1a3b60 AlertButtonStyle, // ec9fb242 AlertOptions, // a0cdac0f AlertType, // 5ab91217 AndroidKeyboardEvent, // e03becc8 - Animated, // b23fe360 + Animated, // 35174686 AppConfig, // 35c0ca70 AppRegistry, // ce465c83 AppState, // 12012be5 @@ -5891,9 +5892,9 @@ export { DimensionsPayload, // 653bc26c DisplayMetrics, // 1dc35cef DisplayMetricsAndroid, // 872e62eb - DrawerLayoutAndroid, // 4dcb4a45 + DrawerLayoutAndroid, // cbd51483 DrawerLayoutAndroidInstance, // c0694352 - DrawerLayoutAndroidProps, // 2f0e6568 + DrawerLayoutAndroidProps, // 5adeae2a DrawerSlideEvent, // c4ab8fba DropShadowValue, // e9df2606 DynamicColorIOS, // d96c228c @@ -5908,9 +5909,9 @@ export { EventSubscription, // b8d084aa ExtendedExceptionData, // 5a6ccf5a FilterFunction, // bf24c0e3 - FlatList, // cb72efc9 - FlatListInstance, // 8ae5b7be - FlatListProps, // 51cbbb65 + FlatList, // 8d058f79 + FlatListInstance, // 5f17838c + FlatListProps, // 3f9e929c FocusEvent, // 850f1517 FontVariant, // 7c7558bb GestureResponderEvent, // 14d3e77a @@ -5921,17 +5922,17 @@ export { IEventEmitter, // fbef6131 IOSKeyboardEvent, // e67bfe3a IgnorePattern, // ec6f6ece - Image, // c9d40e0a - ImageBackground, // 1ebf73eb - ImageBackgroundInstance, // 88068b4d - ImageBackgroundProps, // d4ec764b + Image, // 4c1d8a33 + ImageBackground, // baaf96d7 + ImageBackgroundInstance, // f186cb4b + ImageBackgroundProps, // 91d7e35f ImageErrorEvent, // 978933f4 ImageInstance, // 9a100753 ImageLoadEvent, // 77f0b718 ImageProgressEventIOS, // 445331a4 - ImageProps, // 75d78475 + ImageProps, // 928793c2 ImagePropsAndroid, // 9fd9bcbb - ImagePropsBase, // 3366fcf2 + ImagePropsBase, // 60399bcc ImagePropsIOS, // 4a080668 ImageRequireSource, // 681d683b ImageResolvedAssetSource, // f3060931 @@ -5948,9 +5949,9 @@ export { KeyEvent, // 20fa4267 KeyUpEvent, // 57f832c5 Keyboard, // 49414c97 - KeyboardAvoidingView, // f612e39b - KeyboardAvoidingViewInstance, // 084c1430 - KeyboardAvoidingViewProps, // 8f05bdcc + KeyboardAvoidingView, // 1d65095c + KeyboardAvoidingViewInstance, // 94bbc7f0 + KeyboardAvoidingViewProps, // f4473dc5 KeyboardEvent, // c3f895d4 KeyboardEventEasing, // af4091c8 KeyboardEventName, // 59299ad6 @@ -5975,10 +5976,10 @@ export { MeasureInWindowOnSuccessCallback, // a285f598 MeasureLayoutOnSuccessCallback, // 3592502a MeasureOnSuccessCallback, // 82824e59 - Modal, // 2ae8076c + Modal, // e987d5c9 ModalBaseProps, // 71945951 ModalInstance, // d466ce77 - ModalProps, // 96a029e2 + ModalProps, // 90bdb9cc ModalPropsAndroid, // 515fb173 ModalPropsIOS, // 0e13cfcc ModeChangeEvent, // f64bf69d @@ -6013,15 +6014,15 @@ export { PointerEvent, // ff599afe PressabilityConfig, // faab5639 PressabilityEventHandlers, // 0b910091 - Pressable, // 1317b500 + Pressable, // abf8fdd8 PressableAndroidRippleConfig, // ee32eaca PressableInstance, // eebfe911 - PressableProps, // fa87db54 + PressableProps, // 4d230866 PressableStateCallbackType, // 9af36561 ProcessedColorValue, // 33f74304 - ProgressBarAndroid, // 5fe46213 + ProgressBarAndroid, // faa9cff1 ProgressBarAndroidInstance, // ab545ef1 - ProgressBarAndroidProps, // d83cd71f + ProgressBarAndroidProps, // 7f5f956b PublicRootInstance, // 8040afd7 PublicTextInstance, // 6937c7bf PushNotificationEventName, // 84e7e150 @@ -6029,9 +6030,9 @@ export { PushNotificationPermissions, // c2e7ae4f Rationale, // 5df1b1c1 ReactNativeVersion, // abd76827 - RefreshControl, // 36c129c8 - RefreshControlInstance, // be7161ec - RefreshControlProps, // d564221a + RefreshControl, // 24b61f9b + RefreshControlInstance, // 0f041ce5 + RefreshControlProps, // 26336e02 RefreshControlPropsAndroid, // 99f64c97 RefreshControlPropsIOS, // 72a36381 Registry, // 6c39216d @@ -6043,24 +6044,24 @@ export { RootViewStyleProvider, // d4818465 Runnable, // 594dd93a Runnables, // 4367c557 - SafeAreaView, // 0bfa1f1d + SafeAreaView, // 8db8f007 SafeAreaViewInstance, // 21dba39c ScaledSize, // 07e417c7 ScrollEvent, // d7abdd0a - ScrollResponderType, // 3991d0ad + ScrollResponderType, // d42c5635 ScrollToLocationParamsType, // d7ecdad1 - ScrollView, // f493b5d4 - ScrollViewImperativeMethods, // 2791f991 - ScrollViewInstance, // 8a170aaf - ScrollViewProps, // 346eb88e + ScrollView, // 0334adb9 + ScrollViewImperativeMethods, // 2712c61c + ScrollViewInstance, // 5414d77c + ScrollViewProps, // 33606e64 ScrollViewPropsAndroid, // 44210553 ScrollViewPropsIOS, // b7921e26 ScrollViewScrollToOptions, // 3313411e SectionBase, // dca83594 - SectionList, // 876f013f + SectionList, // f273f7c5 SectionListData, // e0d79987 - SectionListInstance, // dbdba666 - SectionListProps, // 8bd0ac05 + SectionListInstance, // 6bdeafe7 + SectionListProps, // 10eb18d4 SectionListRenderItem, // 466e3e87 SectionListRenderItemInfo, // d809238e Separators, // 6a45f7e3 @@ -6079,17 +6080,17 @@ export { StyleProp, // fa0e9b4a StyleSheet, // fc631571 SubmitBehavior, // c4ddf490 - Switch, // 135ac108 + Switch, // 85f59936 SwitchChangeEvent, // 899635b1 SwitchInstance, // 3c50eec5 - SwitchProps, // 7a40abb7 + SwitchProps, // ce4672e3 Systrace, // 626d178c TVViewPropsIOS, // 330ce7b5 TargetedEvent, // 16e98910 TaskProvider, // 266dedf2 Text, // 2cf03c50 TextContentType, // 239b3ecc - TextInput, // 772bbb29 + TextInput, // 726186a8 TextInputAndroidProps, // 3f09ce49 TextInputChangeEvent, // f55eef98 TextInputContentSizeChangeEvent, // a27cd32a @@ -6098,7 +6099,7 @@ export { TextInputIOSProps, // 0d05a855 TextInputInstance, // 5a0c0e0d TextInputKeyPressEvent, // 546c5d07 - TextInputProps, // cf23de8e + TextInputProps, // 1271eaee TextInputSelectionChangeEvent, // e58f2abc TextInputSubmitEditingEvent, // 6bcb2aa5 TextInstance, // 05463a96 @@ -6124,19 +6125,19 @@ export { UIManager, // a1a7cc01 UTFSequence, // ad625158 Vibration, // 31e4bbf8 - View, // c5b3d5fe + View, // 5439487f ViewInstance, // ffde5573 - ViewProps, // a50b7cfa + ViewProps, // 06109ced ViewPropsAndroid, // 03c17367 ViewPropsIOS, // 58ee19bf ViewStyle, // 00a0f8fb VirtualViewMode, // 6be59722 VirtualizedList, // 68c7345e VirtualizedListInstance, // 423ee7c0 - VirtualizedListProps, // a5458c31 + VirtualizedListProps, // 5d3c740f VirtualizedSectionList, // 9fd9cd61 VirtualizedSectionListInstance, // 12b706d5 - VirtualizedSectionListProps, // ef387a8a + VirtualizedSectionListProps, // f6d311e5 WrapperComponentProvider, // 4b8c7962 codegenNativeCommands, // 628a7c0a codegenNativeComponent, // 32a1bca6 diff --git a/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js b/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js index efe3baf936bd..0ec930bb0dba 100644 --- a/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js +++ b/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js @@ -1715,7 +1715,7 @@ function AccessibilityOrderExample(): React.Node { + accessibilityOrder={['b', 'c', 'a']}> + accessibilityOrder={['b', 'c', 'a']}> + accessibilityOrder={['b', 'c', 'a']}> + accessibilityOrder={['b', 'c', 'a']}> + accessibilityOrder={['b', 'c', 'a']}> + accessibilityOrder={['b', 'c', 'root', 'a']}> + accessibilityOrder={['b', 'c', 'a']}> + accessibilityOrder={['c', 'a', 'b', 'text']}> +