Skip to content

Correct way to move accessibility focus #37015

@robertKozik

Description

@robertKozik

Description

On my project I want to move the accessibility (f.e. VoiceOver) focus on a different component, but I can't find any good, well documented, approach. The use-case is f.e. that after clicking the button I want to open the modal and focus proper component inside that modal.

I found two different solutions, but both of them has some flaws:

  • Move focus with help of AccessibilityInfo.setAccessibilityFocus . But this method requires reactTag which can be only obtained with deprecated findNodeHandle function
  • Use AccessibilityInfo.sendAccessibilityEvent passing "focus" and component ref. The problem with this one is that it's not documented method.

In documentation I've also found the usage on focus() method on ref, but it's not defined on the accessible and focusable View component (No command found with name "focus").

What is the correct way of moving accessibility focus in "post-findNodeHandle" world?

React Native Version

0.70.5

Output of npx react-native info

System:
OS: macOS 13.1
CPU: (10) arm64 Apple M1 Pro
Memory: 72.63 MB / 16.00 GB
Shell: 5.8.1 - /bin/zsh
Binaries:
Node: 19.7.0 - ~/.nvm/versions/node/v19.7.0/bin/node
Yarn: 1.22.19 - ~/.yarn/bin/yarn
npm: 9.5.1 - ~/.nvm/versions/node/v19.7.0/bin/npm
Watchman: 2023.02.13.00 - /opt/homebrew/bin/watchman
Managers:
CocoaPods: 1.11.3 - /usr/local/bin/pod
SDKs:
iOS SDK:
Platforms: DriverKit 22.2, iOS 16.2, macOS 13.1, tvOS 16.1, watchOS 9.1
Android SDK: Not Found
IDEs:
Android Studio: 2021.2 AI-212.5712.43.2112.8815526
Xcode: 14.2/14C18 - /usr/bin/xcodebuild
Languages:
Java: 11.0.14.1 - /usr/bin/javac
npmPackages:
@react-native-community/cli: Not Found
react: 18.1.0 => 18.1.0
react-native: 0.70.5 => 0.70.5
react-native-macos: Not Found
npmGlobalPackages:
react-native: Not Found

Steps to reproduce

  1. Add to your app 2 accessible views, and the Pressable component which will trigger moving accessibility focus function. View, which we want to be focused programatically should be above in hierarchy to button, the other one should be below it.
  2. Turn on the screen reader functionality (on iOS it would be VoiceOver)
  3. Click the button with screen reader on, accessibility focus should move accordingly to the defined View

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

https://snack.expo.dev/@rooobi/accessibility-focus

import * as React from 'react';
import { Text, View, StyleSheet, Pressable, AccessibilityInfo, findNodeHandle } from 'react-native';


export default function App() {
  const ref = React.useRef(null);
  return (
    <View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
      <Text ref={ref} style={{marginBottom: 60}}>
        Should be focused after clicking the button
      </Text>
        <Pressable onPress={() => {
          //move focus with AccessibilityInfo.setAccessibilityFocus
          const reactTag = findNodeHandle(ref.current);
          AccessibilityInfo.setAccessibilityFocus(reactTag);

          //move focus with AccessibilityInfo.sendAccessibilityEvent
          // AccessibilityInfo.sendAccessibilityEvent(ref.current);

          //ref.current.focus is no method
          // ref.current?.focus();
        }}>
          <Text>Click to move focus up</Text>
        </Pressable>
        <Text focusable accessible style={{marginTop: 60}}>
          Next in line to focus
        </Text>
    </View>
  );
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions