Skip to content

Commit

Permalink
feat: Add role prop to Text component
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrieldonadel committed Oct 14, 2022
1 parent 26da3ae commit 4799069
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 68 deletions.
69 changes: 1 addition & 68 deletions Libraries/Components/View/View.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {ViewProps} from './ViewPropTypes';

import flattenStyle from '../../StyleSheet/flattenStyle';
import TextAncestor from '../../Text/TextAncestor';
import {roleToAccessibilityRoleMapping} from '../../Utilities/AcessibilityMapping';
import ViewNativeComponent from './ViewNativeComponent';
import * as React from 'react';

Expand Down Expand Up @@ -80,74 +81,6 @@ const View: React.AbstractComponent<
text: ariaValueText ?? accessibilityValue?.text,
};

// Map role values to AccessibilityRole values
const roleToAccessibilityRoleMapping = {
alert: 'alert',
alertdialog: undefined,
application: undefined,
article: undefined,
banner: undefined,
button: 'button',
cell: undefined,
checkbox: 'checkbox',
columnheader: undefined,
combobox: 'combobox',
complementary: undefined,
contentinfo: undefined,
definition: undefined,
dialog: undefined,
directory: undefined,
document: undefined,
feed: undefined,
figure: undefined,
form: undefined,
grid: 'grid',
group: undefined,
heading: 'header',
img: 'image',
link: 'link',
list: 'list',
listitem: undefined,
log: undefined,
main: undefined,
marquee: undefined,
math: undefined,
menu: 'menu',
menubar: 'menubar',
menuitem: 'menuitem',
meter: undefined,
navigation: undefined,
none: 'none',
note: undefined,
presentation: 'none',
progressbar: 'progressbar',
radio: 'radio',
radiogroup: 'radiogroup',
region: undefined,
row: undefined,
rowgroup: undefined,
rowheader: undefined,
scrollbar: 'scrollbar',
searchbox: 'search',
separator: undefined,
slider: 'adjustable',
spinbutton: 'spinbutton',
status: undefined,
summary: 'summary',
switch: 'switch',
tab: 'tab',
table: undefined,
tablist: 'tablist',
tabpanel: undefined,
term: undefined,
timer: 'timer',
toolbar: 'toolbar',
tooltip: undefined,
tree: undefined,
treegrid: undefined,
treeitem: undefined,
};

const flattenedStyle = flattenStyle(style);
const newPointerEvents = flattenedStyle?.pointerEvents || pointerEvents;

Expand Down
71 changes: 71 additions & 0 deletions Libraries/Components/View/ViewAccessibility.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ export interface AccessibilityProps

'aria-live'?: ('polite' | 'assertive' | 'off') | undefined;
'aria-modal'?: boolean | undefined;

/**
* Indicates to accessibility services to treat UI component like a specific role.
*/
role?: Role;
}

