-
Notifications
You must be signed in to change notification settings - Fork 338
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use CSS custom properties for component matchMedia()
#4562
Conversation
📋 StatsFile sizes
Modules
View stats and visualisations on the review app Action run for 05b819a |
JavaScript changes to npm packagediff --git a/packages/govuk-frontend/dist/govuk/govuk-frontend.min.js b/packages/govuk-frontend/dist/govuk/govuk-frontend.min.js
index 7b92e7d1c..77bb7c649 100644
--- a/packages/govuk-frontend/dist/govuk/govuk-frontend.min.js
+++ b/packages/govuk-frontend/dist/govuk/govuk-frontend.min.js
@@ -34,6 +34,14 @@ function getFragmentFromUrl(t) {
if (t.includes("#")) return t.split("#").pop()
}
+function getBreakpoint(t) {
+ const e = `--govuk-frontend-breakpoint-${t}`;
+ return {
+ property: e,
+ value: window.getComputedStyle(document.documentElement).getPropertyValue(e) || void 0
+ }
+}
+
function setFocus(t, e = {}) {
var n;
const i = t.getAttribute("tabindex");
@@ -697,13 +705,21 @@ class Header extends GOVUKFrontendComponent {
element: i,
identifier: `Navigation (\`<ul id="${n}">\`)`
});
- this.$menu = i, this.$menuButton = e, this.mql = window.matchMedia("(min-width: 48.0625em)"), "addEventListener" in this.mql ? this.mql.addEventListener("change", (() => this.syncState())) : this.mql.addListener((() => this.syncState())), this.syncState(), this.$menuButton.addEventListener("click", (() => this.handleMenuButtonClick()))
+ this.$menu = i, this.$menuButton = e, this.setupResponsiveChecks(), this.$menuButton.addEventListener("click", (() => this.handleMenuButtonClick()))
+ }
+ setupResponsiveChecks() {
+ const t = getBreakpoint("desktop");
+ if (!t.value) throw new ElementError({
+ componentName: "Header",
+ identifier: `CSS custom property (\`${t.property}\`) on pseudo-class \`:root\``
+ });
+ this.mql = window.matchMedia(`(min-width: ${t.value})`), "addEventListener" in this.mql ? this.mql.addEventListener("change", (() => this.checkMode())) : this.mql.addListener((() => this.checkMode())), this.checkMode()
}
- syncState() {
+ checkMode() {
this.mql && this.$menu && this.$menuButton && (this.mql.matches ? (this.$menu.removeAttribute("hidden"), this.$menuButton.setAttribute("hidden", "")) : (this.$menuButton.removeAttribute("hidden"), this.$menuButton.setAttribute("aria-expanded", this.menuIsOpen.toString()), this.menuIsOpen ? this.$menu.removeAttribute("hidden") : this.$menu.setAttribute("hidden", "")))
}
handleMenuButtonClick() {
- this.menuIsOpen = !this.menuIsOpen, this.syncState()
+ this.menuIsOpen = !this.menuIsOpen, this.checkMode()
}
}
Header.moduleName = "govuk-header";
@@ -837,7 +853,12 @@ class Tabs extends GOVUKFrontendComponent {
this.$tabList = n, this.$tabListItems = i, this.setupResponsiveChecks()
}
setupResponsiveChecks() {
- this.mql = window.matchMedia("(min-width: 40.0625em)"), "addEventListener" in this.mql ? this.mql.addEventListener("change", (() => this.checkMode())) : this.mql.addListener((() => this.checkMode())), this.checkMode()
+ const t = getBreakpoint("tablet");
+ if (!t.value) throw new ElementError({
+ componentName: "Tabs",
+ identifier: `CSS custom property (\`${t.property}\`) on pseudo-class \`:root\``
+ });
+ this.mql = window.matchMedia(`(min-width: ${t.value})`), "addEventListener" in this.mql ? this.mql.addEventListener("change", (() => this.checkMode())) : this.mql.addListener((() => this.checkMode())), this.checkMode()
}
checkMode() {
var t;
Action run for 05b819a |
Stylesheets changes to npm packagediff --git a/packages/govuk-frontend/dist/govuk/govuk-frontend.min.css b/packages/govuk-frontend/dist/govuk/govuk-frontend.min.css
index c00459365..7036eb68b 100644
--- a/packages/govuk-frontend/dist/govuk/govuk-frontend.min.css
+++ b/packages/govuk-frontend/dist/govuk/govuk-frontend.min.css
@@ -1,7 +1,10 @@
@charset "UTF-8";
:root {
- --govuk-frontend-version: "development"
+ --govuk-frontend-version: "development";
+ --govuk-frontend-breakpoint-mobile: 20rem;
+ --govuk-frontend-breakpoint-tablet: 40.0625rem;
+ --govuk-frontend-breakpoint-desktop: 48.0625rem
}
.govuk-link {
Action run for 05b819a |
Other changes to npm packagediff --git a/packages/govuk-frontend/dist/govuk/all.bundle.js b/packages/govuk-frontend/dist/govuk/all.bundle.js
index e3b6dffa8..595d5851f 100644
--- a/packages/govuk-frontend/dist/govuk/all.bundle.js
+++ b/packages/govuk-frontend/dist/govuk/all.bundle.js
@@ -51,6 +51,14 @@
}
return url.split('#').pop();
}
+ function getBreakpoint(name) {
+ const property = `--govuk-frontend-breakpoint-${name}`;
+ const value = window.getComputedStyle(document.documentElement).getPropertyValue(property);
+ return {
+ property,
+ value: value || undefined
+ };
+ }
function setFocus($element, options = {}) {
var _options$onBeforeFocu;
const isFocusable = $element.getAttribute('tabindex');
@@ -1551,16 +1559,26 @@
}
this.$menu = $menu;
this.$menuButton = $menuButton;
- this.mql = window.matchMedia('(min-width: 48.0625em)');
+ this.setupResponsiveChecks();
+ this.$menuButton.addEventListener('click', () => this.handleMenuButtonClick());
+ }
+ setupResponsiveChecks() {
+ const breakpoint = getBreakpoint('desktop');
+ if (!breakpoint.value) {
+ throw new ElementError({
+ componentName: 'Header',
+ identifier: `CSS custom property (\`${breakpoint.property}\`) on pseudo-class \`:root\``
+ });
+ }
+ this.mql = window.matchMedia(`(min-width: ${breakpoint.value})`);
if ('addEventListener' in this.mql) {
- this.mql.addEventListener('change', () => this.syncState());
+ this.mql.addEventListener('change', () => this.checkMode());
} else {
- this.mql.addListener(() => this.syncState());
+ this.mql.addListener(() => this.checkMode());
}
- this.syncState();
- this.$menuButton.addEventListener('click', () => this.handleMenuButtonClick());
+ this.checkMode();
}
- syncState() {
+ checkMode() {
if (!this.mql || !this.$menu || !this.$menuButton) {
return;
}
@@ -1579,7 +1597,7 @@
}
handleMenuButtonClick() {
this.menuIsOpen = !this.menuIsOpen;
- this.syncState();
+ this.checkMode();
}
}
Header.moduleName = 'govuk-header';
@@ -1844,7 +1862,14 @@
this.setupResponsiveChecks();
}
setupResponsiveChecks() {
- this.mql = window.matchMedia('(min-width: 40.0625em)');
+ const breakpoint = getBreakpoint('tablet');
+ if (!breakpoint.value) {
+ throw new ElementError({
+ componentName: 'Tabs',
+ identifier: `CSS custom property (\`${breakpoint.property}\`) on pseudo-class \`:root\``
+ });
+ }
+ this.mql = window.matchMedia(`(min-width: ${breakpoint.value})`);
if ('addEventListener' in this.mql) {
this.mql.addEventListener('change', () => this.checkMode());
} else {
diff --git a/packages/govuk-frontend/dist/govuk/all.bundle.mjs b/packages/govuk-frontend/dist/govuk/all.bundle.mjs
index 52c2325ba..7375fe834 100644
--- a/packages/govuk-frontend/dist/govuk/all.bundle.mjs
+++ b/packages/govuk-frontend/dist/govuk/all.bundle.mjs
@@ -45,6 +45,14 @@ function getFragmentFromUrl(url) {
}
return url.split('#').pop();
}
+function getBreakpoint(name) {
+ const property = `--govuk-frontend-breakpoint-${name}`;
+ const value = window.getComputedStyle(document.documentElement).getPropertyValue(property);
+ return {
+ property,
+ value: value || undefined
+ };
+}
function setFocus($element, options = {}) {
var _options$onBeforeFocu;
const isFocusable = $element.getAttribute('tabindex');
@@ -1545,16 +1553,26 @@ class Header extends GOVUKFrontendComponent {
}
this.$menu = $menu;
this.$menuButton = $menuButton;
- this.mql = window.matchMedia('(min-width: 48.0625em)');
+ this.setupResponsiveChecks();
+ this.$menuButton.addEventListener('click', () => this.handleMenuButtonClick());
+ }
+ setupResponsiveChecks() {
+ const breakpoint = getBreakpoint('desktop');
+ if (!breakpoint.value) {
+ throw new ElementError({
+ componentName: 'Header',
+ identifier: `CSS custom property (\`${breakpoint.property}\`) on pseudo-class \`:root\``
+ });
+ }
+ this.mql = window.matchMedia(`(min-width: ${breakpoint.value})`);
if ('addEventListener' in this.mql) {
- this.mql.addEventListener('change', () => this.syncState());
+ this.mql.addEventListener('change', () => this.checkMode());
} else {
- this.mql.addListener(() => this.syncState());
+ this.mql.addListener(() => this.checkMode());
}
- this.syncState();
- this.$menuButton.addEventListener('click', () => this.handleMenuButtonClick());
+ this.checkMode();
}
- syncState() {
+ checkMode() {
if (!this.mql || !this.$menu || !this.$menuButton) {
return;
}
@@ -1573,7 +1591,7 @@ class Header extends GOVUKFrontendComponent {
}
handleMenuButtonClick() {
this.menuIsOpen = !this.menuIsOpen;
- this.syncState();
+ this.checkMode();
}
}
Header.moduleName = 'govuk-header';
@@ -1838,7 +1856,14 @@ class Tabs extends GOVUKFrontendComponent {
this.setupResponsiveChecks();
}
setupResponsiveChecks() {
- this.mql = window.matchMedia('(min-width: 40.0625em)');
+ const breakpoint = getBreakpoint('tablet');
+ if (!breakpoint.value) {
+ throw new ElementError({
+ componentName: 'Tabs',
+ identifier: `CSS custom property (\`${breakpoint.property}\`) on pseudo-class \`:root\``
+ });
+ }
+ this.mql = window.matchMedia(`(min-width: ${breakpoint.value})`);
if ('addEventListener' in this.mql) {
this.mql.addEventListener('change', () => this.checkMode());
} else {
diff --git a/packages/govuk-frontend/dist/govuk/common/index.mjs b/packages/govuk-frontend/dist/govuk/common/index.mjs
index aa2548704..1d272c1ba 100644
--- a/packages/govuk-frontend/dist/govuk/common/index.mjs
+++ b/packages/govuk-frontend/dist/govuk/common/index.mjs
@@ -43,6 +43,14 @@ function getFragmentFromUrl(url) {
}
return url.split('#').pop();
}
+function getBreakpoint(name) {
+ const property = `--govuk-frontend-breakpoint-${name}`;
+ const value = window.getComputedStyle(document.documentElement).getPropertyValue(property);
+ return {
+ property,
+ value: value || undefined
+ };
+}
function setFocus($element, options = {}) {
var _options$onBeforeFocu;
const isFocusable = $element.getAttribute('tabindex');
@@ -107,5 +115,5 @@ function validateConfig(schema, config) {
* @property {string} errorMessage - Error message when required config fields not provided
*/
-export { extractConfigByNamespace, getFragmentFromUrl, isSupported, mergeConfigs, setFocus, validateConfig };
+export { extractConfigByNamespace, getBreakpoint, getFragmentFromUrl, isSupported, mergeConfigs, setFocus, validateConfig };
//# sourceMappingURL=index.mjs.map
diff --git a/packages/govuk-frontend/dist/govuk/components/header/header.bundle.js b/packages/govuk-frontend/dist/govuk/components/header/header.bundle.js
index 89d981d4d..ee3b1e1c6 100644
--- a/packages/govuk-frontend/dist/govuk/components/header/header.bundle.js
+++ b/packages/govuk-frontend/dist/govuk/components/header/header.bundle.js
@@ -4,6 +4,36 @@
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.GOVUKFrontend = {}));
})(this, (function (exports) { 'use strict';
+ function getBreakpoint(name) {
+ const property = `--govuk-frontend-breakpoint-${name}`;
+ const value = window.getComputedStyle(document.documentElement).getPropertyValue(property);
+ return {
+ property,
+ value: value || undefined
+ };
+ }
+ function isSupported($scope = document.body) {
+ if (!$scope) {
+ return false;
+ }
+ return $scope.classList.contains('govuk-frontend-supported');
+ }
+
+ /**
+ * Schema for component config
+ *
+ * @typedef {object} Schema
+ * @property {SchemaCondition[]} [anyOf] - List of schema conditions
+ */
+
+ /**
+ * Schema condition for component config
+ *
+ * @typedef {object} SchemaCondition
+ * @property {string[]} required - List of required config fields
+ * @property {string} errorMessage - Error message when required config fields not provided
+ */
+
class GOVUKFrontendError extends Error {
constructor(...args) {
super(...args);
@@ -40,28 +70,6 @@
}
}
- function isSupported($scope = document.body) {
- if (!$scope) {
- return false;
- }
- return $scope.classList.contains('govuk-frontend-supported');
- }
-
- /**
- * Schema for component config
- *
- * @typedef {object} Schema
- * @property {SchemaCondition[]} [anyOf] - List of schema conditions
- */
-
- /**
- * Schema condition for component config
- *
- * @typedef {object} SchemaCondition
- * @property {string[]} required - List of required config fields
- * @property {string} errorMessage - Error message when required config fields not provided
- */
-
class GOVUKFrontendComponent {
constructor() {
this.checkSupport();
@@ -121,16 +129,26 @@
}
this.$menu = $menu;
this.$menuButton = $menuButton;
- this.mql = window.matchMedia('(min-width: 48.0625em)');
+ this.setupResponsiveChecks();
+ this.$menuButton.addEventListener('click', () => this.handleMenuButtonClick());
+ }
+ setupResponsiveChecks() {
+ const breakpoint = getBreakpoint('desktop');
+ if (!breakpoint.value) {
+ throw new ElementError({
+ componentName: 'Header',
+ identifier: `CSS custom property (\`${breakpoint.property}\`) on pseudo-class \`:root\``
+ });
+ }
+ this.mql = window.matchMedia(`(min-width: ${breakpoint.value})`);
if ('addEventListener' in this.mql) {
- this.mql.addEventListener('change', () => this.syncState());
+ this.mql.addEventListener('change', () => this.checkMode());
} else {
- this.mql.addListener(() => this.syncState());
+ this.mql.addListener(() => this.checkMode());
}
- this.syncState();
- this.$menuButton.addEventListener('click', () => this.handleMenuButtonClick());
+ this.checkMode();
}
- syncState() {
+ checkMode() {
if (!this.mql || !this.$menu || !this.$menuButton) {
return;
}
@@ -149,7 +167,7 @@
}
handleMenuButtonClick() {
this.menuIsOpen = !this.menuIsOpen;
- this.syncState();
+ this.checkMode();
}
}
Header.moduleName = 'govuk-header';
diff --git a/packages/govuk-frontend/dist/govuk/components/header/header.bundle.mjs b/packages/govuk-frontend/dist/govuk/components/header/header.bundle.mjs
index f0060ade1..98e82f86d 100644
--- a/packages/govuk-frontend/dist/govuk/components/header/header.bundle.mjs
+++ b/packages/govuk-frontend/dist/govuk/components/header/header.bundle.mjs
@@ -1,3 +1,33 @@
+function getBreakpoint(name) {
+ const property = `--govuk-frontend-breakpoint-${name}`;
+ const value = window.getComputedStyle(document.documentElement).getPropertyValue(property);
+ return {
+ property,
+ value: value || undefined
+ };
+}
+function isSupported($scope = document.body) {
+ if (!$scope) {
+ return false;
+ }
+ return $scope.classList.contains('govuk-frontend-supported');
+}
+
+/**
+ * Schema for component config
+ *
+ * @typedef {object} Schema
+ * @property {SchemaCondition[]} [anyOf] - List of schema conditions
+ */
+
+/**
+ * Schema condition for component config
+ *
+ * @typedef {object} SchemaCondition
+ * @property {string[]} required - List of required config fields
+ * @property {string} errorMessage - Error message when required config fields not provided
+ */
+
class GOVUKFrontendError extends Error {
constructor(...args) {
super(...args);
@@ -34,28 +64,6 @@ class ElementError extends GOVUKFrontendError {
}
}
-function isSupported($scope = document.body) {
- if (!$scope) {
- return false;
- }
- return $scope.classList.contains('govuk-frontend-supported');
-}
-
-/**
- * Schema for component config
- *
- * @typedef {object} Schema
- * @property {SchemaCondition[]} [anyOf] - List of schema conditions
- */
-
-/**
- * Schema condition for component config
- *
- * @typedef {object} SchemaCondition
- * @property {string[]} required - List of required config fields
- * @property {string} errorMessage - Error message when required config fields not provided
- */
-
class GOVUKFrontendComponent {
constructor() {
this.checkSupport();
@@ -115,16 +123,26 @@ class Header extends GOVUKFrontendComponent {
}
this.$menu = $menu;
this.$menuButton = $menuButton;
- this.mql = window.matchMedia('(min-width: 48.0625em)');
+ this.setupResponsiveChecks();
+ this.$menuButton.addEventListener('click', () => this.handleMenuButtonClick());
+ }
+ setupResponsiveChecks() {
+ const breakpoint = getBreakpoint('desktop');
+ if (!breakpoint.value) {
+ throw new ElementError({
+ componentName: 'Header',
+ identifier: `CSS custom property (\`${breakpoint.property}\`) on pseudo-class \`:root\``
+ });
+ }
+ this.mql = window.matchMedia(`(min-width: ${breakpoint.value})`);
if ('addEventListener' in this.mql) {
- this.mql.addEventListener('change', () => this.syncState());
+ this.mql.addEventListener('change', () => this.checkMode());
} else {
- this.mql.addListener(() => this.syncState());
+ this.mql.addListener(() => this.checkMode());
}
- this.syncState();
- this.$menuButton.addEventListener('click', () => this.handleMenuButtonClick());
+ this.checkMode();
}
- syncState() {
+ checkMode() {
if (!this.mql || !this.$menu || !this.$menuButton) {
return;
}
@@ -143,7 +161,7 @@ class Header extends GOVUKFrontendComponent {
}
handleMenuButtonClick() {
this.menuIsOpen = !this.menuIsOpen;
- this.syncState();
+ this.checkMode();
}
}
Header.moduleName = 'govuk-header';
diff --git a/packages/govuk-frontend/dist/govuk/components/header/header.mjs b/packages/govuk-frontend/dist/govuk/components/header/header.mjs
index 329e89bda..cd6832271 100644
--- a/packages/govuk-frontend/dist/govuk/components/header/header.mjs
+++ b/packages/govuk-frontend/dist/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';
@@ -49,16 +50,26 @@ class Header extends GOVUKFrontendComponent {
}
this.$menu = $menu;
this.$menuButton = $menuButton;
- this.mql = window.matchMedia('(min-width: 48.0625em)');
+ this.setupResponsiveChecks();
+ this.$menuButton.addEventListener('click', () => this.handleMenuButtonClick());
+ }
+ setupResponsiveChecks() {
+ const breakpoint = getBreakpoint('desktop');
+ if (!breakpoint.value) {
+ throw new ElementError({
+ componentName: 'Header',
+ identifier: `CSS custom property (\`${breakpoint.property}\`) on pseudo-class \`:root\``
+ });
+ }
+ this.mql = window.matchMedia(`(min-width: ${breakpoint.value})`);
if ('addEventListener' in this.mql) {
- this.mql.addEventListener('change', () => this.syncState());
+ this.mql.addEventListener('change', () => this.checkMode());
} else {
- this.mql.addListener(() => this.syncState());
+ this.mql.addListener(() => this.checkMode());
}
- this.syncState();
- this.$menuButton.addEventListener('click', () => this.handleMenuButtonClick());
+ this.checkMode();
}
- syncState() {
+ checkMode() {
if (!this.mql || !this.$menu || !this.$menuButton) {
return;
}
@@ -77,7 +88,7 @@ class Header extends GOVUKFrontendComponent {
}
handleMenuButtonClick() {
this.menuIsOpen = !this.menuIsOpen;
- this.syncState();
+ this.checkMode();
}
}
Header.moduleName = 'govuk-header';
diff --git a/packages/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js b/packages/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js
index af2dde6c2..bc832d2f8 100644
--- a/packages/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js
+++ b/packages/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js
@@ -10,6 +10,14 @@
}
return url.split('#').pop();
}
+ function getBreakpoint(name) {
+ const property = `--govuk-frontend-breakpoint-${name}`;
+ const value = window.getComputedStyle(document.documentElement).getPropertyValue(property);
+ return {
+ property,
+ value: value || undefined
+ };
+ }
function isSupported($scope = document.body) {
if (!$scope) {
return false;
@@ -144,7 +152,14 @@
this.setupResponsiveChecks();
}
setupResponsiveChecks() {
- this.mql = window.matchMedia('(min-width: 40.0625em)');
+ const breakpoint = getBreakpoint('tablet');
+ if (!breakpoint.value) {
+ throw new ElementError({
+ componentName: 'Tabs',
+ identifier: `CSS custom property (\`${breakpoint.property}\`) on pseudo-class \`:root\``
+ });
+ }
+ this.mql = window.matchMedia(`(min-width: ${breakpoint.value})`);
if ('addEventListener' in this.mql) {
this.mql.addEventListener('change', () => this.checkMode());
} else {
diff --git a/packages/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs b/packages/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs
index 01113f302..ba301105f 100644
--- a/packages/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs
+++ b/packages/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs
@@ -4,6 +4,14 @@ function getFragmentFromUrl(url) {
}
return url.split('#').pop();
}
+function getBreakpoint(name) {
+ const property = `--govuk-frontend-breakpoint-${name}`;
+ const value = window.getComputedStyle(document.documentElement).getPropertyValue(property);
+ return {
+ property,
+ value: value || undefined
+ };
+}
function isSupported($scope = document.body) {
if (!$scope) {
return false;
@@ -138,7 +146,14 @@ class Tabs extends GOVUKFrontendComponent {
this.setupResponsiveChecks();
}
setupResponsiveChecks() {
- this.mql = window.matchMedia('(min-width: 40.0625em)');
+ const breakpoint = getBreakpoint('tablet');
+ if (!breakpoint.value) {
+ throw new ElementError({
+ componentName: 'Tabs',
+ identifier: `CSS custom property (\`${breakpoint.property}\`) on pseudo-class \`:root\``
+ });
+ }
+ this.mql = window.matchMedia(`(min-width: ${breakpoint.value})`);
if ('addEventListener' in this.mql) {
this.mql.addEventListener('change', () => this.checkMode());
} else {
diff --git a/packages/govuk-frontend/dist/govuk/components/tabs/tabs.mjs b/packages/govuk-frontend/dist/govuk/components/tabs/tabs.mjs
index 943c4238a..f1c6e6ef2 100644
--- a/packages/govuk-frontend/dist/govuk/components/tabs/tabs.mjs
+++ b/packages/govuk-frontend/dist/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';
@@ -67,7 +67,14 @@ class Tabs extends GOVUKFrontendComponent {
this.setupResponsiveChecks();
}
setupResponsiveChecks() {
- this.mql = window.matchMedia('(min-width: 40.0625em)');
+ const breakpoint = getBreakpoint('tablet');
+ if (!breakpoint.value) {
+ throw new ElementError({
+ componentName: 'Tabs',
+ identifier: `CSS custom property (\`${breakpoint.property}\`) on pseudo-class \`:root\``
+ });
+ }
+ this.mql = window.matchMedia(`(min-width: ${breakpoint.value})`);
if ('addEventListener' in this.mql) {
this.mql.addEventListener('change', () => this.checkMode());
} else {
diff --git a/packages/govuk-frontend/dist/govuk/core/_all.scss b/packages/govuk-frontend/dist/govuk/core/_all.scss
index a94480352..a9c87c554 100644
--- a/packages/govuk-frontend/dist/govuk/core/_all.scss
+++ b/packages/govuk-frontend/dist/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/dist/govuk/core/_govuk-frontend-version.scss b/packages/govuk-frontend/dist/govuk/core/_govuk-frontend-properties.scss
similarity index 43%
rename from packages/govuk-frontend/dist/govuk/core/_govuk-frontend-version.scss
rename to packages/govuk-frontend/dist/govuk/core/_govuk-frontend-properties.scss
index 5d939df71..88f50e349 100644
--- a/packages/govuk-frontend/dist/govuk/core/_govuk-frontend-version.scss
+++ b/packages/govuk-frontend/dist/govuk/core/_govuk-frontend-properties.scss
@@ -2,6 +2,11 @@
// 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)};
+ }
}
-/*# sourceMappingURL=_govuk-frontend-version.scss.map */
+/*# sourceMappingURL=_govuk-frontend-properties.scss.map */
Action run for 05b819a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the pattern for passing values from CSS to JavaScript that's enabled by our new browser support!
Listed a couple of suggestions (only the message wording is really blocking). Also thinking it's a pattern worth sharing with the team at dev catch-up as it may be useful in other occasions 😊
const breakpointProperty = '--govuk-frontend-breakpoint-desktop' | ||
const breakpointValue = getComputedStyle(document.body).getPropertyValue( | ||
breakpointProperty | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question How would you feel about encapsulating that into a getBreakpointValue(breakpointName)
. Both to wrap what's needed to access the value out of each class and to see if services maybe start picking up the pattern by digging into our private code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Absolutely fine by me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added getBreakpoint()
in bf55711 as we'll still need the CSS property name for the error
const breakpoint = getBreakpoint('tablet')
// breakpoint.property
// breakpoint.value
*/ | ||
setupResponsiveChecks() { | ||
const breakpointProperty = '--govuk-frontend-breakpoint-desktop' | ||
const breakpointValue = getComputedStyle(document.body).getPropertyValue( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: :root
corresponds to document.documentElement
. It would make the mapping between CSS and JS easier if they both reference the same element, even though the custom property value will cascade down to document.body
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah the issue said window.getComputedStyle()
and I grabbed document.body
from Slack
Shall I use document.documentElement
for <html>
instead?
You've suggested <body>
below in #4562 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've gone with document.documentElement
to represent :root
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh damn sorry for the confusion in the following comment, I did indeed mean to align CSS and JS on the :root
/document.documentElement
.
if (!breakpointValue) { | ||
throw new ElementError({ | ||
componentName: 'Header', | ||
identifier: `CSS custom property (\`${breakpointProperty}\`)` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue Thinking the message may lead to people looking to add a custom property on the root of the component's markup, while we look it up on the body 😊
identifier: `CSS custom property (\`${breakpointProperty}\`)` | |
identifier: `CSS custom property (\`${breakpointProperty}\`) on document's \`body\`` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How's this? Just pushed it up in 21a519d
ElementError: Tabs: CSS custom property (`--govuk-frontend-breakpoint-tablet`) on pseudo-class :root not found
c5e8c16
to
fde26ef
Compare
fde26ef
to
21a519d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neat! Thanks for introducing the helper and picking document.documentElement
. Approving, but I think there's a couple of backticks that are missing in the error messages around :root
(won't need another review).
if (!breakpoint.value) { | ||
throw new ElementError({ | ||
componentName: 'Header', | ||
identifier: `CSS custom property (\`${breakpoint.property}\`) on pseudo-class :root` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick I think there's a couple of backticks missing.
identifier: `CSS custom property (\`${breakpoint.property}\`) on pseudo-class :root` | |
identifier: `CSS custom property (\`${breakpoint.property}\`) on pseudo-class \`:root\`` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, left them off but will add 👍
Is it just types that we don't wrap in backticks?
Radios: Root element (`$module`) is not of type HTMLElement
21a519d
to
f758f95
Compare
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
This change ensures services that override `$govuk-breakpoints` see Tabs and Header media query breakpoints align with the overridden Sass breakpoint values
Co-Authored-By: Romaric <romaric.pascal@digital.cabinet-office.gov.uk>
f758f95
to
05b819a
Compare
Add changelog entry for #4562
This PR adds CSS custom properties for all our breakpoints alongside
--govuk-frontend-version
Then uses them in
window.matchMedia()
instead of hard coded values in JavaScriptCloses #3764
Missing breakpoints
Throws an error if the CSS custom properties are missing:
ElementError: Tabs: CSS custom property (`--govuk-frontend-breakpoint-tablet`) on pseudo-class `:root` not found