/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* 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 React = require('react');
const {
AccessibilityInfo,
TextInput,
Button,
Image,
Text,
View,
TouchableOpacity,
TouchableWithoutFeedback,
Alert,
StyleSheet,
Slider,
Platform,
} = require('react-native');
import type {EventSubscription} from 'react-native/Libraries/vendor/emitter/EventEmitter';
const RNTesterBlock = require('../../components/RNTesterBlock');
const checkImageSource = require('./check.png');
const uncheckImageSource = require('./uncheck.png');
const mixedCheckboxImageSource = require('./mixed.png');
const {createRef} = require('react');
const styles = StyleSheet.create({
default: {
borderWidth: StyleSheet.hairlineWidth,
borderColor: '#0f0f0f',
flex: 1,
fontSize: 13,
padding: 4,
},
touchable: {
backgroundColor: 'blue',
borderColor: 'red',
borderWidth: 1,
borderRadius: 10,
padding: 10,
borderStyle: 'solid',
},
image: {
width: 20,
height: 20,
resizeMode: 'contain',
marginRight: 10,
},
disabledImage: {
width: 120,
height: 120,
},
containerAlignCenter: {
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
},
});
class AccessibilityExample extends React.Component<{}> {
render(): React.Node {
return (
Text's accessibilityLabel is the raw text itself unless it is set
explicitly.
This text component's accessibilityLabel is set explicitly.
This is text one.
This is text two.
This is text one.
This is text two.
This is text one.
This is text two.
{/* Android screen readers will say the accessibility hint instead of the text
since the view doesn't have a label. */}
This is text one.
This is text two.
This is text one.
This is text two.
This is a title.
Alert.alert('Link has been clicked!')}
accessibilityRole="link">
Click me
Alert.alert('Button has been pressed!')}
accessibilityRole="button">
Click me
Alert.alert('Button has been pressed!')}
accessibilityRole="button"
accessibilityState={{disabled: true}}
disabled={true}>
I am disabled. Clicking me will not trigger any action.
Alert.alert('Disabled Button has been pressed!')}
accessibilityLabel={'You are pressing Disabled TouchableOpacity'}
accessibilityState={{disabled: true}}>
I am disabled. Clicking me will not trigger any action.
This view is selected and disabled.
Accessible view with label, hint, role, and state
);
}
}
class CheckboxExample extends React.Component<
{},
{
checkboxState: boolean | 'mixed',
},
> {
state = {
checkboxState: true,
};
_onCheckboxPress = () => {
let checkboxState = false;
if (this.state.checkboxState === false) {
checkboxState = 'mixed';
} else if (this.state.checkboxState === 'mixed') {
checkboxState = true;
} else {
checkboxState = false;
}
this.setState({
checkboxState: checkboxState,
});
};
render() {
return (
Checkbox example
);
}
}
class SwitchExample extends React.Component<
{},
{
switchState: boolean,
},
> {
state = {
switchState: true,
};
_onSwitchToggle = () => {
const switchState = !this.state.switchState;
this.setState({
switchState: switchState,
});
};
render() {
return (
Switch example
);
}
}
class SelectionExample extends React.Component<
{},
{
isSelected: boolean,
isEnabled: boolean,
},
> {
constructor(props: {}) {
super(props);
this.selectableElement = createRef();
}
selectableElement: {
current: React.ElementRef | null,
};
state = {
isSelected: true,
isEnabled: false,
};
render(): React.Node {
const {isSelected, isEnabled} = this.state;
let accessibilityHint = 'click me to select';
if (isSelected) {
accessibilityHint = 'click me to unselect';
}
if (!isEnabled) {
accessibilityHint = 'use the button on the right to enable selection';
}
let buttonTitle = isEnabled ? 'Disable selection' : 'Enable selection';
const touchableHint = ` (touching the TouchableOpacity will ${
isSelected ? 'disable' : 'enable'
} accessibilityState.selected)`;
return (
{
if (isEnabled) {
this.setState({
isSelected: !isSelected,
});
} else {
console.warn('selection is disabled, please enable selection.');
}
}}
accessibilityLabel="element 19"
accessibilityState={{
selected: isSelected,
disabled: !isEnabled,
}}
style={styles.touchable}
accessibilityHint={accessibilityHint}>
{`Selectable TouchableOpacity Example ${touchableHint}`}
);
}
}
class ExpandableElementExample extends React.Component<
{},
{
expandState: boolean,
},
> {
state = {
expandState: false,
};
_onElementPress = () => {
const expandState = !this.state.expandState;
this.setState({
expandState: expandState,
});
};
render() {
return (
Expandable element example
);
}
}
class NestedCheckBox extends React.Component<
{},
{
checkbox1: boolean | 'mixed',
checkbox2: boolean | 'mixed',
checkbox3: boolean | 'mixed',
},
> {
state = {
checkbox1: false,
checkbox2: false,
checkbox3: false,
};
_onPress1 = () => {
let checkbox1 = false;
if (this.state.checkbox1 === false) {
checkbox1 = true;
} else if (this.state.checkbox1 === 'mixed') {
checkbox1 = false;
} else {
checkbox1 = false;
}
setTimeout(() => {
this.setState({
checkbox1: checkbox1,
checkbox2: checkbox1,
checkbox3: checkbox1,
});
}, 2000);
};
_onPress2 = () => {
const checkbox2 = !this.state.checkbox2;
this.setState({
checkbox2: checkbox2,
checkbox1:
checkbox2 && this.state.checkbox3
? true
: checkbox2 || this.state.checkbox3
? 'mixed'
: false,
});
};
_onPress3 = () => {
const checkbox3 = !this.state.checkbox3;
this.setState({
checkbox3: checkbox3,
checkbox1:
this.state.checkbox2 && checkbox3
? true
: this.state.checkbox2 || checkbox3
? 'mixed'
: false,
});
};
render() {
return (
Meat
Beef
Bacon
);
}
}
class AccessibilityRoleAndStateExample extends React.Component<{}> {
render(): React.Node {
return (
Alert example
Combobox example
Menu example
Menu bar example
Menu item example
Progress bar example
Radio button example
Radio group example
Scrollbar example
Spin button example
Tab example
Tab list example
Timer example
Toolbar example
State busy example
);
}
}
class AccessibilityActionsExample extends React.Component<{}> {
render(): React.Node {
return (
{
switch (event.nativeEvent.actionName) {
case 'activate':
Alert.alert('Alert', 'View is clicked');
break;
}
}}>
Click me
{
switch (event.nativeEvent.actionName) {
case 'cut':
Alert.alert('Alert', 'cut action success');
break;
case 'copy':
Alert.alert('Alert', 'copy action success');
break;
case 'paste':
Alert.alert('Alert', 'paste action success');
break;
}
}}>
This view supports many actions.
{
switch (event.nativeEvent.actionName) {
case 'increment':
Alert.alert('Alert', 'increment action success');
break;
case 'decrement':
Alert.alert('Alert', 'decrement action success');
break;
}
}}>
Slider
{
switch (event.nativeEvent.actionName) {
case 'cut':
Alert.alert('Alert', 'cut action success');
break;
case 'copy':
Alert.alert('Alert', 'copy action success');
break;
case 'paste':
Alert.alert('Alert', 'paste action success');
break;
}
}}
onPress={() => Alert.alert('Button has been pressed!')}
accessibilityRole="button">
Click me
{
switch (event.nativeEvent.actionName) {
case 'activate':
Alert.alert('Alert', 'Activate accessiblity action');
break;
case 'copy':
Alert.alert('Alert', 'copy action success');
break;
}
}}>
Text
);
}
}
function SliderAccessibilityExample(): React.Node {
return (
);
}
type FakeSliderExampleState = {
current: number,
textualValue: 'center' | 'left' | 'right',
};
class FakeSliderExample extends React.Component<{}, FakeSliderExampleState> {
state: FakeSliderExampleState = {
current: 50,
textualValue: 'center',
};
increment: () => void = () => {
let newValue = this.state.current + 2;
if (newValue > 100) {
newValue = 100;
}
this.setState({
current: newValue,
});
};
decrement: () => void = () => {
let newValue = this.state.current - 2;
if (newValue < 0) {
newValue = 0;
}
this.setState({
current: newValue,
});
};
render(): React.Node {
return (
{
switch (event.nativeEvent.actionName) {
case 'increment':
this.increment();
break;
case 'decrement':
this.decrement();
break;
}
}}
accessibilityValue={{
min: 0,
now: this.state.current,
max: 100,
}}>
Fake Slider
{
switch (event.nativeEvent.actionName) {
case 'increment':
if (this.state.textualValue === 'center') {
this.setState({textualValue: 'right'});
} else if (this.state.textualValue === 'left') {
this.setState({textualValue: 'center'});
}
break;
case 'decrement':
if (this.state.textualValue === 'center') {
this.setState({textualValue: 'left'});
} else if (this.state.textualValue === 'right') {
this.setState({textualValue: 'center'});
}
break;
}
}}
accessibilityValue={{text: this.state.textualValue}}>
Equalizer
);
}
}
class AnnounceForAccessibility extends React.Component<{}> {
_handleOnPress = () =>
AccessibilityInfo.announceForAccessibility('Announcement Test');
render(): React.Node {
return (
);
}
}
class SetAccessibilityFocusExample extends React.Component<{}> {
render(): React.Node {
const myRef: {current: React.ElementRef | null} = createRef();
const onClose = () => {
if (myRef && myRef.current) {
AccessibilityInfo.sendAccessibilityEvent_unstable(
myRef.current,
'focus',
);
}
};
return (
SetAccessibilityFocus on native element
);
}
}
class EnabledExamples extends React.Component<{}> {
render(): React.Node {
return (
{Platform.OS === 'ios' ? (
<>
>
) : null}
);
}
}
class EnabledExample extends React.Component<
{
eventListener:
| 'reduceMotionChanged'
| 'boldTextChanged'
| 'grayscaleChanged'
| 'invertColorsChanged'
| 'reduceTransparencyChanged'
| 'reduceMotionChanged'
| 'screenReaderChanged',
test: string,
},
{
isEnabled: boolean,
},
> {
state = {
isEnabled: false,
};
_subscription: EventSubscription;
componentDidMount() {
this._subscription = AccessibilityInfo.addEventListener(
this.props.eventListener,
this._handleToggled,
);
switch (this.props.eventListener) {
case 'reduceMotionChanged':
return AccessibilityInfo.isReduceMotionEnabled().then(state => {
this.setState({isEnabled: state});
});
default:
return null;
}
}
componentWillUnmount() {
this._subscription?.remove();
}
_handleToggled = isEnabled => {
if (!this.state.isEnabled) {
this.setState({isEnabled: true});
} else {
this.setState({isEnabled: false});
}
};
render(): React.Node {
return (
The {this.props.test} is{' '}
{this.state.isEnabled ? 'enabled' : 'disabled'}
);
}
}
exports.title = 'Accessibility';
exports.documentationURL = 'https://reactnative.dev/docs/accessibilityinfo';
exports.description = 'Examples of using Accessibility APIs.';
exports.examples = [
{
title: 'Accessibility elements',
render(): React.Element {
return ;
},
},
{
title: 'New accessibility roles and states',
render(): React.Element {
return ;
},
},
{
title: 'Accessibility action examples',
render(): React.Element {
return ;
},
},
{
title: 'Slider Accessibility Examples',
render(): React.Element {
return ;
},
},
{
title: 'Fake Slider Example',
render(): React.Element {
return ;
},
},
{
title: 'Check if the screen reader announces',
render(): React.Element {
return ;
},
},
{
title: 'Check if accessibility is focused',
render(): React.Element {
return ;
},
},
{
title: 'Check if these properties are enabled',
render(): React.Element {
return ;
},
},
{
title:
'Check if accessibilityState disabled is announced when the screenreader focus moves on the image',
render(): React.Element {
return (
);
},
},
];