Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal for various cross platform a11y improvements. #56

Conversation

marcmulcahy
Copy link

This proposal describes various cross platform improvements supported by most platforms.

@kelset kelset added the 💡 Proposal This label identifies a proposal label Nov 16, 2018
Copy link

@necolas necolas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to see others thinking about how to add more accessibility features. I've been coming at this same problem from the perspective of web, where there are perhaps greater constraints on what is possible in some cases, and clearer standards in others.

Properties only available on iOS include:

* accessibilityViewIsModal
* accessibilityElementsHidden
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is similar to Android importantForAccessibility prop. It would be good to consolidate these together and learn from how web handles these cases

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps something like ARIA hiden would be adequate. Android's importantForAccessibility is a bad model to emulate-- it includes yes, no, and auto as values. Auto is the default I believe, and from the developer's point of view, is hard to use, since the rules for when something is automatically marked as unimportant for accessibility aren't clear. I think a better model is to assume everything is important for accessibility, unless explicitly marked otherwise. So it seems like some notion of hidden is adequate.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think we should make accessibilityElementsHidden cross-platform? Mapping to aria-hidden on web and equivalent on Android?


Properties only available on Android include:

* accessibilityLiveRegion
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also available on web

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could standardize on ARIA's notion of a live region, and then dumb down the implementation to the various platforms. Android's notion of a live region is pretty basic (polite or assertive). iOS has no notion of live regions as far as I know, so we'd have to use iOS primitives to implement a subset of live region functionality.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

accessibilityLiveRegion is essentially already identical to ARIA live region, there's just a different in what the none state is called. So you could extend support for the existing API to iOS and then we'll have the 3 main platforms covered.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 on the accessibilityLiveRegion property being more universal. We just implemented this for Windows (see PR here).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for accessibilityLiveRegion on iOS

Several properties are missing from both platforms:

* accessibilityCompoundComponent: replace accessible-- indicates to assistive technologies that all the components inside this one should be treated as a single component.
* accessibilityRelationships: describes how this component is related to others
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a proposal internally that is based on Web's ARIA properties: accessibilityLabelID (equivalent to aria-labelledby), accessibilityDescriptionID (equivalent to aria-describedby), and accessibilityFocusID (equivalent to aria-activedescendent). All these props would take the value of the nativeID of the element they are associated with.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. From naming point of view, are you in favor of using the ARIA namespace, or creating our own properties based on ARIA?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean by "ARIA namespace"? Something like accessibilityLabelledBy vs accessibilityLabelID?


* accessibilityCompoundComponent: replace accessible-- indicates to assistive technologies that all the components inside this one should be treated as a single component.
* accessibilityRelationships: describes how this component is related to others
* accessibilityRange: expose information about range-based components such as sliders
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can probably learn from web here and expose the range props to the underlying accessibility layer of the platform. Or model this off ARIA props for progressbar etc

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've found that in practice, exposing range information in a consumable way is fairly difficult. Exposing a minimum, current, and maximum value allow you to speak a percentage, which is fine for some types of progress bars. But for others, where the actual value is relevant (say a color contrast setting, stereo balance control, movie timeline slider, etc.) it would be nice to include some information that could cause the screen reader to speak either a string or the current value instead of a percentage. Slider's also imply programatic actions to adjust them.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But for others, where the actual value is relevant (say a color contrast setting, stereo balance control, movie timeline slider, etc.) it would be nice to include some information that could cause the screen reader to speak either a string or the current value instead of a percentage.

ARIA has a property for that aria-valuetext - https://www.w3.org/TR/wai-aria-practices/examples/slider/slider-2.html

I do like how understandable and extensible the accessibilityRelationships and accessibilityRange props names are vs having many more individual props ARIA.

Are you thinking it would look something like this (property names tbh for relationships)?

<View
  accessibilityRange={{ min, max, current, text }}
  accessibilityRelationships={{ labelID, descriptionID, focusID }}
/>


### accessibilityCompoundComponent

We think the current implementation, which is called "accessible", should be renamed to accessibilityCompoundComponent, to more accurately represent what it does. The functionality should remain the same.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The behaviour of accessible has always felt a bit ambiguous to me, as on Android and Web it's equivalent to focusable. I don't think accessibilityCompoundComponent is any clearer a name than accessible

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the whole notion of compound component handling needs quite a bit more thought. My main opposition to calling this accessible is that it's misleading-- it has little to do with whether the component is accessible, and almost everything to do with how assistive technologies should treat the component.

Maybe I should drop this from this proposal, and make a separate proposal covering compound component handling? I'm thinking as a start about containers with multiple children, which we want to treat as a single item, but depending on the container layout, perhaps only one child is clickable and should be manipulated when the screen reader double taps, etc.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I should drop this from this proposal, and make a separate proposal covering compound component handling?

I think that sounds good. The idea of an accessibility group is something that's a little complicated on web too, because you have both screen-reader accessibility and keyboard accessibility.

* labeledBy: this component is labeled by the specified component
* describedBy: this component is described by the specified components.

When referring to other components, we may need to add an additional property to view-- namely accessibilityId. We need to find the best forward-looking approach for referencing other components.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have nativeID that we can use for this

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, when was this nativeID property introduced? Trying to understand backward compatibility.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like it was introduced for both platforms here in June 2017 facebook/react-native@70e0455


We think the current implementation, which is called "accessible", should be renamed to accessibilityCompoundComponent, to more accurately represent what it does. The functionality should remain the same.

