-
-
Notifications
You must be signed in to change notification settings - Fork 9.8k
UI: Apply user updates for mobile navigation accessibility #31401
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
UI: Apply user updates for mobile navigation accessibility #31401
Conversation
…moving unnecessary comments and simplifying focus handling logic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
6 file(s) reviewed, 6 comment(s)
Edit PR Review Bot Settings | Greptile
code/core/src/manager/components/mobile/navigation/MobileMenuDrawer.tsx
Outdated
Show resolved
Hide resolved
code/core/src/manager/components/mobile/navigation/MobileMenuDrawer.tsx
Outdated
Show resolved
Hide resolved
code/core/src/manager/components/mobile/navigation/MobileAddonsDrawer.tsx
Outdated
Show resolved
Hide resolved
code/core/src/manager/components/mobile/navigation/MobileNavigation.tsx
Outdated
Show resolved
Hide resolved
code/core/src/manager/components/mobile/navigation/useFocusTrap.tsx
Outdated
Show resolved
Hide resolved
code/core/src/manager/components/mobile/navigation/useFocusTrap.tsx
Outdated
Show resolved
Hide resolved
|
View your CI Pipeline Execution ↗ for commit 18b9fa1.
☁️ Nx Cloud last updated this comment at |
…aria-controls in MobileNavigation
|
@MichaelArestad Do you have any input here? |
MichaelArestad
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yatishgoel Nice!
@ndelangen These changes seem great. I am not an expert on aria attributes and I have not implemented anything like useFocusTrap though I understand the reasoning.
I believe this breaks a few Interaction tests in Navigation that were targeting elements with a specific title attribute. We shouldn't be using title attributes for this anyway. title attributes are not designed to be used for anything other than iframes.
Regarding the title attributes, they were being used as tooltips, which isn't great. In the near future, I do think we should probably:
- Create new tooltips that are accessible, specifically the tooltips designed to show a short string (black background, white text).
- Implement those tooltips in almost every situation where we use
title.
|
@ndelangen Can you code review this when you get a chance? Thank you! |
Sidnioulz
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks so much for undertaking this work, @yatishgoel! This is hard work so please don't take anything in my review as a criticism of your effort. I very much appreciate you giving this a go!
You applied a dialog role with an aria-modal attribute. That's great, and it's what I wrote in the issue so really this is my own fault! It's unfortunately missing a powerful element of the Dialog element: showModal. The showModal function lets you instruct the browser to open a modal and install a focus trap for you, which greatly reduces the amount of code to write and makes better use of standards.
You also used the navigation role in your code. It would be preferrable to use the nav element directly instead. Generally speaking (and as reminded on https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Roles/navigation_role), it's preferable to use the HTML standard element rather than its inferred role and attributes.
I shouldn't have mentioned role in my issue. I sometimes refer to roles instead of elements out of habit because I don't know if the HTML markup is controlled and can be edited, but when a role can be fulfilled through the use of an element, it should. That allows for better future compatibility and easier maintenance.
To move forward, I suggest removing the focus trap implementation and using showModal instead, and switching to actual nav/dialog elements. Then, there would only be minor details left to address.
code/core/src/manager/components/mobile/navigation/MobileAddonsDrawer.tsx
Outdated
Show resolved
Hide resolved
code/core/src/manager/components/mobile/navigation/MobileMenuDrawer.tsx
Outdated
Show resolved
Hide resolved
code/core/src/manager/components/mobile/navigation/MobileMenuDrawer.tsx
Outdated
Show resolved
Hide resolved
code/core/src/manager/components/mobile/navigation/useFocusTrap.tsx
Outdated
Show resolved
Hide resolved
code/core/src/manager/components/mobile/navigation/useFocusTrap.tsx
Outdated
Show resolved
Hide resolved
code/core/src/manager/components/mobile/navigation/useFocusTrap.tsx
Outdated
Show resolved
Hide resolved
code/core/src/manager/components/mobile/navigation/useFocusTrap.tsx
Outdated
Show resolved
Hide resolved
code/core/src/manager/components/mobile/navigation/useFocusTrap.tsx
Outdated
Show resolved
Hide resolved
…ate management. Updated MobileAddonsDrawer and MobileMenuDrawer to use dialog elements for better focus control. Removed unused useFocusTrap hook. Simplified MainContentMatcher by removing unnecessary props. Enhanced MobileNavigation to manage addon panel state more effectively.
Sidnioulz
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A small bug left to fix and a refactor could be made to regroup the modal hooks into a single file, but this is great overall and would definitely fix the linked issue. Kudos, @yatishgoel!
code/core/src/manager/components/mobile/navigation/MobileAddonsDrawer.tsx
Outdated
Show resolved
Hide resolved
code/core/src/manager/components/mobile/navigation/MobileAddonsDrawer.tsx
Outdated
Show resolved
Hide resolved
…ialog hook for improved dialog management. Introduced useModalDialog for better encapsulation of dialog logic and enhanced accessibility. Updated shortcut handling to skip events when a dialog is open.
code/core/src/manager/components/mobile/navigation/MobileMenuDrawer.tsx
Outdated
Show resolved
Hide resolved
…ling - Introduced `forceCloseDialog` function in MobileMenuDrawer to encapsulate dialog closing logic. - Updated onExited callback to use `forceCloseDialog` for cleaner code. - Enhanced useModalDialog to handle Escape key for closing the dialog and prevent default behavior. - Removed redundant dialog close logic from useModalDialog to streamline the component's functionality.
Sidnioulz
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Congrats on fixing the animations! Can you please test the mobile addon panel again? I see a few remaining issues:
- It's positioned in the middle of the screen instead of the bottom
- The close button doesn't close the panel
- It seems I have to press Esc 2-3 times to close the panel
- Fix MobileMenuDrawer and MobileAddonsDrawer appearing centered instead of bottom - Add full width positioning for mobile dialogs - Fix Esc key requiring double press in addon drawer - Fix close button not working properly - Ensure smooth exit animations with proper timing coordination - Override browser default modal positioning with &[open] selector
Thanks for the feedback! I actually just fixed those exact issues in both MobileAddonsDrawer.tsx and MobileMenuDrawer.tsx: Positioning: Added Close Behavior: Converted MobileAddonsDrawer to use React Transition with the same working pattern as MobileMenuDrawer - added Both mobile drawers now use identical patterns: React Transition + useModalDialog + forceCloseDialog for behavior, and the same CSS positioning overrides. MobileMenuDrawer was working correctly, so I used it as the reference to fix MobileAddonsDrawer. Both should now appear at bottom with full width and proper close behavior. |
Package BenchmarksCommit: No significant changes detected, all good. 👏 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code does everything I'd like it to do! Now this is just a matter of getting the CI passing.
We can now turn our attention to the CI :) I haven't looked in detail at the CI reports, but if you get stuck, feel free to ask me to take over and I will have a look. It seems there are a few tests that need to be updated, maybe you could start with this? https://app.circleci.com/jobs/github/storybookjs/storybook/843273
|
@yatishgoel can you please update the tests affected by your change? |
- Replace getByTitle() with getByLabelText() in test queries - Update MockPanel component to use aria-label instead of title - Align tests with accessibility improvements that replaced title with aria-label attributes - All MobileNavigation.stories.tsx tests now pass
- Replace 'button[title="Open navigation menu"]' with 'button[aria-label="Open navigation menu"]' - Fixes timeout issue in composition.spec.ts mobile test - Aligns e2e test with accessibility improvements that replaced title with aria-label
- Replace title attributes with aria-label in manager.spec.ts for better accessibility - Aligns with recent accessibility improvements in the codebase
- Replace title with aria-label for mobile close button in Panel.tsx - Fixes e2e test failure expecting 'aria-label="Close addon panel"' - Completes accessibility improvements for mobile addon panel - Aligns mobile panel close button with navigation accessibility standards
Hi @Sidnioulz, I have successfully updated all tests affected by the accessibility changes and confirmed they're working locally.
Thanks for your guidance! |
Closes #31380
What I did
This PR significantly enhances the accessibility of the mobile navigation and addresses focus management issues, resolving the core concerns raised in #31380. It also incorporates the DOM order fix for desktop and mobile reading consistency from #31076.
Key improvements:
ARIA Attributes for Mobile Navigation:
aria-label,aria-expanded, andaria-controlsto properly communicate its state and relationship with the menu drawer (MobileNavigation.tsx).aria-labelandaria-expanded.Accessible Mobile Menu Drawer (
MobileMenuDrawer.tsx):role="dialog",aria-modal="true", and anaria-labelfor clear anouncement to screen reader users.role="navigation".Focus Management and Trapping:
useFocusTraphook has been implemented and applied toMobileMenuDrawer.tsx.TabandShift+Tab, and closing via theEscapekey.aria-hidden="true"andtabIndex="-1"when the mobile menu is open to prevent interaction with background content (Layout.tsx).DOM Order for Reading Consistency (Addresses Fix Storybook accessibility order #31076):
Layout.tsxensures<SidebarContainer>renders before the main content (<MainContentMatcher>) for a logical reading order.<MobileNavigation>trigger component is rendered first in the DOM within its mobile layout block, while CSSorderis used for its visual placement at the bottom. This ensures screen readers encounter the navigation trigger in a logical sequence.General Code Refinements:
useFocusTrap.useFocusTrap.idprops andaria-controlsfor theMobileAddonsDraweras well, preparing it for similar focus trap implementation if it contains interactive elements.Checklist for Contributors
Testing
The changes in this PR are covered in the following automated tests:
Manual testing
This section is mandatory for all contributions. If you believe no manual test is necessary, please state so explicitly. Thanks!
This section is mandatory for all contributions. If you believe no manual test is necessary, please state so explicitly. Thanks!
yarn task --task sandbox --start-from auto --template react-vite/default-tsTabandShift+Tab. Ensure focus stays within the menu.Escape. Verify the menu closes and focus returns to the "Open navigation menu" button.aria-hidden="true") when the menu was open.Documentation
MIGRATION.MD
Checklist for Maintainers
When this PR is ready for testing, make sure to add
ci:normal,ci:mergedorci:dailyGH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found incode/lib/cli-storybook/src/sandbox-templates.tsMake sure this PR contains one of the labels below:
Available labels
bug: Internal changes that fixes incorrect behavior.maintenance: User-facing maintenance tasks.dependencies: Upgrading (sometimes downgrading) dependencies.build: Internal-facing build tooling & test updates. Will not show up in release changelog.cleanup: Minor cleanup style change. Will not show up in release changelog.documentation: Documentation only changes. Will not show up in release changelog.feature request: Introducing a new feature.BREAKING CHANGE: Changes that break compatibility in some way with current major version.other: Changes that don't fit in the above categories.🦋 Canary release
This PR does not have a canary release associated. You can request a canary release of this pull request by mentioning the
@storybookjs/coreteam here.core team members can create a canary release here or locally with
gh workflow run --repo storybookjs/storybook canary-release-pr.yml --field pr=<PR_NUMBER>Greptile Summary
Here's a concise summary of the key accessibility improvements made to the mobile navigation components:
Enhanced mobile navigation components with comprehensive accessibility features and proper DOM ordering.
role="dialog",aria-modal,aria-controls,aria-expanded) inMobileNavigation.tsxandMobileMenuDrawer.tsxuseFocusTraphook for modal dialogsLayout.tsxto ensure sidebar renders before main content for logical screen reader flowaria-hiddenandtabIndexcontrols to main content when mobile menu is openThe changes significantly improve screen reader compatibility and keyboard navigation while maintaining visual layout through CSS ordering rather than DOM manipulation.