export type AccessibilityActionInfo = Readonly<{
Expand Down Expand Up @@ -286,3 +291,69 @@ export interface AccessibilityPropsIOS {
*/
accessibilityIgnoresInvertColors?: boolean | undefined;
}

export type Role =
| 'alert'
| 'alertdialog'
| 'application'
| 'article'
| 'banner'
| 'button'
| 'cell'
| 'checkbox'
| 'columnheader'
| 'combobox'
| 'complementary'
| 'contentinfo'
| 'definition'
| 'dialog'
| 'directory'
| 'document'
| 'feed'
| 'figure'
| 'form'
| 'grid'
| 'group'
| 'heading'
| 'img'
| 'link'
| 'list'
| 'listitem'
| 'log'
| 'main'
| 'marquee'
| 'math'
| 'menu'
| 'menubar'
| 'menuitem'
| 'meter'
| 'navigation'
| 'none'
| 'note'
| 'presentation'
| 'progressbar'
| 'radio'
| 'radiogroup'
| 'region'
| 'row'
| 'rowgroup'
| 'rowheader'
| 'scrollbar'
| 'searchbox'
| 'separator'
| 'slider'
| 'spinbutton'
| 'status'
| 'summary'
| 'switch'
| 'tab'
| 'table'
| 'tablist'
| 'tabpanel'
| 'term'
| 'timer'
| 'toolbar'
| 'tooltip'
| 'tree'
| 'treegrid'
| 'treeitem';
9 changes: 9 additions & 0 deletions Libraries/Text/Text.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {NativeText, NativeVirtualText} from './TextNativeComponent';
import {type TextProps} from './TextProps';
import * as React from 'react';
import {useContext, useMemo, useState} from 'react';
import {roleToAccessibilityRoleMapping} from '../Utilities/AcessibilityMapping';

/**
* Text is the fundamental component for displaying text.
Expand All @@ -34,6 +35,7 @@ const Text: React.AbstractComponent<
const {
accessible,
accessibilityLabel,
accessibilityRole,
allowFontScaling,
'aria-busy': ariaBusy,
'aria-checked': ariaChecked,
Expand All @@ -55,6 +57,7 @@ const Text: React.AbstractComponent<
onResponderTerminationRequest,
onStartShouldSetResponder,
pressRetentionOffset,
role,
suppressHighlighting,
...restProps
} = props;
Expand Down Expand Up @@ -225,6 +228,9 @@ const Text: React.AbstractComponent<
accessibilityState={_accessibilityState}
{...eventHandlersForText}
accessibilityLabel={ariaLabel ?? accessibilityLabel}
accessibilityRole={
role ? roleToAccessibilityRoleMapping[role] : accessibilityRole
}
isHighlighted={isHighlighted}
isPressable={isPressable}
selectable={_selectable}
Expand All @@ -248,6 +254,9 @@ const Text: React.AbstractComponent<
}
accessibilityLabel={ariaLabel ?? accessibilityLabel}
accessibilityState={nativeTextAccessibilityState}
accessibilityRole={
role ? roleToAccessibilityRoleMapping[role] : accessibilityRole
}
allowFontScaling={allowFontScaling !== false}
ellipsizeMode={ellipsizeMode ?? 'tail'}
isHighlighted={isHighlighted}
Expand Down
6 changes: 6 additions & 0 deletions Libraries/Text/TextProps.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import type {
AccessibilityActionInfo,
AccessibilityRole,
AccessibilityState,
Role,
} from '../Components/View/ViewAccessibility';
import type {TextStyleProp} from '../StyleSheet/StyleSheet';
import type {
Expand Down Expand Up @@ -176,6 +177,11 @@ export type TextProps = $ReadOnly<{|
*/
pressRetentionOffset?: ?PressRetentionOffset,

/**
* Indicates to accessibility services to treat UI component like a specific role.
*/
role?: ?Role,

/**
* Lets the user select text.
*
Expand Down
79 changes: 79 additions & 0 deletions Libraries/Utilities/AcessibilityMapping.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/

'use strict';

// Map role values to AccessibilityRole values
export const roleToAccessibilityRoleMapping = {
alert: 'alert',
alertdialog: undefined,
application: undefined,
article: undefined,
banner: undefined,
button: 'button',
cell: undefined,
checkbox: 'checkbox',
columnheader: undefined,
combobox: 'combobox',
complementary: undefined,
contentinfo: undefined,
definition: undefined,
dialog: undefined,
directory: undefined,
document: undefined,
feed: undefined,
figure: undefined,
form: undefined,
grid: 'grid',
group: undefined,
heading: 'header',
img: 'image',
link: 'link',
list: 'list',
listitem: undefined,
log: undefined,
main: undefined,
marquee: undefined,
math: undefined,
menu: 'menu',
menubar: 'menubar',
menuitem: 'menuitem',
meter: undefined,
navigation: undefined,
none: 'none',
note: undefined,
presentation: 'none',
progressbar: 'progressbar',
radio: 'radio',
radiogroup: 'radiogroup',
region: undefined,
row: undefined,
rowgroup: undefined,
rowheader: undefined,
scrollbar: 'scrollbar',
searchbox: 'search',
separator: undefined,
slider: 'adjustable',
spinbutton: 'spinbutton',
status: undefined,
summary: 'summary',
switch: 'switch',
tab: 'tab',
table: undefined,
tablist: 'tablist',
tabpanel: undefined,
term: undefined,
timer: 'timer',
toolbar: 'toolbar',
tooltip: undefined,
tree: undefined,
treegrid: undefined,
treeitem: undefined,
};
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@ class AccessibilityExample extends React.Component<{}> {
<Text accessibilityRole="header">This is a title.</Text>
</RNTesterBlock>

<RNTesterBlock title="Text with role = heading">
<Text role="heading">This is a title.</Text>
</RNTesterBlock>

<RNTesterBlock title="Touchable with accessibilityRole = link">
<TouchableOpacity
onPress={() => Alert.alert('Link has been clicked!')}
Expand Down

0 comments on commit 4799069

Please sign in to comment.