Skip to content

Commit

Permalink
fix: [#173769898] fix accessibility for loadingerrorcomponent (#2043)
Browse files Browse the repository at this point in the history
* [#173769744] Add accessibility focus for InfoScreenComponent

* [#173769898] improve accessibility for LoadingErrorComponent

* change spinner with activity indicator and refactoring

Co-authored-by: Matteo Boschi <[email protected]>
  • Loading branch information
fabriziofff and Undermaken authored Jul 14, 2020
1 parent 21047ff commit 1ad1dcf
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 22 deletions.
30 changes: 27 additions & 3 deletions ts/components/screens/GenericErrorComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { fromNullable } from "fp-ts/lib/Option";
import { Content, Text, View } from "native-base";
import * as React from "react";
import { Image, ImageSourcePropType, StyleSheet } from "react-native";
import { NavigationEvents } from "react-navigation";
import I18n from "../../i18n";
import customVariables from "../../theme/variables";
import { setAccessibilityFocus } from "../../utils/accessibility";
import { SingleButton, TwoButtonsInlineHalf } from "../ui/BlockButtons";
import FooterWithButtons from "../ui/FooterWithButtons";

Expand All @@ -28,6 +31,8 @@ const styles = StyleSheet.create({
});

export default class GenericErrorComponent extends React.PureComponent<Props> {
private elementRef = React.createRef<View>();

private renderFooterButtons = () => {
const footerProps1: TwoButtonsInlineHalf = {
type: "TwoButtonsInlineHalf",
Expand Down Expand Up @@ -60,8 +65,17 @@ export default class GenericErrorComponent extends React.PureComponent<Props> {
};

public render() {
// accessible if undefined (default error subtext) or text length > 0
const subTextAccessible = fromNullable(this.props.subText).fold(
true,
text => text.length > 0
);

return (
<React.Fragment>
<NavigationEvents
onDidFocus={() => setAccessibilityFocus(this.elementRef)}
/>
<Content bounces={false}>
<View style={styles.center}>
<View spacer={true} extralarge={true} />
Expand All @@ -72,15 +86,25 @@ export default class GenericErrorComponent extends React.PureComponent<Props> {
}
/>
<View spacer={true} />
<Text bold={true} alignCenter={true} style={styles.errorText}>
<Text
bold={true}
alignCenter={true}
style={styles.errorText}
ref={this.elementRef}
>
{this.props.text
? this.props.text
: I18n.t("wallet.errors.GENERIC_ERROR")}
</Text>
<View spacer={true} extralarge={true} />
<View spacer={true} extralarge={true} />
<Text alignCenter={true} style={styles.errorText2}>
{this.props.subText

<Text
alignCenter={true}
style={styles.errorText2}
accessible={subTextAccessible}
>
{this.props.subText !== undefined
? this.props.subText
: I18n.t("wallet.errorTransaction.submitBugText")}
</Text>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,52 @@
import { Millisecond } from "italia-ts-commons/lib/units";
import { View } from "native-base";
import * as React from "react";
import { SafeAreaView } from "react-native";
import { withLoadingSpinner } from "../../../../components/helpers/withLoadingSpinner";
import { useEffect } from "react";
import { ActivityIndicator, SafeAreaView } from "react-native";
import GenericErrorComponent from "../../../../components/screens/GenericErrorComponent";
import { setAccessibilityFocus } from "../../../../utils/accessibility";
import { InfoScreenComponent } from "../infoScreen/InfoScreenComponent";
import { bonusVacanzeStyle } from "../Styles";

export type LoadingErrorProps = {
isLoading: boolean;
loadingCaption?: string;
loadingOpacity?: number;
loadingCaption: string;
errorText?: string;
onRetry: () => void;
onAbort?: () => void;
};

const errorRef = React.createRef<GenericErrorComponent>();
const loadingRef = React.createRef<React.Component>();

const renderError = (props: LoadingErrorProps) => (
<GenericErrorComponent
onRetry={props.onRetry}
onCancel={props.onAbort}
text={props.errorText}
subText={""}
ref={errorRef}
/>
);

const renderLoading = (loadingCaption: string) => (
<View accessible={true} ref={loadingRef} style={{ flex: 1 }}>
<InfoScreenComponent
image={
<ActivityIndicator
color={"black"}
accessible={false}
importantForAccessibility={"no-hide-descendants"}
accessibilityElementsHidden={true}
/>
}
title={loadingCaption}
/>
</View>
);

const delay = 100 as Millisecond;

/**
* This component is a generic error component composed with a loading.
* In this way it is testable regardless of how it will be connected to the application flow.
Expand All @@ -23,21 +57,21 @@ export type LoadingErrorProps = {
* @param props
* @constructor
*/
const InnerLoadingErrorComponent: React.FunctionComponent<
export const LoadingErrorComponent: React.FunctionComponent<
LoadingErrorProps
> = props => {
useEffect(
() => {
setAccessibilityFocus(props.isLoading ? loadingRef : errorRef, delay);
},
[props.isLoading]
);

return (
<SafeAreaView style={bonusVacanzeStyle.flex}>
<GenericErrorComponent
onRetry={props.onRetry}
onCancel={props.onAbort}
text={props.errorText}
subText={" "}
/>
{props.isLoading
? renderLoading(props.loadingCaption)
: renderError(props)}
</SafeAreaView>
);
};

export const LoadingErrorComponent = withLoadingSpinner(
InnerLoadingErrorComponent
);
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ const LoadActivateBonusScreen: React.FunctionComponent<Props> = props => {
<LoadingErrorComponent
{...props}
loadingCaption={loadingCaption}
loadingOpacity={1}
onAbort={() => abortBonusRequest(props.onAbort)}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ const LoadBonusEligibilityScreen: React.FunctionComponent<Props> = props => {
<LoadingErrorComponent
{...props}
loadingCaption={loadingCaption}
loadingOpacity={1}
onAbort={() => abortBonusRequest(props.onAbort)}
/>
);
Expand Down
3 changes: 1 addition & 2 deletions ts/utils/accessibility.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { fromNullable } from "fp-ts/lib/Option";
import { tryCatch } from "fp-ts/lib/Task";
import { Millisecond } from "italia-ts-commons/lib/units";
import { View } from "native-base";
import * as React from "react";
import {
AccessibilityInfo,
Expand All @@ -16,7 +15,7 @@ import {
* @param nodeReference
* @param executionDelay
*/
export const setAccessibilityFocus = <T extends View>(
export const setAccessibilityFocus = <T extends React.Component>(
nodeReference: React.RefObject<T>,
executionDelay: Millisecond = 0 as Millisecond // default: execute immediately
) => {
Expand Down

0 comments on commit 1ad1dcf

Please sign in to comment.