### accessibilityRelationships
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this API look like in practice? Is the value an object?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're referring to compound component handling, I think the answer is yes. perhaps a separate proposal would let us discuss and flesh out exactly how to do this.

Relationships could be an object, or each relationship could be a separate property. We've found it sometimes useful for a relationship to include multiple targets-- for example, cases where multiple components describe a single component.

@necolas
Copy link

necolas commented Nov 16, 2018

For context, Twitter uses React Native to implement their PWA. The RN abstractions (which have web DNA) are considerably better for building modern web apps that straight DOM abstractions. However, Twitter relies on an undocumented feature of React Native for Web that passes aria-* props to the underlying DOM node to work around the missing accessibility features in React Native. Your proposals cover almost exactly the same problems that Twitter has from a web context and that I started bringing up at Facebook. So I'm really happy to see that Amazon is interested in improving the native accessibility story and would like to help make sure that the API maps cleanly to the web's comprehensive accessibility features (which influenced the introduction of accessibilityRole and accessibilityStates).

Properties only available on iOS include:

* accessibilityViewIsModal
* accessibilityElementsHidden
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think we should make accessibilityElementsHidden cross-platform? Mapping to aria-hidden on web and equivalent on Android?


Properties only available on Android include:

* accessibilityLiveRegion
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

accessibilityLiveRegion is essentially already identical to ARIA live region, there's just a different in what the none state is called. So you could extend support for the existing API to iOS and then we'll have the 3 main platforms covered.

Several properties are missing from both platforms:

* accessibilityCompoundComponent: replace accessible-- indicates to assistive technologies that all the components inside this one should be treated as a single component.
* accessibilityRelationships: describes how this component is related to others
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean by "ARIA namespace"? Something like accessibilityLabelledBy vs accessibilityLabelID?


* accessibilityCompoundComponent: replace accessible-- indicates to assistive technologies that all the components inside this one should be treated as a single component.
* accessibilityRelationships: describes how this component is related to others
* accessibilityRange: expose information about range-based components such as sliders
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But for others, where the actual value is relevant (say a color contrast setting, stereo balance control, movie timeline slider, etc.) it would be nice to include some information that could cause the screen reader to speak either a string or the current value instead of a percentage.

ARIA has a property for that aria-valuetext - https://www.w3.org/TR/wai-aria-practices/examples/slider/slider-2.html

I do like how understandable and extensible the accessibilityRelationships and accessibilityRange props names are vs having many more individual props ARIA.

Are you thinking it would look something like this (property names tbh for relationships)?

<View
  accessibilityRange={{ min, max, current, text }}
  accessibilityRelationships={{ labelID, descriptionID, focusID }}
/>


## Motivation

All accessibility properties should be available on all supported platforms. This reduces the burden on developers to understand the nuances of accessibility support on various platforms. It also allows JavaScript components to expose rich accessibility information, rather than relying on the accessibility support in native components.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


### accessibilityCompoundComponent

We think the current implementation, which is called "accessible", should be renamed to accessibilityCompoundComponent, to more accurately represent what it does. The functionality should remain the same.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I should drop this from this proposal, and make a separate proposal covering compound component handling?

I think that sounds good. The idea of an accessibility group is something that's a little complicated on web too, because you have both screen-reader accessibility and keyboard accessibility.

* labeledBy: this component is labeled by the specified component
* describedBy: this component is described by the specified components.

When referring to other components, we may need to add an additional property to view-- namely accessibilityId. We need to find the best forward-looking approach for referencing other components.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like it was introduced for both platforms here in June 2017 facebook/react-native@70e0455


This property describes how this component is related to others. Relationship types include:

* labelFor: This component labels the specified component
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a use-case you had in mind for having the relationship be defined in either direction like this?


The same documentation that is used to describe the properties on either iOS or Android can be marked as cross-platform for use on either. For the accessibilityRelationships property, labeledBy and labelFor are common paradigms across accessibility support on multiple platforms including web.

## Unresolved questions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a related question (and issue) about content that is hidden visually but visible to screen readers. Typically it will be hidden headings so they show up in the screen reader headings list (e.g., mobile.twitter.com does this) and it is visually hidden with a particular CSS incantation. Would you / how would you do something like this in native apps?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe something like this?

import React, { useEffect, useState } from 'react';
import { AccessibilityInfo, Text } from 'react-native';

const useIsScreenReaderEnabled = () => {
  const [isScreenReaderEnabled, setIsScreenReaderEnabled] = useState(false);

  useEffect(() => {
    AccessibilityInfo.addEventListener('screenReaderChanged', setIsScreenReaderEnabled);
    AccessibilityInfo.isScreenReaderEnabled().then(setIsScreenReaderEnabled);
    return () => AccessibilityInfo.removeEventListener('screenReaderChanged', setIsScreenReaderEnabled);
  }, []);

  return isScreenReaderEnabled;
};

const Example = () => {
  const isScreenReaderEnabled = useIsScreenReaderEnabled();
  return <Text>I {isScreenReaderEnabled ? 'love' : '❤️'} React Native for Web</Text>;
};

@necolas
Copy link

necolas commented Jun 5, 2023

I'm going to close this proposal as we've subsequently focused on cross-platform APIs based on the existing ARIA spec as per #496

@necolas necolas closed this Jun 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
💡 Proposal This label identifies a proposal
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants