chore: a11y polish (#9259)

This commit is contained in:
Nathan Walker
2021-03-08 10:26:01 -08:00
parent aaeab990c8
commit a822f2affb
29 changed files with 356 additions and 261 deletions

View File

@@ -6,7 +6,7 @@ import { Style } from '../../styling/style';
import { Page } from '../../page';
import { Order, FlexGrow, FlexShrink, FlexWrapBefore, AlignSelf } from '../../layouts/flexbox-layout';
import { Length } from '../../styling/style-properties';
import { Length, LengthType } from '../../styling/style-properties';
import { DOMNode } from '../../../debugger/dom-node';
/**
@@ -105,8 +105,8 @@ export interface ShowModalOptions {
export abstract class ViewBase extends Observable {
// Dynamic properties.
left: Length;
top: Length;
left: LengthType;
top: LengthType;
effectiveLeft: number;
effectiveTop: number;
dock: 'left' | 'top' | 'right' | 'bottom';

View File

@@ -815,7 +815,7 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
this._context = context;
// This will account for nativeView that is created in createNativeView, recycled
// or for backward compatability - set before _setupUI in iOS contructor.
// or for backward compatibility - set before _setupUI in iOS constructor.
let nativeView = this.nativeViewProtected;
// if (global.isAndroid) {

View File

@@ -21,7 +21,7 @@ import { AndroidActivityBackPressedEventData, android as androidApp } from '../.
import { Device } from '../../../platform';
import lazy from '../../../utils/lazy';
import { accessibilityEnabledProperty, accessibilityHiddenProperty, accessibilityHintProperty, accessibilityIdentifierProperty, accessibilityLabelProperty, accessibilityLanguageProperty, accessibilityLiveRegionProperty, accessibilityMediaSessionProperty, accessibilityRoleProperty, accessibilityStateProperty, accessibilityValueProperty } from '../../../accessibility/accessibility-properties';
import { AccessibilityLiveRegion, AccessibilityRole, AndroidAccessibilityEvent, setupAccessibleView, isAccessibilityServiceEnabled, sendAccessibilityEvent, updateAccessibilityProperties, updateContentDescription } from '../../../accessibility';
import { AccessibilityLiveRegion, AccessibilityRole, AndroidAccessibilityEvent, setupAccessibleView, isAccessibilityServiceEnabled, sendAccessibilityEvent, updateAccessibilityProperties, updateContentDescription, AccessibilityState } from '../../../accessibility';
import * as Utils from '../../../utils';
export * from './view-common';
@@ -782,6 +782,7 @@ export class View extends ViewCommon {
}
[accessibilityRoleProperty.setNative](value: AccessibilityRole): void {
this.accessibilityRole = value;
updateAccessibilityProperties(this);
if (android.os.Build.VERSION.SDK_INT >= 28) {
@@ -829,7 +830,8 @@ export class View extends ViewCommon {
}
}
[accessibilityStateProperty.setNative](): void {
[accessibilityStateProperty.setNative](value: AccessibilityState): void {
this.accessibilityState = value;
updateAccessibilityProperties(this);
}
@@ -1102,18 +1104,10 @@ export class View extends ViewCommon {
}
public accessibilityAnnouncement(msg = this.accessibilityLabel): void {
if (!isAccessibilityServiceEnabled()) {
return;
}
this.androidSendAccessibilityEvent(AndroidAccessibilityEvent.ANNOUNCEMENT, msg);
}
public accessibilityScreenChanged(): void {
if (!isAccessibilityServiceEnabled()) {
return;
}
this.androidSendAccessibilityEvent(AndroidAccessibilityEvent.WINDOW_STATE_CHANGED);
}
}

View File

@@ -6,7 +6,7 @@ import { Animation, AnimationDefinition, AnimationPromise } from '../../animatio
import { LengthType, PercentLengthType } from '../../styling/style-properties';
import { GestureTypes, GesturesObserver } from '../../gestures';
import { LinearGradient } from '../../styling/gradient';
import { AccessibilityLiveRegion, AccessibilityRole, AccessibilityState, AccessibilityTrait, AndroidAccessibilityEvent, IOSPostAccessibilityNotificationType } from '../../../accessibility/accessibility-types';
import { AccessibilityLiveRegion, AccessibilityRole, AccessibilityState, AccessibilityTrait, AccessibilityEventOptions } from '../../../accessibility/accessibility-types';
import { Enums } from '../../enums';
import { CSSShadow } from '../../styling/css-shadow';
@@ -286,7 +286,6 @@ export abstract class View extends ViewBase {
* A hint describes the elements behavior. Example: 'Tap change playback speed'
*/
accessibilityHint: string;
accessibilityTraits?: AccessibilityTrait[];
accessibilityLiveRegion: AccessibilityLiveRegion;
/**
@@ -750,17 +749,18 @@ export abstract class View extends ViewBase {
public eachChildView(callback: (view: View) => boolean): void;
/**
* Android: Send accessibility event
* Send accessibility event
* @params options AccessibilityEventOptions
* androidAccessibilityEvent: AndroidAccessibilityEvent;
* iosNotificationType: IOSPostAccessibilityNotificationType;
* message: string;
*
* iOS Notes:
* type = 'announcement' will announce `args` via VoiceOver. If no args element will be announced instead.
* type = 'layout' used when the layout of a screen changes.
* type = 'screen' large change made to the screen.
*/
public androidSendAccessibilityEvent(eventName: AndroidAccessibilityEvent, msg?: string): void;
/**
* iOS: post accessibility notification.
* type = 'announcement' will announce `args` via VoiceOver. If no args element will be announced instead.
* type = 'layout' used when the layout of a screen changes.
* type = 'screen' large change made to the screen.
*/
public iosPostAccessibilityNotification(notificationType: IOSPostAccessibilityNotificationType, msg?: string): void;
public sendAccessibilityEvent(options: Partial<AccessibilityEventOptions>): void;
/**
* Make an announcement to the screen reader.

View File

@@ -10,8 +10,8 @@ import { IOSHelper } from './view-helper';
import { ios as iosBackground, Background } from '../../styling/background';
import { perspectiveProperty, visibilityProperty, opacityProperty, rotateProperty, rotateXProperty, rotateYProperty, scaleXProperty, scaleYProperty, translateXProperty, translateYProperty, zIndexProperty, backgroundInternalProperty, clipPathProperty } from '../../styling/style-properties';
import { profile } from '../../../profiling';
import { accessibilityEnabledProperty, accessibilityHiddenProperty, accessibilityHintProperty, accessibilityIdentifierProperty, accessibilityLabelProperty, accessibilityLanguageProperty, accessibilityLiveRegionProperty, accessibilityMediaSessionProperty, accessibilityRoleProperty, accessibilityStateProperty, accessibilityTraitsProperty, accessibilityValueProperty } from '../../../accessibility/accessibility-properties';
import { setupAccessibleView, IOSPostAccessibilityNotificationType, isAccessibilityServiceEnabled, updateAccessibilityProperties } from '../../../accessibility';
import { accessibilityEnabledProperty, accessibilityHiddenProperty, accessibilityHintProperty, accessibilityIdentifierProperty, accessibilityLabelProperty, accessibilityLanguageProperty, accessibilityLiveRegionProperty, accessibilityMediaSessionProperty, accessibilityRoleProperty, accessibilityStateProperty, accessibilityValueProperty, accessibilityIgnoresInvertColorsProperty } from '../../../accessibility/accessibility-properties';
import { setupAccessibleView, IOSPostAccessibilityNotificationType, isAccessibilityServiceEnabled, updateAccessibilityProperties, AccessibilityEventOptions, AccessibilityRole, AccessibilityState } from '../../../accessibility';
import { Enums } from '../../enums';
export * from './view-common';
@@ -504,6 +504,13 @@ export class View extends ViewCommon implements ViewDefinition {
}
this._modalAnimatedOptions.push(animated);
// TODO: a11y
// controller.accessibilityViewIsModal = true;
// controller.accessibilityPerformEscape = () => {
// console.log('accessibilityPerformEscape!!')
// return true;
// }
parentController.presentViewControllerAnimatedCompletion(controller, animated, null);
const transitionCoordinator = parentController.transitionCoordinator;
if (transitionCoordinator) {
@@ -575,11 +582,8 @@ export class View extends ViewCommon implements ViewDefinition {
this.nativeViewProtected.accessibilityIdentifier = value;
}
[accessibilityRoleProperty.setNative](): void {
updateAccessibilityProperties(this);
}
[accessibilityTraitsProperty.setNative](): void {
[accessibilityRoleProperty.setNative](value: AccessibilityRole): void {
this.accessibilityRole = value;
updateAccessibilityProperties(this);
}
@@ -590,7 +594,12 @@ export class View extends ViewCommon implements ViewDefinition {
[accessibilityLabelProperty.setNative](value: string): void {
value = value == null ? null : `${value}`;
// not sure if needed for Label:
// if ((<any>this).nativeTextViewProtected) {
// (<any>this).nativeTextViewProtected.accessibilityLabel = value;
// } else {
this.nativeViewProtected.accessibilityLabel = value;
// }
}
[accessibilityHintProperty.setNative](value: string): void {
@@ -598,6 +607,11 @@ export class View extends ViewCommon implements ViewDefinition {
this.nativeViewProtected.accessibilityHint = value;
}
[accessibilityIgnoresInvertColorsProperty.setNative](value: boolean) {
console.log('accessibilityIgnoresInvertColorsProperty:', !!value);
this.nativeViewProtected.accessibilityIgnoresInvertColors = !!value;
}
[accessibilityLanguageProperty.setNative](value: string): void {
value = value == null ? null : `${value}`;
this.nativeViewProtected.accessibilityLanguage = value;
@@ -613,7 +627,8 @@ export class View extends ViewCommon implements ViewDefinition {
updateAccessibilityProperties(this);
}
[accessibilityStateProperty.setNative](): void {
[accessibilityStateProperty.setNative](value: AccessibilityState): void {
this.accessibilityState = value;
updateAccessibilityProperties(this);
}
@@ -733,8 +748,12 @@ export class View extends ViewCommon implements ViewDefinition {
}
}
public iosPostAccessibilityNotification(notificationType: IOSPostAccessibilityNotificationType, msg?: string): void {
if (!notificationType) {
public sendAccessibilityEvent(options: Partial<AccessibilityEventOptions>): void {
if (!isAccessibilityServiceEnabled()) {
return;
}
if (!options.iosNotificationType) {
return;
}
@@ -744,7 +763,7 @@ export class View extends ViewCommon implements ViewDefinition {
args = msg;
}
switch (notificationType) {
switch (options.iosNotificationType) {
case IOSPostAccessibilityNotificationType.Announcement: {
notification = UIAccessibilityAnnouncementNotification;
break;
@@ -766,19 +785,16 @@ export class View extends ViewCommon implements ViewDefinition {
}
public accessibilityAnnouncement(msg = this.accessibilityLabel): void {
if (!isAccessibilityServiceEnabled()) {
return;
}
this.iosPostAccessibilityNotification(IOSPostAccessibilityNotificationType.Announcement, msg);
this.sendAccessibilityEvent({
iosNotificationType: IOSPostAccessibilityNotificationType.Announcement,
message: msg,
});
}
public accessibilityScreenChanged(): void {
if (!isAccessibilityServiceEnabled()) {
return;
}
this.iosPostAccessibilityNotification(IOSPostAccessibilityNotificationType.Screen);
this.sendAccessibilityEvent({
iosNotificationType: IOSPostAccessibilityNotificationType.Screen,
});
}
_getCurrentLayoutBounds(): {

View File

@@ -22,9 +22,9 @@ import { StyleScope } from '../../styling/style-scope';
import { LinearGradient } from '../../styling/linear-gradient';
import * as am from '../../animation';
import { AccessibilityLiveRegion, AccessibilityRole, AccessibilityState, AccessibilityTrait, AndroidAccessibilityEvent, IOSPostAccessibilityNotificationType } from '../../../accessibility/accessibility-types';
import { accessibilityEnabledProperty, accessibilityHintProperty, accessibilityIdentifierProperty, accessibilityLabelProperty, accessibilityTraitsProperty, accessibilityValueProperty } from '../../../accessibility/accessibility-properties';
import { accessibilityBlurEvent, accessibilityFocusChangedEvent, accessibilityFocusEvent, getCurrentFontScale } from '../../../accessibility';
import { AccessibilityEventOptions, AccessibilityLiveRegion, AccessibilityRole, AccessibilityState, AccessibilityTrait } from '../../../accessibility/accessibility-types';
import { accessibilityHintProperty, accessibilityIdentifierProperty, accessibilityLabelProperty, accessibilityValueProperty, accessibilityIgnoresInvertColorsProperty } from '../../../accessibility/accessibility-properties';
import { accessibilityBlurEvent, accessibilityFocusChangedEvent, accessibilityFocusEvent, accessibilityPerformEscapeEvent, getCurrentFontScale } from '../../../accessibility';
import { CSSShadow } from '../../styling/css-shadow';
// helpers (these are okay re-exported here)
@@ -74,6 +74,12 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
public static accessibilityBlurEvent = accessibilityBlurEvent;
public static accessibilityFocusEvent = accessibilityFocusEvent;
public static accessibilityFocusChangedEvent = accessibilityFocusChangedEvent;
public static accessibilityPerformEscapeEvent = accessibilityPerformEscapeEvent;
public accessibilityIdentifier: string;
public accessibilityLabel: string;
public accessibilityValue: string;
public accessibilityHint: string;
protected _closeModalCallback: Function;
public _manager: any;
@@ -99,9 +105,6 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
_androidContentDescriptionUpdated?: boolean;
// a11y
_accessible: boolean;
get css(): string {
const scope = this._styleScope;
@@ -757,12 +760,12 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
}
get accessible(): boolean {
// return this.style.accessible;
return this._accessible;
return this.style.accessible;
// return this._accessible;
}
set accessible(value: boolean) {
// this.style.accessible = value;
this._accessible = value;
this.style.accessible = value;
// this._accessible = value;
}
get accessibilityHidden(): boolean {
@@ -772,8 +775,6 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
this.style.accessibilityHidden = value;
}
public accessibilityIdentifier: string;
get accessibilityRole(): AccessibilityRole {
return this.style.accessibilityRole;
}
@@ -788,10 +789,6 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
this.style.accessibilityState = value;
}
public accessibilityLabel: string;
public accessibilityValue: string;
public accessibilityHint: string;
get accessibilityLiveRegion(): AccessibilityLiveRegion {
return this.style.accessibilityLiveRegion;
}
@@ -813,8 +810,6 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
this.style.accessibilityMediaSession = value;
}
public accessibilityTraits?: AccessibilityTrait[];
get automationText(): string {
return this.accessibilityIdentifier;
}
@@ -1093,11 +1088,7 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
return false;
}
public androidSendAccessibilityEvent(eventName: AndroidAccessibilityEvent, msg?: string): void {
return;
}
public iosPostAccessibilityNotification(notificationType: IOSPostAccessibilityNotificationType, msg?: string): void {
public sendAccessibilityEvent(options: Partial<AccessibilityEventOptions>): void {
return;
}
@@ -1160,9 +1151,8 @@ export const iosIgnoreSafeAreaProperty = new InheritedProperty({
valueConverter: booleanConverter,
});
iosIgnoreSafeAreaProperty.register(ViewCommon);
accessibilityEnabledProperty.register(ViewCommon);
accessibilityIdentifierProperty.register(ViewCommon);
accessibilityLabelProperty.register(ViewCommon);
accessibilityValueProperty.register(ViewCommon);
accessibilityHintProperty.register(ViewCommon);
accessibilityTraitsProperty.register(ViewCommon);
accessibilityIgnoresInvertColorsProperty.register(ViewCommon);

View File

@@ -46,21 +46,21 @@ export namespace IOSHelper {
* Returns a view with viewController or undefined if no such found along the view's parent chain.
* @param view The view form which to start the search.
*/
export function getParentWithViewController(view: View): View;
export function updateAutoAdjustScrollInsets(controller: any /* UIViewController */, owner: View): void;
export function updateConstraints(controller: any /* UIViewController */, owner: View): void;
export function layoutView(controller: any /* UIViewController */, owner: View): void;
export function getParentWithViewController(view: Partial<View>): View;
export function updateAutoAdjustScrollInsets(controller: any /* UIViewController */, owner: Partial<View>): void;
export function updateConstraints(controller: any /* UIViewController */, owner: Partial<View>): void;
export function layoutView(controller: any /* UIViewController */, owner: Partial<View>): void;
export function getPositionFromFrame(frame: any /* CGRect */): { left; top; right; bottom };
export function getFrameFromPosition(position: { left; top; right; bottom }, insets?: { left; top; right; bottom }): any; /* CGRect */
export function shrinkToSafeArea(view: View, frame: any /* CGRect */): any; /* CGRect */
export function expandBeyondSafeArea(view: View, frame: any /* CGRect */): any; /* CGRect */
export function shrinkToSafeArea(view: Partial<View>, frame: any /* CGRect */): any; /* CGRect */
export function expandBeyondSafeArea(view: Partial<View>, frame: any /* CGRect */): any; /* CGRect */
export class UILayoutViewController {
public static initWithOwner(owner: WeakRef<View>): UILayoutViewController;
public static initWithOwner(owner: WeakRef<Partial<View>>): UILayoutViewController;
}
export class UIAdaptivePresentationControllerDelegateImp {
public static initWithOwnerAndCallback(owner: WeakRef<View>, whenClosedCallback: Function): UIAdaptivePresentationControllerDelegateImp;
public static initWithOwnerAndCallback(owner: WeakRef<Partial<View>>, whenClosedCallback: Function): UIAdaptivePresentationControllerDelegateImp;
}
export class UIPopoverPresentationControllerDelegateImp {
public static initWithOwnerAndCallback(owner: WeakRef<View>, whenClosedCallback: Function): UIPopoverPresentationControllerDelegateImp;
public static initWithOwnerAndCallback(owner: WeakRef<Partial<View>>, whenClosedCallback: Function): UIPopoverPresentationControllerDelegateImp;
}
}

View File

@@ -1,7 +1,7 @@
import { Observable, EventData } from '../../../data/observable';
const handlersForEventName = new Map<string, (eventData: EventData) => void>();
const sourcesMap = new WeakMap<Observable, Map<string, Array<TargetHandlerPair>>>();
const sourcesMap = new WeakMap<Partial<Observable>, Map<string, Array<TargetHandlerPair>>>();
class TargetHandlerPair {
tagetRef: WeakRef<Object>;