From 6f17c7e6ffd154cb5abd88fb55d3ba4987bf76f7 Mon Sep 17 00:00:00 2001 From: "truph01 (via MelvinBot)" Date: Thu, 5 Mar 2026 18:57:54 +0000 Subject: [PATCH 1/3] Add button role to PressableWithDelayToggle for screen reader accessibility Default accessibilityRole to CONST.ROLE.BUTTON in PressableWithDelayToggle so screen readers announce the element as a button. Remove unused accessible={false} props from TFA page callers. Replace blanket eslint-disable with targeted eslint-disable-next-line on the inner PressableWithoutFeedback. Improve accessibilityLabel fallback to use visible text when tooltip text is empty. Co-authored-by: truph01 --- src/components/Pressable/PressableWithDelayToggle.tsx | 7 ++++--- .../settings/Security/TwoFactorAuth/CopyCodesPage.tsx | 2 -- src/pages/settings/Security/TwoFactorAuth/VerifyPage.tsx | 1 - 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/components/Pressable/PressableWithDelayToggle.tsx b/src/components/Pressable/PressableWithDelayToggle.tsx index dfdf361eb723..35a9e7887fa7 100644 --- a/src/components/Pressable/PressableWithDelayToggle.tsx +++ b/src/components/Pressable/PressableWithDelayToggle.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react-native-a11y/has-valid-accessibility-descriptors */ import React from 'react'; import type {StyleProp, TextStyle, ViewStyle} from 'react-native'; import Icon from '@components/Icon'; @@ -83,7 +82,7 @@ function PressableWithDelayToggle({ iconStyles, icon, ref, - accessibilityRole, + accessibilityRole = CONST.ROLE.BUTTON, shouldHaveActiveBackground, iconWidth = variables.iconSizeSmall, iconHeight = variables.iconSizeSmall, @@ -132,7 +131,8 @@ function PressableWithDelayToggle({ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment ref={ref as any} onPress={updatePressState} - accessibilityLabel={tooltipTexts} + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- Fallback to visible text when tooltip is empty for screen readers + accessibilityLabel={tooltipTexts || (!isActive && textChecked ? textChecked : text) || ''} suppressHighlighting={inline ? true : undefined} accessibilityRole={accessibilityRole} > @@ -142,6 +142,7 @@ function PressableWithDelayToggle({ text={tooltipTexts} shouldRender > + {/* eslint-disable-next-line react-native-a11y/has-valid-accessibility-descriptors */} Clipboard.setString(account?.twoFactorAuthSecretKey ?? '')} styles={[styles.button, styles.buttonMedium, styles.twoFactorAuthCopyCodeButton]} textStyles={[styles.buttonMediumText]} - accessible={false} sentryLabel={CONST.SENTRY_LABEL.TWO_FACTOR_AUTH.COPY} /> From f011914c9d879e05b44adf0b74c8d67ecda33e46 Mon Sep 17 00:00:00 2001 From: "truph01 (via MelvinBot)" Date: Thu, 5 Mar 2026 19:13:07 +0000 Subject: [PATCH 2/3] Fix: Add missing accessibilityLabel to PressableWithDelayToggle call sites The PressableProps type requires either accessible={false} or an accessibilityLabel string. These call sites were missing it, causing TypeScript errors. Co-authored-by: truph01 --- src/pages/settings/Security/TwoFactorAuth/CopyCodesPage.tsx | 2 ++ src/pages/settings/Security/TwoFactorAuth/VerifyPage.tsx | 1 + 2 files changed, 3 insertions(+) diff --git a/src/pages/settings/Security/TwoFactorAuth/CopyCodesPage.tsx b/src/pages/settings/Security/TwoFactorAuth/CopyCodesPage.tsx index 52c2a7fb931f..00f75149eb64 100644 --- a/src/pages/settings/Security/TwoFactorAuth/CopyCodesPage.tsx +++ b/src/pages/settings/Security/TwoFactorAuth/CopyCodesPage.tsx @@ -125,6 +125,7 @@ function CopyCodesPage({route}: TwoFactorAuthPageProps) { textStyles={[styles.buttonMediumText]} tooltipText="" tooltipTextChecked="" + accessibilityLabel={translate('twoFactorAuth.copy')} sentryLabel={CONST.SENTRY_LABEL.TWO_FACTOR_AUTH.COPY_CODES} /> diff --git a/src/pages/settings/Security/TwoFactorAuth/VerifyPage.tsx b/src/pages/settings/Security/TwoFactorAuth/VerifyPage.tsx index e16b46fead0c..5a301caefa40 100644 --- a/src/pages/settings/Security/TwoFactorAuth/VerifyPage.tsx +++ b/src/pages/settings/Security/TwoFactorAuth/VerifyPage.tsx @@ -130,6 +130,7 @@ function VerifyPage({route}: VerifyPageProps) { onPress={() => Clipboard.setString(account?.twoFactorAuthSecretKey ?? '')} styles={[styles.button, styles.buttonMedium, styles.twoFactorAuthCopyCodeButton]} textStyles={[styles.buttonMediumText]} + accessibilityLabel={translate('twoFactorAuth.copy')} sentryLabel={CONST.SENTRY_LABEL.TWO_FACTOR_AUTH.COPY} /> From 26cd3600ab761fe52960df6bfc6fcbf7a5b2705d Mon Sep 17 00:00:00 2001 From: "truph01 (via MelvinBot)" Date: Fri, 6 Mar 2026 12:14:40 +0000 Subject: [PATCH 3/3] Refactor: extract inline accessibilityLabel into processedAccessibilityLabel variable and add eslint-disable justification Co-authored-by: truph01 --- src/components/Pressable/PressableWithDelayToggle.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/Pressable/PressableWithDelayToggle.tsx b/src/components/Pressable/PressableWithDelayToggle.tsx index 35a9e7887fa7..bb7d1759ba3f 100644 --- a/src/components/Pressable/PressableWithDelayToggle.tsx +++ b/src/components/Pressable/PressableWithDelayToggle.tsx @@ -108,6 +108,8 @@ function PressableWithDelayToggle({ // of a Pressable const PressableView = inline ? Text : PressableWithoutFeedback; const tooltipTexts = !isActive ? tooltipTextChecked : tooltipText; + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- Fallback to visible text when tooltip is empty for screen readers + const processedAccessibilityLabel = tooltipTexts || (!isActive && textChecked ? textChecked : text) || ''; const shouldShowIcon = !!icon || (!isActive && !!resolvedIconChecked); const labelText = // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- Disabling this line for safeness as nullish coalescing works only if the value is undefined or null @@ -131,8 +133,7 @@ function PressableWithDelayToggle({ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment ref={ref as any} onPress={updatePressState} - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- Fallback to visible text when tooltip is empty for screen readers - accessibilityLabel={tooltipTexts || (!isActive && textChecked ? textChecked : text) || ''} + accessibilityLabel={processedAccessibilityLabel} suppressHighlighting={inline ? true : undefined} accessibilityRole={accessibilityRole} > @@ -142,7 +143,7 @@ function PressableWithDelayToggle({ text={tooltipTexts} shouldRender > - {/* eslint-disable-next-line react-native-a11y/has-valid-accessibility-descriptors */} + {/* eslint-disable-next-line react-native-a11y/has-valid-accessibility-descriptors -- Inner pressable is intentionally non-accessible (accessible={false}) since the outer PressableView handles accessibility */}