From da979ef5b5e852067faf17c940042beed5eba171 Mon Sep 17 00:00:00 2001 From: Cristiano Tofani Date: Thu, 18 Jul 2024 16:04:45 +0200 Subject: [PATCH 1/8] wip fix accessibility --- example/src/pages/Badges.tsx | 2 +- example/src/pages/ListItem.tsx | 43 +++------------- src/components/accordion/AccordionItem.tsx | 15 +++++- src/components/banner/Banner.tsx | 6 ++- src/components/checkbox/CheckboxLabel.tsx | 2 + src/components/listitems/ListItemCheckbox.tsx | 6 ++- src/components/listitems/ListItemHeader.tsx | 6 +-- src/components/listitems/ListItemInfo.tsx | 6 +-- src/components/listitems/ListItemRadio.tsx | 1 + .../listitems/ListItemRadioWithAmount.tsx | 7 ++- src/components/listitems/ListItemSwitch.tsx | 1 + src/components/modules/ModuleCheckout.tsx | 6 ++- .../progressLoader/ProgressLoader.tsx | 3 ++ src/components/radio/RadioButtonLabel.tsx | 6 ++- src/components/tag/Tag.tsx | 51 +++++++++++-------- src/components/toast/ToastProvider.tsx | 11 +++- src/components/typography/BaseTypography.tsx | 1 + 17 files changed, 99 insertions(+), 74 deletions(-) diff --git a/example/src/pages/Badges.tsx b/example/src/pages/Badges.tsx index 18e6ba9c..63c146b5 100644 --- a/example/src/pages/Badges.tsx +++ b/example/src/pages/Badges.tsx @@ -114,7 +114,7 @@ const renderTag = () => ( - + diff --git a/example/src/pages/ListItem.tsx b/example/src/pages/ListItem.tsx index 049758be..c97c2f09 100644 --- a/example/src/pages/ListItem.tsx +++ b/example/src/pages/ListItem.tsx @@ -392,21 +392,15 @@ const renderListItemAction = () => ( const renderListItemInfo = () => ( - + ( icon="psp" label="Label" value="A looong looooong looooooooong looooooooooong title" - accessibilityLabel="Empty just for testing purposes" endElement={{ type: "iconButton", componentProps: { @@ -435,7 +428,6 @@ const renderListItemInfo = () => ( icon="psp" label="Label" value="A looong looooong looooooooong looooooooooong title" - accessibilityLabel="Empty just for testing purposes" endElement={{ type: "badge", componentProps: { @@ -445,18 +437,8 @@ const renderListItemInfo = () => ( }} /> - - + + ); @@ -464,18 +446,11 @@ const renderListItemInfo = () => ( const renderListItemHeader = () => ( - - + + ( ( ( }} /> - + ); diff --git a/src/components/accordion/AccordionItem.tsx b/src/components/accordion/AccordionItem.tsx index 935c578f..a37f9ee6 100644 --- a/src/components/accordion/AccordionItem.tsx +++ b/src/components/accordion/AccordionItem.tsx @@ -26,6 +26,7 @@ import { H6 } from "../typography"; export type AccordionItem = { title: string; body: string | React.ReactNode; + accessibilityLabel?: string; icon?: IOIcons; }; @@ -75,7 +76,12 @@ export const AccordionBody = ({ children, expanded }: AccordionBody) => { ); }; -export const AccordionItem = ({ title, body, icon }: AccordionItem) => { +export const AccordionItem = ({ + title, + accessibilityLabel, + body, + icon +}: AccordionItem) => { const theme = useIOTheme(); const [expanded, setExpanded] = useState(false); @@ -115,6 +121,7 @@ export const AccordionItem = ({ title, body, icon }: AccordionItem) => { accessible={true} accessibilityRole="button" accessibilityState={{ expanded }} + accessibilityLabel={accessibilityLabel ?? title} onPress={onItemPress} > @@ -133,7 +140,11 @@ export const AccordionItem = ({ title, body, icon }: AccordionItem) => { )} - +
{title}
diff --git a/src/components/banner/Banner.tsx b/src/components/banner/Banner.tsx index 0a3aca2c..cb46653a 100644 --- a/src/components/banner/Banner.tsx +++ b/src/components/banner/Banner.tsx @@ -224,7 +224,11 @@ export const Banner = ({ {action && ( /* Disable pointer events to avoid pressed state on the button */ - + diff --git a/src/components/checkbox/CheckboxLabel.tsx b/src/components/checkbox/CheckboxLabel.tsx index f1342b22..d0630ca0 100644 --- a/src/components/checkbox/CheckboxLabel.tsx +++ b/src/components/checkbox/CheckboxLabel.tsx @@ -68,6 +68,8 @@ export const CheckboxLabel = ({ - + diff --git a/src/components/listitems/ListItemHeader.tsx b/src/components/listitems/ListItemHeader.tsx index c0057dd1..c550823b 100644 --- a/src/components/listitems/ListItemHeader.tsx +++ b/src/components/listitems/ListItemHeader.tsx @@ -71,9 +71,9 @@ export const ListItemHeader = ({ diff --git a/src/components/listitems/ListItemRadioWithAmount.tsx b/src/components/listitems/ListItemRadioWithAmount.tsx index 787317e2..d9bb05b9 100644 --- a/src/components/listitems/ListItemRadioWithAmount.tsx +++ b/src/components/listitems/ListItemRadioWithAmount.tsx @@ -72,7 +72,12 @@ export const ListItemRadioWithAmount = ({ )} - +
{formattedAmountString} diff --git a/src/components/listitems/ListItemSwitch.tsx b/src/components/listitems/ListItemSwitch.tsx index 75c42173..a2a61c8d 100644 --- a/src/components/listitems/ListItemSwitch.tsx +++ b/src/components/listitems/ListItemSwitch.tsx @@ -168,6 +168,7 @@ export const ListItemSwitch = React.memo( diff --git a/src/components/modules/ModuleCheckout.tsx b/src/components/modules/ModuleCheckout.tsx index bf7e5858..e73fe373 100644 --- a/src/components/modules/ModuleCheckout.tsx +++ b/src/components/modules/ModuleCheckout.tsx @@ -83,7 +83,11 @@ export const ModuleCheckout = (props: ModuleCheckoutProps) => { - + null} /> diff --git a/src/components/progressLoader/ProgressLoader.tsx b/src/components/progressLoader/ProgressLoader.tsx index 1ffeb4b3..f609463f 100644 --- a/src/components/progressLoader/ProgressLoader.tsx +++ b/src/components/progressLoader/ProgressLoader.tsx @@ -17,6 +17,7 @@ const styles = StyleSheet.create({ export type ProgressLoader = { progress: number; + accessibilityLabel?: string; color?: IOColors; }; @@ -27,6 +28,7 @@ export type ProgressLoader = { */ export const ProgressLoader = ({ progress, + accessibilityLabel, color = "blueIO-500" }: ProgressLoader) => { const [width, setWidth] = React.useState(0); @@ -48,6 +50,7 @@ export const ProgressLoader = ({ setWidth(e.nativeEvent.layout.width)} + accessibilityLabel={accessibilityLabel} > - + diff --git a/src/components/tag/Tag.tsx b/src/components/tag/Tag.tsx index 596825e6..f8d0ff66 100644 --- a/src/components/tag/Tag.tsx +++ b/src/components/tag/Tag.tsx @@ -12,33 +12,40 @@ import { makeFontStyleObject } from "../../utils/fonts"; import { WithTestID } from "../../utils/types"; import { IOIconSizeScale, IOIcons, Icon } from "../icons"; -export type Tag = WithTestID< +type VariantProps = { + iconColor: IOColors; + iconName: IOIcons; +}; + +type TextProps = | { - text?: string; - variant: - | "qrCode" - | "legalMessage" - | "info" - | "warning" - | "error" - | "success" - | "attachment" - | "noIcon"; + text: string; iconAccessibilityLabel?: string; - customIconProps?: never; } | { - text?: string; - variant: "customIcon"; - customIconProps: VariantProps; - iconAccessibilityLabel?: string; - } ->; + text?: never; + iconAccessibilityLabel: string; + }; -type VariantProps = { - iconColor: IOColors; - iconName: IOIcons; -}; +export type Tag = TextProps & + WithTestID< + | { + variant: + | "qrCode" + | "legalMessage" + | "info" + | "warning" + | "error" + | "success" + | "attachment" + | "noIcon"; + customIconProps?: never; + } + | { + variant: "customIcon"; + customIconProps: VariantProps; + } + >; const IOTagIconMargin: IOSpacingScale = 6; const IOTagIconSize: IOIconSizeScale = 16; diff --git a/src/components/toast/ToastProvider.tsx b/src/components/toast/ToastProvider.tsx index c8f591b7..6a47e8a9 100644 --- a/src/components/toast/ToastProvider.tsx +++ b/src/components/toast/ToastProvider.tsx @@ -1,6 +1,11 @@ import { throttle } from "lodash"; import React from "react"; -import { SafeAreaView, StyleSheet, View } from "react-native"; +import { + AccessibilityInfo, + SafeAreaView, + StyleSheet, + View +} from "react-native"; import Animated, { Easing, SequencedTransition, @@ -86,6 +91,10 @@ export const ToastProvider = ({ children }: ToastProviderProps) => { triggerHaptic(toast.hapticFeedback); } + AccessibilityInfo.announceForAccessibilityWithOptions(toast.message, { + queue: true + }); + return id; }, []); diff --git a/src/components/typography/BaseTypography.tsx b/src/components/typography/BaseTypography.tsx index c6926180..140fffda 100644 --- a/src/components/typography/BaseTypography.tsx +++ b/src/components/typography/BaseTypography.tsx @@ -49,6 +49,7 @@ export const BaseTypography = React.forwardRef((props, ref) => { calculateTextStyle(props.color, props.weight, props.isItalic, props.font), [props.color, props.weight, props.isItalic, props.font] ); + const style = props.style ? [props.style, props.fontStyle, fontStyle] : [props.fontStyle, fontStyle]; From 0a062c73860cf9595a65d89316cdc43b876f6c64 Mon Sep 17 00:00:00 2001 From: Cristiano Tofani Date: Thu, 18 Jul 2024 16:36:58 +0200 Subject: [PATCH 2/8] Complete fixes on text input componets --- src/components/textInput/TextInputBase.tsx | 9 +++++++++ src/components/textInput/TextInputValidation.tsx | 9 ++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/components/textInput/TextInputBase.tsx b/src/components/textInput/TextInputBase.tsx index 0a87cb83..71aab31e 100644 --- a/src/components/textInput/TextInputBase.tsx +++ b/src/components/textInput/TextInputBase.tsx @@ -170,6 +170,11 @@ const HelperRow = ({ }, helperRowStyle ]} + // in case of error message the element should be ignored by VO or Talkback + accessibilityElementsHidden={bottomMessageColor === "error-600"} + importantForAccessibility={ + bottomMessageColor === "error-600" ? "no-hide-descendants" : "auto" + } > {bottomMessage && ( @@ -350,6 +355,8 @@ export const TextInputBase = ({ ]} accessible={false} accessibilityRole={"none"} + accessibilityElementsHidden + importantForAccessibility="no" > {/* Fake border managed with Animated.View to avoid little jumps when the border is animated */} @@ -379,6 +386,8 @@ export const TextInputBase = ({ ? derivedInputProps.textInputProps : textInputProps)} accessible + importantForAccessibility="yes" + accessibilityElementsHidden={false} editable={!disabled} secureTextEntry={isSecretInput} disableFullscreenUI={true} diff --git a/src/components/textInput/TextInputValidation.tsx b/src/components/textInput/TextInputValidation.tsx index 0c18cbd5..d559af49 100644 --- a/src/components/textInput/TextInputValidation.tsx +++ b/src/components/textInput/TextInputValidation.tsx @@ -1,6 +1,6 @@ import * as React from "react"; import { useCallback, useMemo, useState } from "react"; -import { View } from "react-native"; +import { AccessibilityInfo, View } from "react-native"; import Animated from "react-native-reanimated"; import { IOColors } from "../../core/IOColors"; import { @@ -16,7 +16,7 @@ type TextInputValidationProps = Omit< "rightElement" | "status" | "bottomMessageColor" | "isPassword" > & { onValidate: (value: string) => boolean; - errorMessage?: string; + errorMessage: string; }; const feedbackIconSize: IOIconSizeScale = 24; @@ -37,11 +37,14 @@ export const TextInputValidation = ({ setIsValid(validation); if (!validation) { triggerHaptic("notificationError"); + AccessibilityInfo.announceForAccessibilityWithOptions(errorMessage, { + queue: true + }); } else { triggerHaptic("notificationSuccess"); } onBlur?.(); - }, [onValidate, value, onBlur]); + }, [onValidate, value, onBlur, errorMessage]); const onFocusHandler = useCallback(() => { setIsValid(undefined); From fd88f30256416464602b93ac0ad93c63b53fe0e4 Mon Sep 17 00:00:00 2001 From: Cristiano Tofani Date: Thu, 18 Jul 2024 16:41:42 +0200 Subject: [PATCH 3/8] updates snaps --- .../banner/__test__/__snapshots__/banner.test.tsx.snap | 4 ++++ .../__test__/__snapshots__/listitem.test.tsx.snap | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/src/components/banner/__test__/__snapshots__/banner.test.tsx.snap b/src/components/banner/__test__/__snapshots__/banner.test.tsx.snap index c99907b8..63446766 100644 --- a/src/components/banner/__test__/__snapshots__/banner.test.tsx.snap +++ b/src/components/banner/__test__/__snapshots__/banner.test.tsx.snap @@ -111,6 +111,8 @@ exports[`Test Banner Components - Experimental Enabled Banner Snapshot 1`] = ` } /> Date: Thu, 18 Jul 2024 17:06:27 +0200 Subject: [PATCH 4/8] fixes --- example/src/pages/TextInputs.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/example/src/pages/TextInputs.tsx b/example/src/pages/TextInputs.tsx index 1b7d0b45..1d4c0467 100644 --- a/example/src/pages/TextInputs.tsx +++ b/example/src/pages/TextInputs.tsx @@ -98,6 +98,7 @@ export const TextInputs = () => ( placeholder={"Base input"} onValidate={value => value.length > 2} bottomMessage="Inserisci almeno 3 caratteri" + errorMessage="Inserisci almeno 3 caratteri" />
Base input with validation and error
( disabled placeholder={"Validation input (Disabled)"} onValidate={value => value.length > 2} + errorMessage="C'รจ stato un errore" />
From f90499c720b3470e90968c96cff0063446b4ca18 Mon Sep 17 00:00:00 2001 From: Damiano Plebani Date: Fri, 19 Jul 2024 11:15:57 +0200 Subject: [PATCH 5/8] Fix typo --- example/src/pages/Badges.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/src/pages/Badges.tsx b/example/src/pages/Badges.tsx index 63c146b5..663c6a44 100644 --- a/example/src/pages/Badges.tsx +++ b/example/src/pages/Badges.tsx @@ -114,7 +114,7 @@ const renderTag = () => (
- + From 8f5349f54190c346365511c55b5c89c1dd2d3c87 Mon Sep 17 00:00:00 2001 From: Cristiano Tofani Date: Fri, 19 Jul 2024 15:39:21 +0200 Subject: [PATCH 6/8] Fix accessibility on FeatureInfo with action --- src/components/typography/LabelLink.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/typography/LabelLink.tsx b/src/components/typography/LabelLink.tsx index 29e337b5..9efcdb9e 100644 --- a/src/components/typography/LabelLink.tsx +++ b/src/components/typography/LabelLink.tsx @@ -38,6 +38,9 @@ export const LabelLink = React.forwardRef((props, ref) => { return useTypographyFactory( { + accessible: true, + importantForAccessibility: "yes", + accessibilityElementsHidden: false, accessibilityRole: props.onPress ? "link" : undefined, ...props, allowFontScaling: isExperimental, From 788ec315fd5cabd2a36337c9735bb5f4ccf86809 Mon Sep 17 00:00:00 2001 From: Cristiano Tofani Date: Fri, 19 Jul 2024 15:47:57 +0200 Subject: [PATCH 7/8] add state to TabItem component --- src/components/tabs/TabItem.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/tabs/TabItem.tsx b/src/components/tabs/TabItem.tsx index d038f4b8..46e00fb7 100644 --- a/src/components/tabs/TabItem.tsx +++ b/src/components/tabs/TabItem.tsx @@ -235,6 +235,7 @@ const TabItem = ({ accessibilityLabel={accessibilityLabel} accessibilityHint={accessibilityHint} accessibilityRole={"button"} + accessibilityState={{ selected }} testID={testID} onPress={onPress} onPressIn={onPressIn} From 21779679422943d74f56ab7dff3f1db7b5f21b8d Mon Sep 17 00:00:00 2001 From: Cristiano Tofani Date: Fri, 19 Jul 2024 16:18:57 +0200 Subject: [PATCH 8/8] move link accessibility props to FeatureInfo --- src/components/featureInfo/FeatureInfo.tsx | 8 +++++++- src/components/typography/LabelLink.tsx | 3 --- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/components/featureInfo/FeatureInfo.tsx b/src/components/featureInfo/FeatureInfo.tsx index 355631e4..c84c8e33 100644 --- a/src/components/featureInfo/FeatureInfo.tsx +++ b/src/components/featureInfo/FeatureInfo.tsx @@ -75,7 +75,13 @@ export const FeatureInfo = ({ This verbose code could be deleted once we got "gap" property support */} {body && } - + {actionLabel} diff --git a/src/components/typography/LabelLink.tsx b/src/components/typography/LabelLink.tsx index 9efcdb9e..29e337b5 100644 --- a/src/components/typography/LabelLink.tsx +++ b/src/components/typography/LabelLink.tsx @@ -38,9 +38,6 @@ export const LabelLink = React.forwardRef((props, ref) => { return useTypographyFactory( { - accessible: true, - importantForAccessibility: "yes", - accessibilityElementsHidden: false, accessibilityRole: props.onPress ? "link" : undefined, ...props, allowFontScaling: isExperimental,