Ziqi Chen 121e2e5ca6 accessibilityTraits + accessibilityComponentType >> accessibilityRole + accessibilityStates 2/3
Summary:
Previously, I created two props, `accessibilityRole` and `accessibilityStates` for view. These props were intended to be a cross-platform solution to replace  `accessibilityComponentType` on Android and `accessibilityTraits` on iOS.

In this stack, I ran a code mod to replace instances of the two old properties used in our codebase with the new ones.
For this diff, I did a search for all the remnant uses of `accessibilityComponentType` that was not caught by my script, and I manually changed them to `accessibilityRole` and `accessibilityStates`. If the same prop also set `accessibilityTraits` I also removed that here because the two new props works on both platforms.

It was difficult to write a script for this, because most of them were contextual changes.
Out of the contextual changes, most of them followed one of these two patterns:

Before:

```
const accessibilityComponentType = 'button';
const accessibilityTraits = ['button'];

if (this.props.checked) {
  accessibilityTraits.push('selected');
}
if (this.props.disabled) {
 accessibilityTraits.push('disabled');
}

      contentView = (
        <AdsManagerTouchableHighlight
          accessibilityComponentType={accessibilityComponentType}
          accessibilityTraits={accessibilityTraits}
```

After:
      const accessibilityRole = 'button';
      const accessibilityStates = [];

        if (this.props.checked) {
          accessibilityStates.push('selected');
        }
        if (this.props.disabled) {
           accessibilityStates.push('disabled');
        }

      contentView = (
        <AdsManagerTouchableHighlight
          accessibilityRole={accessibilityRole}
          accessibilityStates={accessibilityStates}

Before:

```
  <PressableBackground
          accessible={this.props.accessible}
          accessibilityLabel={this.props.accessibilityLabel}
          accessibilityTraits={this.props.accessibilityTraits}
```

After:

```
  <PressableBackground
          accessible={this.props.accessible}
          accessibilityLabel={this.props.accessibilityLabel}
          accessibilityRole={this.props.accessibilityRole}
          accessibilityRole={this.props.accessibilityStates}
```

In addition to changing the props on the components,
Another fix I had to do was to add props  accessibilityRole and accessibilityStates to components that don't directly inherit properties from view including text input and touchables.

Reviewed By: PeteTheHeat

Differential Revision: D8943499

fbshipit-source-id: fbb40a5e5f5d630b0fe56a009ff24635d4c8cc93
2018-07-25 23:48:26 -07:00

188 lines
4.8 KiB
JavaScript

/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow
*/
'use strict';
const ColorPropType = require('ColorPropType');
const Platform = require('Platform');
const React = require('React');
const PropTypes = require('prop-types');
const StyleSheet = require('StyleSheet');
const Text = require('Text');
const TouchableNativeFeedback = require('TouchableNativeFeedback');
const TouchableOpacity = require('TouchableOpacity');
const View = require('View');
const invariant = require('fbjs/lib/invariant');
/**
* A basic button component that should render nicely on any platform. Supports
* a minimal level of customization.
*
* <center><img src="img/buttonExample.png"></img></center>
*
* If this button doesn't look right for your app, you can build your own
* button using [TouchableOpacity](docs/touchableopacity.html)
* or [TouchableNativeFeedback](docs/touchablenativefeedback.html).
* For inspiration, look at the [source code for this button component](https://github.com/facebook/react-native/blob/master/Libraries/Components/Button.js).
* Or, take a look at the [wide variety of button components built by the community](https://js.coach/react-native?search=button).
*
* Example usage:
*
* ```
* import { Button } from 'react-native';
* ...
*
* <Button
* onPress={onPressLearnMore}
* title="Learn More"
* color="#841584"
* accessibilityLabel="Learn more about this purple button"
* />
* ```
*
*/
class Button extends React.Component<{
title: string,
onPress: () => any,
color?: ?string,
hasTVPreferredFocus?: ?boolean,
accessibilityLabel?: ?string,
disabled?: ?boolean,
testID?: ?string,
}> {
static propTypes = {
/**
* Text to display inside the button
*/
title: PropTypes.string.isRequired,
/**
* Text to display for blindness accessibility features
*/
accessibilityLabel: PropTypes.string,
/**
* Color of the text (iOS), or background color of the button (Android)
*/
color: ColorPropType,
/**
* If true, disable all interactions for this component.
*/
disabled: PropTypes.bool,
/**
* TV preferred focus (see documentation for the View component).
*/
hasTVPreferredFocus: PropTypes.bool,
/**
* Handler to be called when the user taps the button
*/
onPress: PropTypes.func.isRequired,
/**
* Used to locate this view in end-to-end tests.
*/
testID: PropTypes.string,
};
render() {
const {
accessibilityLabel,
color,
onPress,
title,
hasTVPreferredFocus,
disabled,
testID,
} = this.props;
const buttonStyles = [styles.button];
const textStyles = [styles.text];
if (color) {
if (Platform.OS === 'ios') {
textStyles.push({color: color});
} else {
buttonStyles.push({backgroundColor: color});
}
}
const accessibilityStates = [];
if (disabled) {
buttonStyles.push(styles.buttonDisabled);
textStyles.push(styles.textDisabled);
accessibilityStates.push('disabled');
}
invariant(
typeof title === 'string',
'The title prop of a Button must be a string',
);
const formattedTitle =
Platform.OS === 'android' ? title.toUpperCase() : title;
const Touchable =
Platform.OS === 'android' ? TouchableNativeFeedback : TouchableOpacity;
return (
<Touchable
accessibilityLabel={accessibilityLabel}
accessibilityRole="button"
accessibilityStates={accessibilityStates}
hasTVPreferredFocus={hasTVPreferredFocus}
testID={testID}
disabled={disabled}
onPress={onPress}>
<View style={buttonStyles}>
<Text style={textStyles} disabled={disabled}>
{formattedTitle}
</Text>
</View>
</Touchable>
);
}
}
const styles = StyleSheet.create({
button: Platform.select({
ios: {},
android: {
elevation: 4,
// Material design blue from https://material.google.com/style/color.html#color-color-palette
backgroundColor: '#2196F3',
borderRadius: 2,
},
}),
text: Platform.select({
ios: {
// iOS blue from https://developer.apple.com/ios/human-interface-guidelines/visual-design/color/
color: '#007AFF',
textAlign: 'center',
padding: 8,
fontSize: 18,
},
android: {
color: 'white',
textAlign: 'center',
padding: 8,
fontWeight: '500',
},
}),
buttonDisabled: Platform.select({
ios: {},
android: {
elevation: 0,
backgroundColor: '#dfdfdf',
},
}),
textDisabled: Platform.select({
ios: {
color: '#cdcdcd',
},
android: {
color: '#a1a1a1',
},
}),
});
module.exports = Button;