Skip to content

Commit

Permalink
Fix/30842 - Add accessibilityState prop in slider (#31145)
Browse files Browse the repository at this point in the history
Summary:
Accessibility service does not announce "selected" on accessibilityState = {selected: true} of the Button Component.
Issue link - #30956

## Changelog

<!-- Help reviewers and the release process by writing your own changelog entry. For an example, see:
https://github.com/facebook/react-native/wiki/Changelog
-->

[General] [Added] - Add accessibilityState prop to Slider component

Pull Request resolved: #31145

Test Plan:
Verified accessibility states are read by voiceover and talkback. Some state values aren't handled by iOS and have been identified.

Added snapshot tests to test accessibilityState.disabled = disabled values

`js1 test Slider-test`

Reviewed By: yungsters

Differential Revision: D28337723

Pulled By: lunaleaps

fbshipit-source-id: 72a54d8d9dcf1fafb9785c81da99f32a21f3df00
  • Loading branch information
Sladyn Nunes authored and facebook-github-bot committed May 21, 2021
1 parent 0aa1aa6 commit 35dd861
Show file tree
Hide file tree
Showing 4 changed files with 210 additions and 1 deletion.
14 changes: 13 additions & 1 deletion Libraries/Components/Slider/Slider.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import StyleSheet, {
import type {ImageSource} from '../../Image/ImageSource';
import type {ViewProps} from '../View/ViewPropTypes';
import type {SyntheticEvent} from '../../Types/CoreEventTypes';
import type {AccessibilityState} from '../View/ViewAccessibility';

type Event = SyntheticEvent<
$ReadOnly<{|
Expand Down Expand Up @@ -131,6 +132,11 @@ type Props = $ReadOnly<{|
* Used to locate this view in UI automation tests.
*/
testID?: ?string,

/**
Indicates to accessibility services that UI Component is in a specific State.
*/
accessibilityState?: ?AccessibilityState,
|}>;

/**
Expand Down Expand Up @@ -200,7 +206,6 @@ const Slider = (
const style = StyleSheet.compose(styles.slider, props.style);

const {
disabled = false,
value = 0.5,
minimumValue = 0,
maximumValue = 1,
Expand Down Expand Up @@ -230,9 +235,16 @@ const Slider = (
}
: null;

const disabled =
props.disabled === true || props.accessibilityState?.disabled === true;
const accessibilityState = disabled
? {...props.accessibilityState, disabled: true}
: props.accessibilityState;

return (
<SliderNativeComponent
{...localProps}
accessibilityState={accessibilityState}
// TODO: Reconcile these across the two platforms.
enabled={!disabled}
disabled={disabled}
Expand Down
37 changes: 37 additions & 0 deletions Libraries/Components/__tests__/Slider-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* 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.
*
* @flow
* @format
*/

import * as React from 'react';
import ReactTestRenderer from 'react-test-renderer';
import Slider from '../Slider/Slider';

describe('<Slider />', () => {
it('should render as expected', () => {
expect(ReactTestRenderer.create(<Slider />)).toMatchSnapshot();
});

it('should set disabled as false', () => {
// Slider component should set disabled prop as false by default
expect(ReactTestRenderer.create(<Slider />)).toMatchSnapshot();
expect(
ReactTestRenderer.create(
<Slider accessibilityState={{disabled: false}} />,
),
).toMatchSnapshot();
});
it('should set disabled as true', () => {
expect(ReactTestRenderer.create(<Slider disabled />)).toMatchSnapshot();
expect(
ReactTestRenderer.create(
<Slider accessibilityState={{disabled: true}} />,
),
).toMatchSnapshot();
});
});
121 changes: 121 additions & 0 deletions Libraries/Components/__tests__/__snapshots__/Slider-test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<Slider /> should render as expected 1`] = `
<RCTSlider
disabled={false}
enabled={true}
maximumValue={1}
minimumValue={0}
onChange={null}
onResponderTerminationRequest={[Function]}
onSlidingComplete={null}
onStartShouldSetResponder={[Function]}
onValueChange={null}
step={0}
style={
Object {
"height": 40,
}
}
value={0.5}
/>
`;

exports[`<Slider /> should set disabled as false 1`] = `
<RCTSlider
disabled={false}
enabled={true}
maximumValue={1}
minimumValue={0}
onChange={null}
onResponderTerminationRequest={[Function]}
onSlidingComplete={null}
onStartShouldSetResponder={[Function]}
onValueChange={null}
step={0}
style={
Object {
"height": 40,
}
}
value={0.5}
/>
`;

exports[`<Slider /> should set disabled as false 2`] = `
<RCTSlider
accessibilityState={
Object {
"disabled": false,
}
}
disabled={false}
enabled={true}
maximumValue={1}
minimumValue={0}
onChange={null}
onResponderTerminationRequest={[Function]}
onSlidingComplete={null}
onStartShouldSetResponder={[Function]}
onValueChange={null}
step={0}
style={
Object {
"height": 40,
}
}
value={0.5}
/>
`;

exports[`<Slider /> should set disabled as true 1`] = `
<RCTSlider
accessibilityState={
Object {
"disabled": true,
}
}
disabled={true}
enabled={false}
maximumValue={1}
minimumValue={0}
onChange={null}
onResponderTerminationRequest={[Function]}
onSlidingComplete={null}
onStartShouldSetResponder={[Function]}
onValueChange={null}
step={0}
style={
Object {
"height": 40,
}
}
value={0.5}
/>
`;

exports[`<Slider /> should set disabled as true 2`] = `
<RCTSlider
accessibilityState={
Object {
"disabled": true,
}
}
disabled={true}
enabled={false}
maximumValue={1}
minimumValue={0}
onChange={null}
onResponderTerminationRequest={[Function]}
onSlidingComplete={null}
onStartShouldSetResponder={[Function]}
onValueChange={null}
step={0}
style={
Object {
"height": 40,
}
}
value={0.5}
/>
`;
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const {
TouchableWithoutFeedback,
Alert,
StyleSheet,
Slider,
Platform,
} = require('react-native');
import type {EventSubscription} from 'react-native/Libraries/vendor/emitter/EventEmitter';
Expand Down Expand Up @@ -696,6 +697,38 @@ class AccessibilityActionsExample extends React.Component<{}> {
}
}

function SliderAccessibilityExample(): React.Node {
return (
<View>
<RNTesterBlock
title="Disabled Slider via disabled"
description="Verify with TalkBack/VoiceOver announces Slider as disabled">
<Slider value={25} maximumValue={100} minimumValue={0} disabled />
</RNTesterBlock>
<RNTesterBlock
title="Disabled Slider via accessibiltyState"
description="Verify with TalkBack/VoiceOver announces Slider as disabled">
<Slider
value={75}
maximumValue={100}
minimumValue={0}
accessibilityState={{disabled: true}}
/>
</RNTesterBlock>
<RNTesterBlock
title="Selected Slider"
description="Verify with TalkBack/VoiceOver announces Slider as selected">
<Slider
value={75}
maximumValue={100}
minimumValue={0}
accessibilityState={{selected: true}}
/>
</RNTesterBlock>
</View>
);
}

type FakeSliderExampleState = {
current: number,
textualValue: 'center' | 'left' | 'right',
Expand Down Expand Up @@ -970,6 +1003,12 @@ exports.examples = [
return <AccessibilityActionsExample />;
},
},
{
title: 'Slider Accessibility Examples',
render(): React.Element<typeof SliderAccessibilityExample> {
return <SliderAccessibilityExample />;
},
},
{
title: 'Fake Slider Example',
render(): React.Element<typeof FakeSliderExample> {
Expand Down

0 comments on commit 35dd861

Please sign in to comment.