From 5c01c2007ee144b31d5bf4e97a33ce17baaba92d Mon Sep 17 00:00:00 2001 From: Lauri Eskola <lauri.eskola@acquia.com> Date: Fri, 17 Sep 2021 10:45:27 +0300 Subject: [PATCH] Issue #3226785 by mherchel, Gauravmahlawat, thejimbirch, andy-blum, schillerm: Olivero: Wide search form should close on blur --- .../Tests/Olivero/oliveroSearchFormTest.js | 44 ++++++++++++++++--- core/themes/olivero/js/search.es6.js | 32 +++++++------- core/themes/olivero/js/search.js | 15 ++++--- 3 files changed, 63 insertions(+), 28 deletions(-) diff --git a/core/tests/Drupal/Nightwatch/Tests/Olivero/oliveroSearchFormTest.js b/core/tests/Drupal/Nightwatch/Tests/Olivero/oliveroSearchFormTest.js index 63366c1f7e42..83e51a4af563 100644 --- a/core/tests/Drupal/Nightwatch/Tests/Olivero/oliveroSearchFormTest.js +++ b/core/tests/Drupal/Nightwatch/Tests/Olivero/oliveroSearchFormTest.js @@ -3,6 +3,7 @@ const headerNavSelector = '#header-nav'; const searchButtonSelector = 'button.block-search-wide__button'; const searchFormSelector = '.search-form.search-block-form'; const searchWideSelector = '.block-search-wide__wrapper'; +const searchWideInputSelector = '#edit-keys--2'; const searchNarrowSelector = '.block-search-narrow'; module.exports = { @@ -32,24 +33,57 @@ module.exports = { .waitForElementVisible(searchButtonSelector) .assert.attributeEquals(searchButtonSelector, 'aria-expanded', 'false') .click(searchButtonSelector) - .waitForElementVisible(`${searchWideSelector}`) - .waitForElementVisible(`${searchWideSelector} ${searchFormSelector}`) + .waitForElementVisible(searchWideInputSelector) .assert.attributeEquals(searchButtonSelector, 'aria-expanded', 'true') .assert.attributeContains( - `${searchWideSelector} ${searchFormSelector} input[name=keys]`, + searchWideInputSelector, 'placeholder', 'Search by keyword or phrase.', ) .assert.attributeContains( - `${searchWideSelector} ${searchFormSelector} input[name=keys]`, + searchWideInputSelector, 'title', 'Enter the terms you wish to search for.', ) .assert.elementPresent('button.search-form__submit') + // Assert wide search form closes when element moves to body. .click('body') - .waitForElementNotVisible(`${searchWideSelector}`) + .waitForElementNotVisible(searchWideSelector) .assert.attributeEquals(searchButtonSelector, 'aria-expanded', 'false'); }, + 'Test focus management': (browser) => { + browser + .drupalRelativeURL('/') + .waitForElementVisible(searchButtonSelector) + .click(searchButtonSelector) + .waitForElementVisible(searchWideInputSelector) + .pause(400) // Wait for transitionend event to fire. + // Assert that focus is moved to wide search text input. + .execute( + // eslint-disable-next-line func-names, prefer-arrow-callback, no-shadow + function (searchWideInputSelector) { + return document.activeElement.matches(searchWideInputSelector); + }, + [searchWideInputSelector], + (result) => { + browser.assert.ok( + result.value, + 'Assert that focus moves to wide search form on open.', + ); + }, + ) + // Assert that search form is still visible when focus is on disclosure button. + .keys(browser.Keys.SHIFT) + .keys(browser.Keys.TAB) + .pause(50) + .isVisible(searchWideSelector) + // Assert that search form is NOT visible when focus moves back to menu item. + .keys(browser.Keys.TAB) + .pause(50) + .waitForElementNotVisible(searchWideSelector) + // Release all keys. + .keys(browser.Keys.NULL); + }, 'search narrow form is accessible': (browser) => { browser .resizeWindow(1000, 800) diff --git a/core/themes/olivero/js/search.es6.js b/core/themes/olivero/js/search.es6.js index d542770a90bc..4fc8f35396c5 100644 --- a/core/themes/olivero/js/search.es6.js +++ b/core/themes/olivero/js/search.es6.js @@ -28,7 +28,8 @@ function handleFocus() { if (searchIsVisible()) { searchWideWrapper.querySelector('input[type="search"]').focus(); - } else { + } else if (searchWideWrapper.contains(document.activeElement)) { + // Return focus to button only if focus was inside of the search wrapper. searchWideButton.focus(); } } @@ -61,21 +62,8 @@ } }); - document.addEventListener('click', (e) => { - if ( - e.target.matches( - '[data-drupal-selector="block-search-wide-button"], [data-drupal-selector="block-search-wide-button"] *', - ) - ) { - toggleSearchVisibility(!searchIsVisible()); - } else if ( - searchIsVisible() && - !e.target.matches( - '[data-drupal-selector="block-search-wide-wrapper"], [data-drupal-selector="block-search-wide-wrapper"] *', - ) - ) { - toggleSearchVisibility(false); - } + searchWideButton.addEventListener('click', () => { + toggleSearchVisibility(!searchIsVisible()); }); /** @@ -98,4 +86,16 @@ } }, }; + + /** + * Close the wide search container if focus moves from either the container + * or its toggle button. + */ + document + .querySelector('[data-drupal-selector="search-block-form-2"]') + .addEventListener('focusout', (e) => { + if (!e.currentTarget.contains(e.relatedTarget)) { + toggleSearchVisibility(false); + } + }); })(Drupal); diff --git a/core/themes/olivero/js/search.js b/core/themes/olivero/js/search.js index 97bb6aac400d..2d96deb22030 100644 --- a/core/themes/olivero/js/search.js +++ b/core/themes/olivero/js/search.js @@ -18,7 +18,7 @@ function handleFocus() { if (searchIsVisible()) { searchWideWrapper.querySelector('input[type="search"]').focus(); - } else { + } else if (searchWideWrapper.contains(document.activeElement)) { searchWideButton.focus(); } } @@ -43,12 +43,8 @@ toggleSearchVisibility(false); } }); - document.addEventListener('click', function (e) { - if (e.target.matches('[data-drupal-selector="block-search-wide-button"], [data-drupal-selector="block-search-wide-button"] *')) { - toggleSearchVisibility(!searchIsVisible()); - } else if (searchIsVisible() && !e.target.matches('[data-drupal-selector="block-search-wide-wrapper"], [data-drupal-selector="block-search-wide-wrapper"] *')) { - toggleSearchVisibility(false); - } + searchWideButton.addEventListener('click', function () { + toggleSearchVisibility(!searchIsVisible()); }); Drupal.behaviors.searchWide = { attach: function attach(context) { @@ -59,4 +55,9 @@ } } }; + document.querySelector('[data-drupal-selector="search-block-form-2"]').addEventListener('focusout', function (e) { + if (!e.currentTarget.contains(e.relatedTarget)) { + toggleSearchVisibility(false); + } + }); })(Drupal); \ No newline at end of file -- GitLab