Last active
November 30, 2023 10:23
-
-
Save louy/6b66c45ae47bb4e3bac5a104dd0649ff to your computer and use it in GitHub Desktop.
RN Accessibility Wrapper, a custom view that allows you to control the accessibility behaviour of a React Native component tree
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @author Louay Alakkad (github.com/louy) | |
* @license MIT https://opensource.org/licenses/MIT | |
*/ | |
import React from 'react' | |
import PropTypes from 'prop-types' | |
import { | |
NativeModules, | |
ViewProps, | |
ViewPropTypes, | |
findNodeHandle, | |
requireNativeComponent, | |
Platform, | |
View | |
} from 'react-native' | |
const { RNAccessibilityWrapperManager } = NativeModules | |
const RNAccessibilityWrapper = requireNativeComponent( | |
'RNAccessibilityWrapper' | |
) as React.ComponentClass<any> | |
interface AccessibilityWrapperProps extends ViewProps { | |
fieldsRefs?: React.RefObject<React.Component>[] | |
} | |
const AccessibilityWrapperPropTypes = { | |
...ViewPropTypes, | |
fieldsRefs: PropTypes.arrayOf(PropTypes.shape({ | |
current: PropTypes.object | |
}) as PropTypes.Validator<React.RefObject<React.Component>>) | |
} | |
class AccessibilityWrapperIOS extends React.Component< | |
AccessibilityWrapperProps | |
> { | |
public static propTypes = AccessibilityWrapperPropTypes | |
private ref = React.createRef<React.Component<any>>() | |
public componentDidMount() { | |
if (this.props.fieldsRefs) { | |
this.setAccessibilityFields(this.props.fieldsRefs.map(ref => ref.current)) | |
} | |
} | |
public componentDidUpdate() { | |
if (this.props.fieldsRefs) { | |
this.setAccessibilityFields(this.props.fieldsRefs.map(ref => ref.current)) | |
} | |
} | |
private setAccessibilityFields = ( | |
fields: (React.Component<any> | null)[] | |
) => { | |
const fieldTags = | |
fields && fields.map(component => component && findNodeHandle(component)) | |
return RNAccessibilityWrapperManager.setAccessibilityFields( | |
findNodeHandle(this.ref.current), | |
fieldTags | |
) | |
} | |
public render() { | |
return <RNAccessibilityWrapper {...this.props} ref={this.ref} /> | |
} | |
} | |
const AccessibilityWrapperAndroid: React.FunctionComponent< | |
AccessibilityWrapperProps | |
> = ({ fieldsRefs, ...props }) => <View {...props} /> | |
AccessibilityWrapperAndroid.propTypes = AccessibilityWrapperPropTypes | |
/** | |
* The AccessibilityWrapper component allows you to adjust the behaviour of the native platform | |
* when it comes to accessibility. Using this component you can tell the native platform to | |
* group all subviews together for accessibility purposes (since it's not always done by | |
* default), and you can even override the focus order of subviews | |
* | |
* @example | |
* export default class App extends Component<{}> { | |
* fooRef = React.createRef<Text>(); | |
* barRef = React.createRef<Text>(); | |
* bazRef = React.createRef<Text>(); | |
* | |
* public render() { | |
* return ( | |
* <AccessibilityWrapper fieldsRefs={[ | |
* this.barRef, | |
* this.fooRef, | |
* this.bazRef, | |
* ]}> | |
* <SafeAreaView> | |
* <Text ref={this.fooRef}>Foo</Text> | |
* <Text ref={this.barRef}>Bar</Text> | |
* <Text ref={this.bazRef}>Baz</Text> | |
* </SafeAreaView> | |
* </AccessibilityWrapper> | |
* ); | |
* } | |
* } | |
*/ | |
export default Platform.select<React.ComponentType<AccessibilityWrapperProps>>({ | |
ios: AccessibilityWrapperIOS as React.ComponentType< | |
AccessibilityWrapperProps | |
>, | |
android: AccessibilityWrapperAndroid as React.ComponentType< | |
AccessibilityWrapperProps | |
> | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// RNAccessibilityWrapper.h | |
// | |
// Created by Louay Alakkad on 10/04/2019. | |
// License: MIT https://opensource.org/licenses/MIT | |
// | |
#import <UIKit/UIKit.h> | |
#import <UIKit/UIAccessibilityContainer.h> | |
#import <React/RCTView.h> | |
@interface RNAccessibilityWrapper : RCTView | |
- (void) setAccessibilityFields: (NSArray *)reactTags; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// RNAccessibilityWrapper.m | |
// | |
// Created by Louay Alakkad on 10/04/2019. | |
// License: MIT https://opensource.org/licenses/MIT | |
// | |
#import <Foundation/Foundation.h> | |
#import "RNAccessibilityWrapper.h" | |
#import <UIKit/UIKit.h> | |
@implementation RNAccessibilityWrapper | |
- (void) setAccessibilityFields: (NSArray *)fields | |
{ | |
NSMutableArray *accessibleElements = [NSMutableArray arrayWithCapacity:[fields count]]; | |
[fields enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL * stop) { | |
UIView *field = obj; | |
[accessibleElements addObject:field]; | |
}]; | |
self.accessibilityElements = (NSArray *)accessibleElements; | |
} | |
- (bool) shouldGroupAccessibilityChildren { | |
return YES; | |
} | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// RNAccessibilityViewManager | |
// | |
// Created by Louay Alakkad on 10/04/2019. | |
// License: MIT https://opensource.org/licenses/MIT | |
// | |
#import <React/RCTViewManager.h> | |
@interface RNAccessibilityWrapperManager : RCTViewManager | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// RNAccessibilityWrapper.m | |
// | |
// Created by Louay Alakkad on 10/04/2019. | |
// License: MIT https://opensource.org/licenses/MIT | |
// | |
#import <Foundation/Foundation.h> | |
#import <React/RCTUIManager.h> | |
#import "RNAccessibilityWrapper.h" | |
#import "RNAccessibilityWrapperManager.h" | |
@implementation RNAccessibilityWrapperManager | |
RCT_EXPORT_MODULE() | |
- (UIView *)view { | |
return [[RNAccessibilityWrapper alloc] init]; | |
} | |
RCT_EXPORT_METHOD(setAccessibilityFields:(nonnull NSNumber *)reactTag | |
fieldsReactTags: (nonnull NSArray *)fieldsReactTags) { | |
dispatch_async(dispatch_get_main_queue(), ^{ | |
RNAccessibilityWrapper *component = (RNAccessibilityWrapper *)[self.bridge.uiManager viewForReactTag:reactTag]; | |
NSMutableArray *fields = [NSMutableArray arrayWithCapacity:[fieldsReactTags count]]; | |
[fieldsReactTags enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL * stop) { | |
NSNumber *tag = (NSNumber *)obj; | |
UIView *field = [self.bridge.uiManager viewForReactTag:tag]; | |
[fields addObject:field]; | |
}]; | |
[component setAccessibilityFields: fields]; | |
}); | |
} | |
@end |
Hi, tnx for your work man. Probably it's why I can fix bugs.
I wrote a lib, it can be usefull I guess https://www.npmjs.com/package/react-native-a11y (NewArch, Android, iOs ) supported
Hi, tnx for your work man. Probably it's why I can fix bugs. I wrote a lib, it can be usefull I guess https://www.npmjs.com/package/react-native-a11y (NewArch, Android, iOs ) supported
Nice @ArturKalach !! Will check this out. Focus order has long been a pain point with RN and some layouts.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@rahulpunchh I'm no longer maintaining this I'm afraid, so I can't help, but you can try asking on stackoverflow or somewhere similar