fix(a11y): remove duplicate focusable elements#80875
fix(a11y): remove duplicate focusable elements#80875marufsharifi wants to merge 11 commits intoExpensify:mainfrom
Conversation
|
Hey! I see that you made changes to our Form component. Make sure to update the docs in FORMS.md accordingly. Cheers! |
| const columnDirection = isVertical ? styles.flexColumn : styles.flexRow; | ||
| const pageFooterWrapper = [styles.footerWrapper, imageDirection, imageStyle, isVertical ? styles.pl10 : {}]; | ||
| const footerColumns = [styles.footerColumnsContainer, columnDirection]; | ||
| const footerColumn = isVertical ? [styles.p4] : [styles.p4, isMediumScreenWidth ? styles.w50 : styles.w25]; |
There was a problem hiding this comment.
❌ CONSISTENCY-1 (docs)
Platform-specific logic should be separated into platform-specific files rather than using Platform.OS checks within components. This increases maintainability and reduces complexity.
Suggested fix: Create platform-specific implementations:
Footer.web.tsx:
// Keep the existing TextLink implementation
{column.rows.map(({href, onPress, translationPath}) => (
<Hoverable key={translationPath}>
{(hovered) => (
<View>
{onPress ? (
<TextLink style={getTextLinkStyle(hovered)} onPress={onPress}>
{translate(translationPath)}
</TextLink>
) : (
<TextLink style={getTextLinkStyle(hovered)} href={href}>
{translate(translationPath)}
</TextLink>
)}
</View>
)}
</Hoverable>
))}Footer.native.tsx:
// Use PressableWithoutFeedback implementation
{column.rows.map(({href, onPress, translationPath}) => (
<Hoverable key={translationPath}>
{(hovered) => (
<PressableWithoutFeedback
accessible
accessibilityRole={CONST.ROLE.LINK}
accessibilityLabel={translate(translationPath)}
onPress={() => {
if (onPress) {
onPress({} as GestureResponderEvent);
return;
}
if (href) {
openLinkUtil(href, environmentURL);
}
}}
>
<Text accessible={false} suppressHighlighting style={[styles.link, getTextLinkStyle(hovered)]}>
{translate(translationPath)}
</Text>
</PressableWithoutFeedback>
)}
</Hoverable>
))}Please rate this suggestion with 👍 or 👎 to help us improve! Reactions are used to monitor reviewer efficiency.
There was a problem hiding this comment.
@Ollyws, do you agree? Please share your thoughts on this. thanks
There was a problem hiding this comment.
@marufsharifi Yeah I agree we should create platform specific files possibly just for the footer-row component to avoid repeating ourselves.
Codecov Report✅ Changes either increased or maintained existing code coverage, great job!
|
|
@Ollyws, kindly bump, thanks. |
|
Why's it necessary to change the content of the index.tsx files, wasn't this issue only occuring on native? |
@Ollyws, the issue existed in both platforms before our changes, so I fixed it in both platforms. thanks. Web: mweb-without-changes.mp4Native: native-without-changes.mp4 |
|
@Ollyws, kindly bump. thanks. |
|
Will get to this one tomorrow. |
Reviewer Checklist
Screenshots/VideosAndroid: HybridApp01_Android_Native.mp4Android: mWeb Chrome02_Android_Chrome.mp4iOS: HybridApp03_iOS_Native.mp4iOS: mWeb Safari04_iOS_Safari.mp4MacOS: Chrome / SafariMacOS_Safari.mp4 |
|
We did not find an internal engineer to review this PR, trying to assign a random engineer to #79245 as well as to this PR... Please reach out for help on Slack if no one gets assigned! |
| role={CONST.ROLE.PRESENTATION} | ||
| onPress={onPress} | ||
| tabIndex={-1} | ||
| accessible={false} |
There was a problem hiding this comment.
Why are we setting accessible = false on our base text input?
There was a problem hiding this comment.
@roryabraham Thanks for calling this out.
We set accessible={false} on the PressableWithoutFeedback wrapper because that wrapper is only a touch/focus helper, not the semantic form control.
In #77329, TalkBack was focusing this wrapper first (it had an accessibilityLabel), then focusing the real input (InputComponent), which caused duplicate announcements.
Making the wrapper non-accessible (and removing its label) leaves only the real TextInput in the accessibility tree, which resolves the duplicate focus stop.
Explanation of Change
Fixed Issues
$ #79245
PROPOSAL: #79245 (comment)
Tests
Precondition:
The user is not signed in
Second issue
Precondition:
The user is not signed in
'Phone or email input field, edit box'
Offline tests
Same as Tests
QA Steps
Same as Tests
// TODO: These must be filled out, or the issue title must include "[No QA]."
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectioncanBeMissingparam foruseOnyxtoggleReportand notonIconClick)src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.ScrollViewcomponent to make it scrollable when more elements are added to the page.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
phone-email-android.mp4
footer-android.mp4
Android: mWeb Chrome
email-mweb.mp4
footer-mweb.mp4
iOS: Native
Screen.Recording.1404-11-09.at.2.07.47.PM.mov
Screen.Recording.1404-11-09.at.2.18.20.PM.mov
iOS: mWeb Safari
Screen.Recording.1404-11-09.at.2.11.15.PM.mov
Screen.Recording.1404-11-09.at.2.23.46.PM.mov
MacOS: Chrome / Safari
Screen.Recording.1404-11-09.at.3.01.19.PM.mp4
Screen.Recording.1404-11-09.at.3.02.02.PM.mov