From cf1631abcb6ee92cbb08654aa7c2ecd87efc0469 Mon Sep 17 00:00:00 2001 From: NikoHelle Date: Tue, 19 Nov 2024 10:28:26 +0200 Subject: [PATCH 1/2] (hds-2521) Added options.focusTargetSelector The focus is moved to given element when banner closes on user action. --- .../cookieConsent/CookieConsent.stories.tsx | 15 +++++++----- .../CookieConsentCore.stories.tsx | 14 +++++++---- .../cookieConsentCore/cookieConsentCore.js | 24 ++++++++++++++++--- .../src/components/cookieConsentCore/types.ts | 1 + 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/packages/react/src/components/cookieConsent/CookieConsent.stories.tsx b/packages/react/src/components/cookieConsent/CookieConsent.stories.tsx index ae9e5a1ff4..8156deff53 100644 --- a/packages/react/src/components/cookieConsent/CookieConsent.stories.tsx +++ b/packages/react/src/components/cookieConsent/CookieConsent.stories.tsx @@ -60,7 +60,7 @@ const Actions = () => { }; const openBanner = async () => { // eslint-disable-next-line no-console - console.log('Spawning banner', await window.hds.cookieConsent.openBanner(['statistics', 'chat'])); + console.log('Spawning banner', await window.hds.cookieConsent.openBanner(['statistics', 'chat'], '#banner-opener')); }; return (
@@ -71,7 +71,7 @@ const Actions = () => { -
@@ -120,7 +120,8 @@ export const Example = ({ currentTabIndex }: { currentTabIndex?: number } = {}) return ( a', theme }} siteSettings={{ ...siteSettings, remove: false, monitorInterval: 0 }} >
@@ -131,6 +132,7 @@ export const Example = ({ currentTabIndex }: { currentTabIndex?: number } = {}) titleHref="https://hel.fi" logo={} logoAriaLabel="Service logo" + id="actionbar" > @@ -157,13 +159,13 @@ export const Example = ({ currentTabIndex }: { currentTabIndex?: number } = {}) -

Banner ( {language} )

+

Banner ( {language} )

Banner is shown if required consents are not consented.

-

Consents ( {language} )

+

Consents ( {language} )

Banner is also shown here when needed.

@@ -205,9 +207,10 @@ export const Banner = () => {
-

Cookie consent banner

+

Cookie consent banner

The banner is shown only if necessary.

diff --git a/packages/react/src/components/cookieConsentCore/CookieConsentCore.stories.tsx b/packages/react/src/components/cookieConsentCore/CookieConsentCore.stories.tsx index 15dbab4f0b..6f17216320 100644 --- a/packages/react/src/components/cookieConsentCore/CookieConsentCore.stories.tsx +++ b/packages/react/src/components/cookieConsentCore/CookieConsentCore.stories.tsx @@ -36,7 +36,7 @@ const Actions = () => { }; const openBanner = async () => { // eslint-disable-next-line no-console - console.log('Spawning banner', await window.hds.cookieConsent.openBanner(['statistics', 'chat'])); + console.log('Spawning banner', await window.hds.cookieConsent.openBanner(['statistics', 'chat'], '#banner-opener')); }; return ( <> @@ -45,7 +45,9 @@ const Actions = () => { - + ); @@ -71,20 +73,22 @@ const DummyContent = () => ( ); export const Banner = (options: Options = {}) => { + const focusTargetSelector = 'main h1'; + const combinedOptions: Options = { ...options, focusTargetSelector, submitEvent: true }; return (
-

Cookie consent banner

+

Cookie consent banner

The banner is shown only if necessary.

- +
); }; export const SettingsPage = (options: Options = {}) => { - const combinedOptions = { ...options, submitEvent: true }; + const combinedOptions: Options = { ...options, submitEvent: true }; return (
diff --git a/packages/react/src/components/cookieConsentCore/cookieConsentCore.js b/packages/react/src/components/cookieConsentCore/cookieConsentCore.js index 6b8d96e417..5a3ad80791 100644 --- a/packages/react/src/components/cookieConsentCore/cookieConsentCore.js +++ b/packages/react/src/components/cookieConsentCore/cookieConsentCore.js @@ -40,6 +40,7 @@ export class CookieConsentCore { #pageContentSelector; #submitEvent = false; #settingsPageSelector; + #focusTargetSelector; #disableAutoRender; #monitor; #cookieHandler; @@ -74,6 +75,7 @@ export class CookieConsentCore { * @param {string} [options.pageContentSelector='body'] - The selector for where to add scroll-margin-bottom. * @param {boolean} [options.submitEvent=false] - If set to true, do not reload the page, but submit the string as an event after consent. * @param {string} [options.settingsPageSelector=null] - If this string is set and a matching element is found on the page, show cookie settings in a page replacing the matched element. + * @param {string} [options.focusTargetSelector=null] - Selector for the element that will receive focus once the banner is closed. * @param {boolean} [options.disableAutoRender=false] - If true, neither banner or page are rendered automatically * @param {boolean} [calledFromCreate=false] - Indicates if the constructor was called from the create method. * @throws {Error} Throws an error if called from outside the create method. @@ -89,6 +91,7 @@ export class CookieConsentCore { pageContentSelector = 'body', // Where to add scroll-margin-bottom submitEvent = false, // if set, do not reload page, but submit 'hds-cookie-consent-changed' as event after consent settingsPageSelector = null, // If this string is set and a matching element is found on the page, show cookie settings in a page replacing the matched element. + focusTargetSelector = null, disableAutoRender = false, }, calledFromCreate = false, @@ -106,6 +109,7 @@ export class CookieConsentCore { this.#pageContentSelector = pageContentSelector; this.#submitEvent = submitEvent; this.#settingsPageSelector = settingsPageSelector; + this.#focusTargetSelector = focusTargetSelector; this.#disableAutoRender = disableAutoRender; CookieConsentCore.addToHdsScope('cookieConsent', this); @@ -161,6 +165,7 @@ export class CookieConsentCore { * @param {string} [options.pageContentSelector='body'] - The selector for where to add scroll-margin-bottom. * @param {boolean} [options.submitEvent=false] - If set, do not reload the page, but submit 'hds-cookie-consent-changed' event after consent. * @param {string} [options.settingsPageSelector=null] - If this string is set and a matching element is found on the page, show cookie settings in a page replacing the matched element. + * @param {string} [options.focusTargetSelector=null] - Selector for the element that will receive focus once the banner is closed. * @param {boolean} [options.disableAutoRender=false] - If... * @return {Promise} A promise that resolves to a new instance of the CookieConsent class. * @throws {Error} Throws an error if the siteSettingsParam is not a string or an object. @@ -246,13 +251,19 @@ export class CookieConsentCore { /** * Opens banner when not on cookie settings page. + * * @param {Array} highlightedGroups - Groups to highlight when opened + * * @param {string} focusTargetSelector - Selector for the element that will receive focus once the banner is closed. Overrides the options.focusTargetSelector */ - openBanner(highlightedGroups = []) { + openBanner(highlightedGroups = [], focusTargetSelector = '') { if (this.#settingsPageSelector && document.querySelector(this.#settingsPageSelector)) { // eslint-disable-next-line no-console console.error(`Cookie consent: The user is already on settings page`); return; } + + if (focusTargetSelector) { + this.#focusTargetSelector = focusTargetSelector; + } this.removeBanner(); this.#render(this.#language, this.#siteSettings, true, null, highlightedGroups); } @@ -342,7 +353,7 @@ export class CookieConsentCore { * Removes the banner and related elements. * @returns {void} */ - removeBanner() { + removeBanner(setFocus = false) { this.killTimeout(); // Remove banner size observer if (this.#resizeReference.resizeObserver && this.#resizeReference.bannerHeightElement) { @@ -360,6 +371,13 @@ export class CookieConsentCore { // Remove scroll-margin-bottom variable from all elements inside the contentSelector document.documentElement.style.removeProperty('--hds-cookie-consent-height'); + + if (setFocus && this.#focusTargetSelector) { + const element = document.querySelector(this.#focusTargetSelector); + if (element) { + element.focus(); + } + } } // MARK: Private methods @@ -417,7 +435,7 @@ export class CookieConsentCore { } else { window.dispatchEvent(new CustomEvent(cookieEventType.CHANGE, { detail: { acceptedGroups } })); if (!this.#settingsPageElement) { - this.removeBanner(); + this.removeBanner(true); // removeBanner() removes the setTimeout that shows notification // announceSettingsSaved() must be called after the removeBanner() this.#announceSettingsSaved(); diff --git a/packages/react/src/components/cookieConsentCore/types.ts b/packages/react/src/components/cookieConsentCore/types.ts index 94d3ef1816..6eaacba93b 100644 --- a/packages/react/src/components/cookieConsentCore/types.ts +++ b/packages/react/src/components/cookieConsentCore/types.ts @@ -15,6 +15,7 @@ export type Options = { pageContentSelector?: string | undefined; submitEvent?: boolean | undefined; settingsPageSelector?: string | undefined; + focusTargetSelector?: string | undefined; disableAutoRender?: boolean | undefined; }; From 4616a52a3c6b474f3707b4aa868b96fd39a0b42f Mon Sep 17 00:00:00 2001 From: NikoHelle Date: Tue, 19 Nov 2024 12:01:02 +0200 Subject: [PATCH 2/2] (hds-2521) e2e tests for focus move --- .../components/react-cookie-consent-spec.ts | 26 ++++++++++++++++-- ...roval-and-not-shown-again--desktop-png.png | Bin 18278 -> 0 bytes ...hown-again-focus-is-moved--desktop-png.png | Bin 0 -> 18286 bytes e2e/utils/playwright.util.ts | 5 ++++ 4 files changed, 28 insertions(+), 3 deletions(-) delete mode 100644 e2e/tests/react/components/react-cookie-consent-spec.ts-snapshots/banner-is-closed-after-approval-and-not-shown-again--desktop-png.png create mode 100644 e2e/tests/react/components/react-cookie-consent-spec.ts-snapshots/banner-is-closed-after-approval-and-not-shown-again-focus-is-moved--desktop-png.png diff --git a/e2e/tests/react/components/react-cookie-consent-spec.ts b/e2e/tests/react/components/react-cookie-consent-spec.ts index fc35bc1df1..f6f55d288a 100644 --- a/e2e/tests/react/components/react-cookie-consent-spec.ts +++ b/e2e/tests/react/components/react-cookie-consent-spec.ts @@ -1,10 +1,11 @@ import { test, expect, Page, Locator } from '@playwright/test'; -import { isLocatorSelectedOrChecked } from '../../../utils/element.util'; +import { getFocusedElement, isLocatorSelectedOrChecked } from '../../../utils/element.util'; import { gotoStorybookUrlByName, createScreenshotFileName, takeScreenshotWithSpacing, waitFor, + getLocatorElement, } from '../../../utils/playwright.util'; const componentName = 'cookieconsent'; const storybook = 'react'; @@ -80,7 +81,7 @@ test.describe(`Banner`, () => { const storeConsentsAndWaitForBannerClose = async ( page: Page, - approveType: 'all' | 'required', + approveType: 'all' | 'required' | 'selected', bannerLocator: Locator, ) => { const banner = bannerLocator || getBannerOrPageLocator(page); @@ -179,7 +180,7 @@ test.describe(`Banner`, () => { const screenshotNameSV = createScreenshotFileName(testInfo, isMobile, 'sv language'); await takeScreenshotWithSpacing(page, banner, screenshotNameSV); }); - test('Banner is closed after approval and not shown again.', async ({ page, isMobile }, testInfo) => { + test('Banner is closed after approval and not shown again. Focus is moved.', async ({ page, isMobile }, testInfo) => { if (isMobile) { // viewport is too small to test with mobile view. Banner blocks the ui. return; @@ -188,6 +189,9 @@ test.describe(`Banner`, () => { await changeTab(page, 'banner'); const banner = getBannerOrPageLocator(page); await storeConsentsAndWaitForBannerClose(page, 'all', banner); + const focusTarget = await getLocatorElement(page.locator('#actionbar > a')); + const focusedElement = await getFocusedElement(page.locator('body')); + expect(focusTarget === focusedElement).toBeTruthy(); const screenshotName = createScreenshotFileName(testInfo, isMobile); await takeScreenshotWithSpacing(page, page.locator('body'), screenshotName); @@ -207,6 +211,22 @@ test.describe(`Banner`, () => { const consents = await approveRequiredAndCheckStoredConsents(page); expect(consents).toEqual(['essential', 'test_essential']); }); + test('Element given in openBanner is focused on banner close', async ({ page, isMobile }, testInfo) => { + if (isMobile) { + // viewport is too small to test with mobile view. Banner blocks the ui. + return; + } + const openerSelector = '#banner-opener'; + await gotoStorybookUrlByName(page, 'Example', componentName, storybook); + await changeTab(page, 'actions'); + const bannerOpener = page.locator(openerSelector); + const banner = getBannerOrPageLocator(page); + await bannerOpener.click(); + await storeConsentsAndWaitForBannerClose(page, 'selected', banner); + const focusTarget = await getLocatorElement(page.locator(openerSelector)); + const focusedElement = await getFocusedElement(page.locator('body')); + expect(focusTarget === focusedElement).toBeTruthy(); + }); test('Stored consents are changed via settings page', async ({ page, isMobile }, testInfo) => { if (isMobile) { // viewport is too small to test with mobile view. Banner blocks the ui. diff --git a/e2e/tests/react/components/react-cookie-consent-spec.ts-snapshots/banner-is-closed-after-approval-and-not-shown-again--desktop-png.png b/e2e/tests/react/components/react-cookie-consent-spec.ts-snapshots/banner-is-closed-after-approval-and-not-shown-again--desktop-png.png deleted file mode 100644 index e81ee9041b8ee8d6e8e780ad75d129c52432fab5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18278 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 diff --git a/e2e/tests/react/components/react-cookie-consent-spec.ts-snapshots/banner-is-closed-after-approval-and-not-shown-again-focus-is-moved--desktop-png.png b/e2e/tests/react/components/react-cookie-consent-spec.ts-snapshots/banner-is-closed-after-approval-and-not-shown-again-focus-is-moved--desktop-png.png new file mode 100644 index 0000000000000000000000000000000000000000..6599225b455d4dd901cb7355787aed835909e637 GIT binary patch literal 18286 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 => { + const first = locator.first(); + return first.evaluate((el) => el); +};