react-native icon indicating copy to clipboard operation
react-native copied to clipboard

Accessibility gesture, swipe right, sends accessibilityAction "increment"

Open Katedam opened this issue 5 years ago • 2 comments

Description

Using a 7" Amazon Fire tablet v6.0 & v7.0 with VoiceView enabled, components with the following props, accessibilityRole="adjustable", accessibilityActions=[{ name: "increment" }, { name: "decrement"}], and onAccessibilityAction={callback}, announce to the user to swipe up or down to increment. When a user swipes right to navigate to the next item on the screen, the accessibilityAction "increment" is dispatched and therefore the callback is run which increments the adjustable component without user intent. There is no way to differentiate between the swipe up "increment" event and the swipe right "increment" event. It should not be dispatching this event at all on a swipe right.

Works as expected on iOS using VoiceOver and other android devices using TalkBack.

On the Fire tablet, there are sliders built into the device's settings screen and those work as expected with VoiceView. This makes me think that it's the RN layer that is causing this bug.

React Native version:

0.63.2

Steps To Reproduce

Provide a detailed list of steps that reproduce the issue.

  1. Turn on an Amazon Fire tablet (7" v7.0)
  2. open an app with an adjustable component such as a slider that has accessibility actions enabled aka accessibilityRole="adjustable", accessibilityActions=[{ name: "increment" }, { name: "decrement"}], and onAccessibilityAction={callback}
  3. Turn on VoiceView (the fire tablet's screen reader)
  4. Adjust the component by swiping up or down
  5. Navigate to the next item on the screen by swiping right
  6. View that the slider/adjustable component increments by one increment

Expected Results

I expect for the slider to remain at the value that the last up/down swipe put it in and for the swipe right to only navigate to the next element without affecting the adjustable element.

Snack, code example, screenshot, or link to a repository:

  const handleSwipeForA11y = (event: AccessibilityActionEvent) => {
    switch (event.nativeEvent.actionName) {
      case "increment":
        onA11ySwipeUp();
        break;
      case "decrement":
        onA11ySwipeDown();
    }
  };

<View
      accessible
      accessibilityRole="adjustable"
      accessibilityLabel={"I am a slider"}
      accessibilityValue={{ min: 0, max: 100, now: 0 }}
      accessibilityActions={[{ name: "increment" }, { name: "decrement"}]}
      onAccessibilityAction={handleSwipeForA11y}
    >
        <SliderJS // This slider component is from an open source lib
          testID={`${testID}-newSlider`}
          step={step}
          minimumValue={minValue}
          maximumValue={maxValue}
          onValueChange={onChange}
          onSlidingComplete={onComplete}
          value={value}
          thumbTintColor={color}
          minimumTrackTintColor={color}
          thumbStyle={styles.thumb}
          trackStyle={styles.track}
        />
</View>

Katedam avatar Sep 30 '20 23:09 Katedam

After a deep dive into react-native-slider, which is where SliderJS comes from, I discovered that SliderJS actually takes custom props (not apparent after glancing over their docs) as {...other}. I was able to move all of the accessibility props from the View wrapper to the component which fixed this issue of the "increment" accessibility action event firing on swipe right. Under the hood, SliderJS is just another View so I'm really not sure why moving the props from one View to another ended up being the work around but...there ya go.

<SliderJS
      accessible
      accessibilityRole="adjustable"
      accessibilityLabel={"I am a slider"}
      accessibilityValue={{ min: 0, max: 100, now: 0 }}
      accessibilityActions={[{ name: "increment" }, { name: "decrement"}]}
      onAccessibilityAction={handleSwipeForA11y}
      testID={`${testID}-newSlider`}
      step={step}
      minimumValue={minValue}
      maximumValue={maxValue}
      onValueChange={onChange}
      onSlidingComplete={onComplete}
      value={value}
      thumbTintColor={color}
      minimumTrackTintColor={color}
      thumbStyle={styles.thumb}
      trackStyle={styles.track}
/>

I would be really interested if anyone has any theories on what was actually happening with this...

Katedam avatar Oct 01 '20 23:10 Katedam

I had a similar issue in which I was marking a View as "adjustable" to implement an accessible slider. TalkBack wouldn't let me use volume controls to update the slider value. It turns out it was because I had children elements in my View that were also accessible. Once I moved those children to siblings, TalkBack was able to interaact with the slider as expected

awinograd avatar Oct 16 '20 14:10 awinograd

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.

github-actions[bot] avatar Aug 05 '23 05:08 github-actions[bot]

This issue was closed because it has been stalled for 7 days with no activity.

github-actions[bot] avatar Aug 12 '23 05:08 github-actions[bot]