@@ -5,6 +5,9 @@ const NAV_DONATE_CLASS = '.nav-donate';
55const NAV_SUBMENU_CLASS = '.nav-submenu' ;
66const SITE_LOGO_CLASS = '.site-logo' ;
77const NAV_MENU_CLOSE_CLASS = '.nav-menu-close' ;
8+ const MOBILE_NAV_ID = '#nav-main' ;
9+ const PAGE_WRAPPER_ID = '#content' ;
10+ const NAV_MENU_TOGGLE_CLASS = '.nav-menu-toggle' ;
811
912/**
1013 * Function to handle keyboard accessibility in the navigation menu.
@@ -121,6 +124,9 @@ export const setupAccessibleNavMenu = () => {
121124 }
122125
123126 if ( mobileNav ) {
127+ const doc = mobileNav . ownerDocument ;
128+ let lastFocusedElement = null ;
129+ const isMobileMenuOpen = ( ) => mobileNav . classList . contains ( 'open' ) ;
124130 /**
125131 * Adds event listeners to create a keyboard trap between the buttons.
126132 */
@@ -156,10 +162,16 @@ export const setupAccessibleNavMenu = () => {
156162 return ;
157163 }
158164
159- hamburgerBtn . addEventListener ( 'keydown' , event => {
160- if ( event . key === 'Enter' ) {
161- setTimeout ( ( ) => logo . focus ( ) , 0 ) ;
162- }
165+ hamburgerBtn . addEventListener ( 'click' , ( ) => {
166+ lastFocusedElement = doc . activeElement ;
167+
168+ // Wait for CSS class to apply
169+ requestAnimationFrame ( ( ) => {
170+ if ( isMobileMenuOpen ( ) ) {
171+ syncMobileNavAria ( true ) ;
172+ logo . focus ( ) ;
173+ }
174+ } ) ;
163175 } ) ;
164176 } ;
165177
@@ -168,21 +180,25 @@ export const setupAccessibleNavMenu = () => {
168180 */
169181 const focusLogoOnMenuClose = ( ) => {
170182 const closeBtn = mobileNav . querySelector ( NAV_MENU_CLOSE_CLASS ) ;
171- const hamburgerLogo = mobileNav . querySelector ( SITE_LOGO_CLASS ) ;
172- const mainLogo = document . querySelector ( `#header ${ SITE_LOGO_CLASS } ` ) ;
183+ const toggleBtn = document . querySelector ( NAV_MENU_TOGGLE_CLASS ) ;
173184
174- if ( ! mainLogo || ! hamburgerLogo || ! closeBtn ) {
185+ if ( ! closeBtn || ! toggleBtn ) {
175186 return ;
176187 }
177188
178- closeBtn . addEventListener ( 'keydown' , event => {
179- if ( event . key === 'Enter' ) {
180- setTimeout ( ( ) => mainLogo . focus ( ) , 0 ) ;
181- }
182- if ( event . key === 'Tab' && event . shiftKey ) {
183- setTimeout ( ( ) => hamburgerLogo . focus ( ) , 0 ) ;
184- }
189+ closeBtn . addEventListener ( 'click' , ( ) => {
190+ const page = document . querySelector ( PAGE_WRAPPER_ID ) ;
191+ page . removeAttribute ( 'aria-hidden' ) ;
192+ page . inert = false ;
193+
194+
195+ requestAnimationFrame ( ( ) => {
196+ ( lastFocusedElement || toggleBtn ) . focus ( ) ;
197+ mobileNav . setAttribute ( 'aria-hidden' , 'true' ) ;
198+ toggleBtn . setAttribute ( 'aria-expanded' , 'false' ) ;
199+ } ) ;
185200 } ) ;
201+
186202 } ;
187203
188204 addKeyboardTrap ( ) ;
@@ -209,3 +225,36 @@ export const updateNavMenuTabIndex = () => {
209225 ] ;
210226 tabbingItems . forEach ( item => item . setAttribute ( 'tabindex' , menu . classList . contains ( 'open' ) ? 0 : - 1 ) ) ;
211227} ;
228+
229+ /**
230+ * Function to update aria attributes for mobile navigation.
231+ * @param {boolean } isOpen - Whether the mobile navigation is open.
232+ */
233+ const syncMobileNavAria = isOpen => {
234+ const mobileNav = document . querySelector ( MOBILE_NAV_ID ) ;
235+ const page = document . querySelector ( PAGE_WRAPPER_ID ) ;
236+ const toggleBtn = document . querySelector ( NAV_MENU_TOGGLE_CLASS ) ;
237+
238+ if ( ! mobileNav || ! page || ! toggleBtn ) {
239+ return ;
240+ }
241+
242+ // Mobile menu
243+ if ( isOpen ) {
244+ mobileNav . removeAttribute ( 'aria-hidden' ) ;
245+ } else {
246+ mobileNav . setAttribute ( 'aria-hidden' , 'true' ) ;
247+ }
248+
249+ // Page behind
250+ if ( isOpen ) {
251+ page . setAttribute ( 'aria-hidden' , 'true' ) ;
252+ page . inert = true ;
253+ } else {
254+ page . removeAttribute ( 'aria-hidden' ) ;
255+ page . inert = false ;
256+ }
257+
258+ // Toggle button state
259+ toggleBtn . setAttribute ( 'aria-expanded' , String ( isOpen ) ) ;
260+ } ;
0 commit comments