From 02bcbdd72a661ba0712c6b1f3cc3eb68d8d5acf2 Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Wed, 13 Dec 2023 09:49:04 +0000 Subject: [PATCH 1/7] Rename Sass partial for CSS custom properties --- packages/govuk-frontend/src/govuk/core/_all.scss | 2 +- ...-frontend-version.scss => _govuk-frontend-properties.scss} | 0 packages/govuk-frontend/tasks/build/release.unit.test.mjs | 4 ++-- 3 files changed, 3 insertions(+), 3 deletions(-) rename packages/govuk-frontend/src/govuk/core/{_govuk-frontend-version.scss => _govuk-frontend-properties.scss} (100%) diff --git a/packages/govuk-frontend/src/govuk/core/_all.scss b/packages/govuk-frontend/src/govuk/core/_all.scss index 3cc0d13c17..48e95beaf5 100644 --- a/packages/govuk-frontend/src/govuk/core/_all.scss +++ b/packages/govuk-frontend/src/govuk/core/_all.scss @@ -1,4 +1,4 @@ -@import "govuk-frontend-version"; +@import "govuk-frontend-properties"; @import "links"; @import "lists"; @import "typography"; diff --git a/packages/govuk-frontend/src/govuk/core/_govuk-frontend-version.scss b/packages/govuk-frontend/src/govuk/core/_govuk-frontend-properties.scss similarity index 100% rename from packages/govuk-frontend/src/govuk/core/_govuk-frontend-version.scss rename to packages/govuk-frontend/src/govuk/core/_govuk-frontend-properties.scss diff --git a/packages/govuk-frontend/tasks/build/release.unit.test.mjs b/packages/govuk-frontend/tasks/build/release.unit.test.mjs index d72502f52d..1fe149e38e 100644 --- a/packages/govuk-frontend/tasks/build/release.unit.test.mjs +++ b/packages/govuk-frontend/tasks/build/release.unit.test.mjs @@ -49,7 +49,7 @@ describe('dist/', () => { ) }) - it('should contain version number custom property', () => { + it('should contain CSS custom properties', () => { expect(stylesheet).toContain(`--govuk-frontend-version:"${pkg.version}"`) }) }) @@ -70,7 +70,7 @@ describe('dist/', () => { '../packages/govuk-frontend/src/govuk/all.scss' ) expect(sourcemap.sources).toContain( - '../packages/govuk-frontend/src/govuk/core/_govuk-frontend-version.scss' + '../packages/govuk-frontend/src/govuk/core/_govuk-frontend-properties.scss' ) }) }) From 5ba7af3af2bfba59a4b1c1fd72b801b865a38a5b Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Wed, 13 Dec 2023 10:58:12 +0000 Subject: [PATCH 2/7] Add CSS custom property for each breakpoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All browsers that support ES modules… Support CSS custom properties https://browsersl.ist/#q=supports+es6-module+and+not+supports+css-variables Support CSS rem units https://browsersl.ist/#q=supports+es6-module+and+not+supports+rem --- .../src/govuk/core/_govuk-frontend-properties.scss | 5 +++++ .../govuk-frontend/tasks/build/release.unit.test.mjs | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/packages/govuk-frontend/src/govuk/core/_govuk-frontend-properties.scss b/packages/govuk-frontend/src/govuk/core/_govuk-frontend-properties.scss index 5e6d9a1645..0e211c4483 100644 --- a/packages/govuk-frontend/src/govuk/core/_govuk-frontend-properties.scss +++ b/packages/govuk-frontend/src/govuk/core/_govuk-frontend-properties.scss @@ -2,4 +2,9 @@ // This variable is automatically overwritten during builds and releases. // It doesn't need to be updated manually. --govuk-frontend-version: "development"; + + // CSS custom property for each breakpoint + @each $name, $value in $govuk-breakpoints { + --govuk-frontend-breakpoint-#{$name}: #{govuk-px-to-rem($value)}; + } } diff --git a/packages/govuk-frontend/tasks/build/release.unit.test.mjs b/packages/govuk-frontend/tasks/build/release.unit.test.mjs index 1fe149e38e..dcc306660d 100644 --- a/packages/govuk-frontend/tasks/build/release.unit.test.mjs +++ b/packages/govuk-frontend/tasks/build/release.unit.test.mjs @@ -50,7 +50,17 @@ describe('dist/', () => { }) it('should contain CSS custom properties', () => { + // GOV.UK Frontend version number expect(stylesheet).toContain(`--govuk-frontend-version:"${pkg.version}"`) + + // Breakpoints for `window.matchMedia()` in Header, Tabs components + expect(stylesheet).toContain('--govuk-frontend-breakpoint-mobile:20rem') + expect(stylesheet).toContain( + '--govuk-frontend-breakpoint-tablet:40.0625rem' + ) + expect(stylesheet).toContain( + '--govuk-frontend-breakpoint-desktop:48.0625rem' + ) }) }) From b627242fd068f4186ea8edaf61c57fefd4f42377 Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Wed, 13 Dec 2023 10:10:25 +0000 Subject: [PATCH 3/7] Align Header with Tabs `setupResponsiveChecks()` + `checkMode()` --- .../src/govuk/components/header/header.mjs | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/packages/govuk-frontend/src/govuk/components/header/header.mjs b/packages/govuk-frontend/src/govuk/components/header/header.mjs index 856b7dff25..81679a9649 100644 --- a/packages/govuk-frontend/src/govuk/components/header/header.mjs +++ b/packages/govuk-frontend/src/govuk/components/header/header.mjs @@ -83,23 +83,33 @@ export class Header extends GOVUKFrontendComponent { this.$menu = $menu this.$menuButton = $menuButton + this.setupResponsiveChecks() + + this.$menuButton.addEventListener('click', () => + this.handleMenuButtonClick() + ) + } + + /** + * Setup viewport resize check + * + * @private + */ + setupResponsiveChecks() { // Set the matchMedia to the govuk-frontend desktop breakpoint this.mql = window.matchMedia('(min-width: 48.0625em)') // MediaQueryList.addEventListener isn't supported by Safari < 14 so we need // to be able to fall back to the deprecated MediaQueryList.addListener if ('addEventListener' in this.mql) { - this.mql.addEventListener('change', () => this.syncState()) + this.mql.addEventListener('change', () => this.checkMode()) } else { // @ts-expect-error Property 'addListener' does not exist // eslint-disable-next-line @typescript-eslint/no-unsafe-call - this.mql.addListener(() => this.syncState()) + this.mql.addListener(() => this.checkMode()) } - this.syncState() - this.$menuButton.addEventListener('click', () => - this.handleMenuButtonClick() - ) + this.checkMode() } /** @@ -112,7 +122,7 @@ export class Header extends GOVUKFrontendComponent { * * @private */ - syncState() { + checkMode() { if (!this.mql || !this.$menu || !this.$menuButton) { return } @@ -142,7 +152,7 @@ export class Header extends GOVUKFrontendComponent { */ handleMenuButtonClick() { this.menuIsOpen = !this.menuIsOpen - this.syncState() + this.checkMode() } /** From 5ddc7eb6be22209c9649a07ceb675e86d19a1fc3 Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Wed, 13 Dec 2023 10:30:28 +0000 Subject: [PATCH 4/7] Use CSS custom properties in component `matchMedia()` This change ensures services that override `$govuk-breakpoints` see Tabs and Header media query breakpoints align with the overridden Sass breakpoint values --- .../src/govuk/components/header/header.mjs | 9 +++++++-- .../govuk-frontend/src/govuk/components/tabs/tabs.mjs | 8 +++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/packages/govuk-frontend/src/govuk/components/header/header.mjs b/packages/govuk-frontend/src/govuk/components/header/header.mjs index 81679a9649..30c71d590d 100644 --- a/packages/govuk-frontend/src/govuk/components/header/header.mjs +++ b/packages/govuk-frontend/src/govuk/components/header/header.mjs @@ -96,8 +96,13 @@ export class Header extends GOVUKFrontendComponent { * @private */ setupResponsiveChecks() { - // Set the matchMedia to the govuk-frontend desktop breakpoint - this.mql = window.matchMedia('(min-width: 48.0625em)') + const breakpointProperty = '--govuk-frontend-breakpoint-desktop' + const breakpointValue = window + .getComputedStyle(document.documentElement) + .getPropertyValue(breakpointProperty) + + // Media query list for GOV.UK Frontend desktop breakpoint + this.mql = window.matchMedia(`(min-width: ${breakpointValue})`) // MediaQueryList.addEventListener isn't supported by Safari < 14 so we need // to be able to fall back to the deprecated MediaQueryList.addListener diff --git a/packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs b/packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs index b5f79c381e..854bb217e4 100644 --- a/packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs +++ b/packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs @@ -105,7 +105,13 @@ export class Tabs extends GOVUKFrontendComponent { * @private */ setupResponsiveChecks() { - this.mql = window.matchMedia('(min-width: 40.0625em)') + const breakpointProperty = '--govuk-frontend-breakpoint-tablet' + const breakpointValue = window + .getComputedStyle(document.documentElement) + .getPropertyValue(breakpointProperty) + + // Media query list for GOV.UK Frontend tablet breakpoint + this.mql = window.matchMedia(`(min-width: ${breakpointValue})`) // MediaQueryList.addEventListener isn't supported by Safari < 14 so we need // to be able to fall back to the deprecated MediaQueryList.addListener From cd3e1715d754d71e24ddec311f3ac95930b88197 Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Wed, 13 Dec 2023 10:31:05 +0000 Subject: [PATCH 5/7] Throw errors when CSS custom properties are missing --- .../govuk-frontend/src/govuk/components/header/header.mjs | 7 +++++++ packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/packages/govuk-frontend/src/govuk/components/header/header.mjs b/packages/govuk-frontend/src/govuk/components/header/header.mjs index 30c71d590d..41128a5ed4 100644 --- a/packages/govuk-frontend/src/govuk/components/header/header.mjs +++ b/packages/govuk-frontend/src/govuk/components/header/header.mjs @@ -101,6 +101,13 @@ export class Header extends GOVUKFrontendComponent { .getComputedStyle(document.documentElement) .getPropertyValue(breakpointProperty) + if (!breakpointValue) { + throw new ElementError({ + componentName: 'Header', + identifier: `CSS custom property (\`${breakpointProperty}\`)` + }) + } + // Media query list for GOV.UK Frontend desktop breakpoint this.mql = window.matchMedia(`(min-width: ${breakpointValue})`) diff --git a/packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs b/packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs index 854bb217e4..157cf1a0f3 100644 --- a/packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs +++ b/packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs @@ -110,6 +110,13 @@ export class Tabs extends GOVUKFrontendComponent { .getComputedStyle(document.documentElement) .getPropertyValue(breakpointProperty) + if (!breakpointValue) { + throw new ElementError({ + componentName: 'Tabs', + identifier: `CSS custom property (\`${breakpointProperty}\`)` + }) + } + // Media query list for GOV.UK Frontend tablet breakpoint this.mql = window.matchMedia(`(min-width: ${breakpointValue})`) From 562cfdd7c877fcbe7c8aab3e94379c4cdfe7d0c2 Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Fri, 15 Dec 2023 14:30:10 +0000 Subject: [PATCH 6/7] Add `getBreakpoint()` to common utilities Co-Authored-By: Romaric --- .../govuk-frontend/src/govuk/common/index.mjs | 21 +++++++++++++++++++ .../src/govuk/components/header/header.mjs | 12 +++++------ .../src/govuk/components/tabs/tabs.mjs | 13 +++++------- 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/packages/govuk-frontend/src/govuk/common/index.mjs b/packages/govuk-frontend/src/govuk/common/index.mjs index 8984b5a9e8..c3f21d11e2 100644 --- a/packages/govuk-frontend/src/govuk/common/index.mjs +++ b/packages/govuk-frontend/src/govuk/common/index.mjs @@ -133,6 +133,27 @@ export function getFragmentFromUrl(url) { return url.split('#').pop() } +/** + * Get GOV.UK Frontend breakpoint value from CSS custom property + * + * @private + * @param {string} name - Breakpoint name + * @returns {{ property: string, value?: string }} Breakpoint object + */ +export function getBreakpoint(name) { + const property = `--govuk-frontend-breakpoint-${name}` + + // Get value from `` with breakpoints on CSS :root + const value = window + .getComputedStyle(document.documentElement) + .getPropertyValue(property) + + return { + property, + value: value || undefined + } +} + /** * Move focus to element * diff --git a/packages/govuk-frontend/src/govuk/components/header/header.mjs b/packages/govuk-frontend/src/govuk/components/header/header.mjs index 41128a5ed4..5f9bcbc356 100644 --- a/packages/govuk-frontend/src/govuk/components/header/header.mjs +++ b/packages/govuk-frontend/src/govuk/components/header/header.mjs @@ -1,3 +1,4 @@ +import { getBreakpoint } from '../../common/index.mjs' import { ElementError } from '../../errors/index.mjs' import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs' @@ -96,20 +97,17 @@ export class Header extends GOVUKFrontendComponent { * @private */ setupResponsiveChecks() { - const breakpointProperty = '--govuk-frontend-breakpoint-desktop' - const breakpointValue = window - .getComputedStyle(document.documentElement) - .getPropertyValue(breakpointProperty) + const breakpoint = getBreakpoint('desktop') - if (!breakpointValue) { + if (!breakpoint.value) { throw new ElementError({ componentName: 'Header', - identifier: `CSS custom property (\`${breakpointProperty}\`)` + identifier: `CSS custom property (\`${breakpoint.property}\`)` }) } // Media query list for GOV.UK Frontend desktop breakpoint - this.mql = window.matchMedia(`(min-width: ${breakpointValue})`) + this.mql = window.matchMedia(`(min-width: ${breakpoint.value})`) // MediaQueryList.addEventListener isn't supported by Safari < 14 so we need // to be able to fall back to the deprecated MediaQueryList.addListener diff --git a/packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs b/packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs index 157cf1a0f3..6358d114de 100644 --- a/packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs +++ b/packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs @@ -1,4 +1,4 @@ -import { getFragmentFromUrl } from '../../common/index.mjs' +import { getBreakpoint, getFragmentFromUrl } from '../../common/index.mjs' import { ElementError } from '../../errors/index.mjs' import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs' @@ -105,20 +105,17 @@ export class Tabs extends GOVUKFrontendComponent { * @private */ setupResponsiveChecks() { - const breakpointProperty = '--govuk-frontend-breakpoint-tablet' - const breakpointValue = window - .getComputedStyle(document.documentElement) - .getPropertyValue(breakpointProperty) + const breakpoint = getBreakpoint('tablet') - if (!breakpointValue) { + if (!breakpoint.value) { throw new ElementError({ componentName: 'Tabs', - identifier: `CSS custom property (\`${breakpointProperty}\`)` + identifier: `CSS custom property (\`${breakpoint.property}\`)` }) } // Media query list for GOV.UK Frontend tablet breakpoint - this.mql = window.matchMedia(`(min-width: ${breakpointValue})`) + this.mql = window.matchMedia(`(min-width: ${breakpoint.value})`) // MediaQueryList.addEventListener isn't supported by Safari < 14 so we need // to be able to fall back to the deprecated MediaQueryList.addListener From 05b819af0368b1008c26a19dc80cf6fbfaac53b9 Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Fri, 15 Dec 2023 14:32:43 +0000 Subject: [PATCH 7/7] Clarify where CSS custom properties are defined https://github.com/alphagov/govuk-frontend/pull/4562#discussion_r1427030841 --- packages/govuk-frontend/src/govuk/components/header/header.mjs | 2 +- packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/govuk-frontend/src/govuk/components/header/header.mjs b/packages/govuk-frontend/src/govuk/components/header/header.mjs index 5f9bcbc356..0e03a309b4 100644 --- a/packages/govuk-frontend/src/govuk/components/header/header.mjs +++ b/packages/govuk-frontend/src/govuk/components/header/header.mjs @@ -102,7 +102,7 @@ export class Header extends GOVUKFrontendComponent { if (!breakpoint.value) { throw new ElementError({ componentName: 'Header', - identifier: `CSS custom property (\`${breakpoint.property}\`)` + identifier: `CSS custom property (\`${breakpoint.property}\`) on pseudo-class \`:root\`` }) } diff --git a/packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs b/packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs index 6358d114de..907c8a2e42 100644 --- a/packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs +++ b/packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs @@ -110,7 +110,7 @@ export class Tabs extends GOVUKFrontendComponent { if (!breakpoint.value) { throw new ElementError({ componentName: 'Tabs', - identifier: `CSS custom property (\`${breakpoint.property}\`)` + identifier: `CSS custom property (\`${breakpoint.property}\`) on pseudo-class \`:root\`` }) }