Skip to content
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

fix(menu): hide from screen readers while animating #30036

Merged
merged 7 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions core/src/components/menu/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type { Attributes } from '@utils/helpers';
import { inheritAriaAttributes, assert, clamp, isEndSide as isEnd } from '@utils/helpers';
import { menuController } from '@utils/menu-controller';
import { BACKDROP, GESTURE, getPresentedOverlay } from '@utils/overlays';
import { isPlatform } from '@utils/platform';
import { hostContext } from '@utils/theme';

import { config } from '../../global/config';
Expand Down Expand Up @@ -631,6 +632,23 @@ export class Menu implements ComponentInterface, MenuI {
private beforeAnimation(shouldOpen: boolean, role?: string) {
assert(!this.isAnimating, '_before() should not be called while animating');

/**
* When the menu is presented on an Android device, TalkBack's focus rings
* may appear in the wrong position due to the transition (specifically
* `transform` styles). This occurs because the focus rings are initially
* displayed at the starting position of the elements before the transition
* begins. This workaround ensures the focus rings do not appear in the
* incorrect location.
*
* If this solution is applied to iOS devices, then it leads to a bug where
* the overlays cannot be accessed by screen readers. This is due to
* VoiceOver not being able to update the accessibility tree when the
* `aria-hidden` is removed.
*/
if (isPlatform('android')) {
this.el.setAttribute('aria-hidden', 'true');
}

// this places the menu into the correct location before it animates in
// this css class doesn't actually kick off any animations
this.el.classList.add(SHOW_MENU);
Expand Down Expand Up @@ -687,6 +705,17 @@ export class Menu implements ComponentInterface, MenuI {
}

if (isOpen) {
/**
* When the menu is presented on an Android device, TalkBack's focus rings
* may appear in the wrong position due to the transition (specifically
* `transform` styles). The menu is hidden from screen readers during the
* transition to prevent this. Once the transition is complete, the menu
* is shown again.
*/
if (isPlatform('android')) {
this.el.removeAttribute('aria-hidden');
}

// emit open event
this.ionDidOpen.emit();

Expand All @@ -703,6 +732,8 @@ export class Menu implements ComponentInterface, MenuI {
// start focus trapping
document.addEventListener('focus', this.handleFocus, true);
} else {
this.el.removeAttribute('aria-hidden');

// remove css classes and unhide content from screen readers
this.el.classList.remove(SHOW_MENU);

Expand Down
11 changes: 6 additions & 5 deletions core/src/utils/overlays.ts
Original file line number Diff line number Diff line change
Expand Up @@ -971,11 +971,12 @@ export const createTriggerController = () => {
* like TalkBack do not announce or interact with the content until the
* animation is complete, avoiding confusion for users.
*
* If the overlay is being presented, it prevents focus rings from appearing
* in incorrect positions due to the transition (specifically `transform`
* styles), ensuring that when aria-hidden is removed, the focus rings are
* correctly displayed in the final location of the elements. This only
* applies to Android devices.
* When the overlay is presented on an Android device, TalkBack's focus rings
* may appear in the wrong position due to the transition (specifically
* `transform` styles). This occurs because the focus rings are initially
* displayed at the starting position of the elements before the transition
* begins. This workaround ensures the focus rings do not appear in the
* incorrect location.
*
* If this solution is applied to iOS devices, then it leads to a bug where
* the overlays cannot be accessed by screen readers. This is due to
Expand Down
Loading