From f3ddc5153418db8a21c2c42158df2db06fb9463f Mon Sep 17 00:00:00 2001 From: bwang Date: Wed, 1 Feb 2023 14:31:53 -0600 Subject: [PATCH] Add setFocusToToggleButton function to pinnableElement.js Bug: T325020 Change-Id: I3829b146551ea55b84ae717a5db27003b0f2b97b --- resources/skins.vector.es6/main.js | 5 +++- resources/skins.vector.es6/pinnableElement.js | 28 ++++++++++++++++++- .../pinnableElement.test.js.snap | 12 ++++++-- tests/jest/pinnableElement.test.js | 25 +++++++++++++++-- 4 files changed, 64 insertions(+), 6 deletions(-) diff --git a/resources/skins.vector.es6/main.js b/resources/skins.vector.es6/main.js index f3ac530c9..31d65dc5b 100644 --- a/resources/skins.vector.es6/main.js +++ b/resources/skins.vector.es6/main.js @@ -278,7 +278,10 @@ const main = () => { onToggleClick: ( id ) => { tableOfContents.toggleExpandSection( id ); }, - onTogglePinned: updateTocLocation + onTogglePinned: () => { + updateTocLocation(); + pinnableElement.setFocusAfterToggle( TOC_ID ); + } } ); const headingSelector = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' diff --git a/resources/skins.vector.es6/pinnableElement.js b/resources/skins.vector.es6/pinnableElement.js index a8b786b3e..69d004e55 100644 --- a/resources/skins.vector.es6/pinnableElement.js +++ b/resources/skins.vector.es6/pinnableElement.js @@ -97,14 +97,39 @@ function pinnableElementClickHandler( header ) { } = header.dataset; togglePinnableClasses( header ); + setSavedPinnableState( header ); // Optional functionality of moving the pinnable element in the DOM // to different containers based on it's pinned status if ( pinnableElementId && pinnedContainerId && unpinnedContainerId ) { const newContainerId = isPinned( header ) ? pinnedContainerId : unpinnedContainerId; movePinnableElement( pinnableElementId, newContainerId ); + setFocusAfterToggle( pinnableElementId ); + } +} + +/** + * Sets focus on the correct toggle button depending on the pinned state. + * Also opens the dropdown containing the unpinned element. + * + * @param {string} pinnableElementId + */ +function setFocusAfterToggle( pinnableElementId ) { + let focusElement; + const pinnableElement = document.getElementById( pinnableElementId ); + const header = /** @type {HTMLElement|null} */ ( pinnableElement && pinnableElement.querySelector( '.vector-pinnable-header' ) ); + if ( !pinnableElement || !header ) { + return; + } + if ( isPinned( header ) ) { + focusElement = /** @type {HTMLElement|null} */ ( pinnableElement.querySelector( '.vector-pinnable-header-unpin-button' ) ); + } else { + const dropdown = pinnableElement.closest( '.vector-dropdown' ); + focusElement = /** @type {HTMLInputElement|null} */ ( dropdown && dropdown.querySelector( '.vector-menu-checkbox' ) ); + } + if ( focusElement ) { + focusElement.focus(); } - setSavedPinnableState( header ); } /** @@ -177,6 +202,7 @@ function initPinnableElement() { module.exports = { initPinnableElement, movePinnableElement, + setFocusAfterToggle, isPinned, PINNED_HEADER_CLASS, UNPINNED_HEADER_CLASS diff --git a/tests/jest/__snapshots__/pinnableElement.test.js.snap b/tests/jest/__snapshots__/pinnableElement.test.js.snap index bb5391172..cb4c28d9c 100644 --- a/tests/jest/__snapshots__/pinnableElement.test.js.snap +++ b/tests/jest/__snapshots__/pinnableElement.test.js.snap @@ -5,13 +5,21 @@ exports[`Pinnable header renders 1`] = `
-
-
+
+ + +
+
+
simple pinnable element
+
+
" `; diff --git a/tests/jest/pinnableElement.test.js b/tests/jest/pinnableElement.test.js index 3b0549f07..ce17a055b 100644 --- a/tests/jest/pinnableElement.test.js +++ b/tests/jest/pinnableElement.test.js @@ -54,8 +54,16 @@ const initializeHTML = ( headerData ) => {
${ headerData[ 'is-pinned' ] ? pinnableElementHTML : '' }
-
- ${ !headerData[ 'is-pinned' ] ? pinnableElementHTML : '' } +
+ + +
+
+ ${ !headerData[ 'is-pinned' ] ? pinnableElementHTML : '' } +
+
`; @@ -173,4 +181,17 @@ describe( 'Pinnable header', () => { expect( pinnableElement.isPinned( header ) ).toBe( false ); } ); + + test( 'setFocusAfterToggle() sets focus on appropriate element after pinnableElement is toggled', () => { + initializeHTML( movableData ); + pinnableElement.initPinnableElement(); + const dropdownCheckbox = /** @type {HTMLElement} */ ( document.getElementById( 'checkbox' ) ); + const pinButton = /** @type {HTMLElement} */ ( document.querySelector( '.vector-pinnable-header-pin-button' ) ); + const unpinButton = /** @type {HTMLElement} */ ( document.querySelector( '.vector-pinnable-header-unpin-button' ) ); + + pinButton.click(); + expect( document.activeElement ).toBe( unpinButton ); + unpinButton.click(); + expect( document.activeElement ).toBe( dropdownCheckbox ); + } ); } );