Skip to content
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

Release v5.4.1 #5128

Merged
merged 1 commit into from
Jul 12, 2024
Merged

Release v5.4.1 #5128

merged 1 commit into from
Jul 12, 2024

Conversation

romaricpascal
Copy link
Member

@romaricpascal romaricpascal commented Jul 12, 2024

To install this version with npm, run npm install govuk-frontend@5.4.1. You can also find more information about how to stay up to date in our documentation.

Recommended changes

Update Breadcrumbs to use nav and aria-label

We've made changes to the Breadcrumbs component to improve how it appears to screen readers.

We've changed the wrapping element to use the nav tag to expose it as a navigational landmark, and added an aria-label attribute to differentiate it as breadcrumb navigation.

This change was introduced in pull request #4995: Update Breadcrumb component to improve screen reader accessibility.

Fixes

We've made fixes to GOV.UK Frontend in the following pull requests:

@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-5128 July 12, 2024 10:52 Inactive
Copy link

JavaScript changes to GitHub release

diff --git a/dist/govuk-frontend-5.4.0.min.js b/dist/govuk-frontend-5.4.1.min.js
index 7c8495726..6f7f6128b 100644
--- a/dist/govuk-frontend-5.4.0.min.js
+++ b/dist/govuk-frontend-5.4.1.min.js
@@ -1,44 +1,44 @@
-const version = "5.4.0";
+const version = "5.4.1";
 
 function normaliseString(e, t) {
     const n = e ? e.trim() : "";
-    let s, i = null == t ? void 0 : t.type;
-    switch (i || (["true", "false"].includes(n) && (i = "boolean"), n.length > 0 && isFinite(Number(n)) && (i = "number")), i) {
+    let i, s = null == t ? void 0 : t.type;
+    switch (s || (["true", "false"].includes(n) && (s = "boolean"), n.length > 0 && isFinite(Number(n)) && (s = "number")), s) {
         case "boolean":
-            s = "true" === n;
+            i = "true" === n;
             break;
         case "number":
-            s = Number(n);
+            i = Number(n);
             break;
         default:
-            s = e
+            i = e
     }
-    return s
+    return i
 }
 
 function mergeConfigs(...e) {
     const t = {};
     for (const n of e)
         for (const e of Object.keys(n)) {
-            const s = t[e],
-                i = n[e];
-            isObject(s) && isObject(i) ? t[e] = mergeConfigs(s, i) : t[e] = i
+            const i = t[e],
+                s = n[e];
+            isObject(i) && isObject(s) ? t[e] = mergeConfigs(i, s) : t[e] = s
         }
     return t
 }
 
 function extractConfigByNamespace(e, t, n) {
-    const s = e.schema.properties[n];
-    if ("object" !== (null == s ? void 0 : s.type)) return;
-    const i = {
+    const i = e.schema.properties[n];
+    if ("object" !== (null == i ? void 0 : i.type)) return;
+    const s = {
         [n]: {}
     };
     for (const [o, r] of Object.entries(t)) {
-        let e = i;
+        let e = s;
         const t = o.split(".");
-        for (const [s, i] of t.entries()) "object" == typeof e && (s < t.length - 1 ? (isObject(e[i]) || (e[i] = {}), e = e[i]) : o !== n && (e[i] = normaliseString(r)))
+        for (const [i, s] of t.entries()) "object" == typeof e && (i < t.length - 1 ? (isObject(e[s]) || (e[s] = {}), e = e[s]) : o !== n && (e[s] = normaliseString(r)))
     }
-    return i[n]
+    return s[n]
 }
 
 function getFragmentFromUrl(e) {
@@ -55,13 +55,13 @@ function getBreakpoint(e) {
 
 function setFocus(e, t = {}) {
     var n;
-    const s = e.getAttribute("tabindex");
+    const i = e.getAttribute("tabindex");
 
     function onBlur() {
         var n;
-        null == (n = t.onBlur) || n.call(e), s || e.removeAttribute("tabindex")
+        null == (n = t.onBlur) || n.call(e), i || e.removeAttribute("tabindex")
     }
-    s || e.setAttribute("tabindex", "-1"), e.addEventListener("focus", (function() {
+    i || e.setAttribute("tabindex", "-1"), e.addEventListener("focus", (function() {
         e.addEventListener("blur", onBlur, {
             once: !0
         })
@@ -82,7 +82,7 @@ function isObject(e) {
 
 function normaliseDataset(e, t) {
     const n = {};
-    for (const [s, i] of Object.entries(e.schema.properties)) s in t && (n[s] = normaliseString(t[s], i)), "object" === (null == i ? void 0 : i.type) && (n[s] = extractConfigByNamespace(e, t, s));
+    for (const [i, s] of Object.entries(e.schema.properties)) i in t && (n[i] = normaliseString(t[i], s)), "object" === (null == s ? void 0 : s.type) && (n[i] = extractConfigByNamespace(e, t, i));
     return n
 }
 class GOVUKFrontendError extends Error {
@@ -107,11 +107,11 @@ class ElementError extends GOVUKFrontendError {
         if ("object" == typeof e) {
             const {
                 componentName: n,
-                identifier: s,
-                element: i,
+                identifier: i,
+                element: s,
                 expectedType: o
             } = e;
-            t = `${n}: ${s}`, t += i ? ` is not of type ${null!=o?o:"HTMLElement"}` : " not found"
+            t = `${n}: ${i}`, t += s ? ` is not of type ${null!=o?o:"HTMLElement"}` : " not found"
         }
         super(t), this.name = "ElementError"
     }
@@ -133,8 +133,8 @@ class I18n {
         if (!e) throw new Error("i18n: lookup key missing");
         let n = this.translations[e];
         if ("number" == typeof(null == t ? void 0 : t.count) && "object" == typeof n) {
-            const s = n[this.getPluralSuffix(e, t.count)];
-            s && (n = s)
+            const i = n[this.getPluralSuffix(e, t.count)];
+            i && (n = i)
         }
         if ("string" == typeof n) {
             if (n.match(/%{(.\S+)}/)) {
@@ -147,9 +147,9 @@ class I18n {
     }
     replacePlaceholders(e, t) {
         const n = Intl.NumberFormat.supportedLocalesOf(this.locale).length ? new Intl.NumberFormat(this.locale) : void 0;
-        return e.replace(/%{(.\S+)}/g, (function(e, s) {
-            if (Object.prototype.hasOwnProperty.call(t, s)) {
-                const e = t[s];
+        return e.replace(/%{(.\S+)}/g, (function(e, i) {
+            if (Object.prototype.hasOwnProperty.call(t, i)) {
+                const e = t[i];
                 return !1 === e || "number" != typeof e && "string" != typeof e ? "" : "number" == typeof e ? n ? n.format(e) : `${e}` : e
             }
             throw new Error(`i18n: no data found to replace ${e} placeholder in string`)
@@ -161,10 +161,10 @@ class I18n {
     getPluralSuffix(e, t) {
         if (t = Number(t), !isFinite(t)) return "other";
         const n = this.translations[e],
-            s = this.hasIntlPluralRulesSupport() ? new Intl.PluralRules(this.locale).select(t) : this.selectPluralFormUsingFallbackRules(t);
+            i = this.hasIntlPluralRulesSupport() ? new Intl.PluralRules(this.locale).select(t) : this.selectPluralFormUsingFallbackRules(t);
         if ("object" == typeof n) {
-            if (s in n) return s;
-            if ("other" in n) return console.warn(`i18n: Missing plural form ".${s}" for "${this.locale}" locale. Falling back to ".other".`), "other"
+            if (i in n) return i;
+            if ("other" in n) return console.warn(`i18n: Missing plural form ".${i}" for "${this.locale}" locale. Falling back to ".other".`), "other"
         }
         throw new Error(`i18n: Plural form ".other" is required for "${this.locale}" locale`)
     }
@@ -207,21 +207,19 @@ I18n.pluralRulesMap = {
     welsh: e => 0 === e ? "zero" : 1 === e ? "one" : 2 === e ? "two" : 3 === e ? "few" : 6 === e ? "many" : "other"
 };
 class Accordion extends GOVUKFrontendComponent {
-    constructor(t, n = {}) {
-        if (super(), this.$module = void 0, this.config = void 0, this.i18n = void 0, this.controlsClass = "govuk-accordion__controls", this.showAllClass = "govuk-accordion__show-all", this.showAllTextClass = "govuk-accordion__show-all-text", this.sectionClass = "govuk-accordion__section", this.sectionExpandedClass = "govuk-accordion__section--expanded", this.sectionButtonClass = "govuk-accordion__section-button", this.sectionHeaderClass = "govuk-accordion__section-header", this.sectionHeadingClass = "govuk-accordion__section-heading", this.sectionHeadingDividerClass = "govuk-accordion__section-heading-divider", this.sectionHeadingTextClass = "govuk-accordion__section-heading-text", this.sectionHeadingTextFocusClass = "govuk-accordion__section-heading-text-focus", this.sectionShowHideToggleClass = "govuk-accordion__section-toggle", this.sectionShowHideToggleFocusClass = "govuk-accordion__section-toggle-focus", this.sectionShowHideTextClass = "govuk-accordion__section-toggle-text", this.upChevronIconClass = "govuk-accordion-nav__chevron", this.downChevronIconClass = "govuk-accordion-nav__chevron--down", this.sectionSummaryClass = "govuk-accordion__section-summary", this.sectionSummaryFocusClass = "govuk-accordion__section-summary-focus", this.sectionContentClass = "govuk-accordion__section-content", this.$sections = void 0, this.browserSupportsSessionStorage = !1, this.$showAllButton = null, this.$showAllIcon = null, this.$showAllText = null, !(t instanceof HTMLElement)) throw new ElementError({
+    constructor(e, t = {}) {
+        if (super(), this.$module = void 0, this.config = void 0, this.i18n = void 0, this.controlsClass = "govuk-accordion__controls", this.showAllClass = "govuk-accordion__show-all", this.showAllTextClass = "govuk-accordion__show-all-text", this.sectionClass = "govuk-accordion__section", this.sectionExpandedClass = "govuk-accordion__section--expanded", this.sectionButtonClass = "govuk-accordion__section-button", this.sectionHeaderClass = "govuk-accordion__section-header", this.sectionHeadingClass = "govuk-accordion__section-heading", this.sectionHeadingDividerClass = "govuk-accordion__section-heading-divider", this.sectionHeadingTextClass = "govuk-accordion__section-heading-text", this.sectionHeadingTextFocusClass = "govuk-accordion__section-heading-text-focus", this.sectionShowHideToggleClass = "govuk-accordion__section-toggle", this.sectionShowHideToggleFocusClass = "govuk-accordion__section-toggle-focus", this.sectionShowHideTextClass = "govuk-accordion__section-toggle-text", this.upChevronIconClass = "govuk-accordion-nav__chevron", this.downChevronIconClass = "govuk-accordion-nav__chevron--down", this.sectionSummaryClass = "govuk-accordion__section-summary", this.sectionSummaryFocusClass = "govuk-accordion__section-summary-focus", this.sectionContentClass = "govuk-accordion__section-content", this.$sections = void 0, this.$showAllButton = null, this.$showAllIcon = null, this.$showAllText = null, !(e instanceof HTMLElement)) throw new ElementError({
             componentName: "Accordion",
-            element: t,
+            element: e,
             identifier: "Root element (`$module`)"
         });
-        this.$module = t, this.config = mergeConfigs(Accordion.defaults, n, normaliseDataset(Accordion, t.dataset)), this.i18n = new I18n(this.config.i18n);
-        const s = this.$module.querySelectorAll(`.${this.sectionClass}`);
-        if (!s.length) throw new ElementError({
+        this.$module = e, this.config = mergeConfigs(Accordion.defaults, t, normaliseDataset(Accordion, e.dataset)), this.i18n = new I18n(this.config.i18n);
+        const n = this.$module.querySelectorAll(`.${this.sectionClass}`);
+        if (!n.length) throw new ElementError({
             componentName: "Accordion",
             identifier: `Sections (\`<div class="${this.sectionClass}">\`)`
         });
-        this.$sections = s, this.browserSupportsSessionStorage = e.checkForSessionStorage(), this.initControls(), this.initSectionHeaders();
-        const i = this.checkIfAllSectionsOpen();
-        this.updateShowAllButton(i)
+        this.$sections = n, this.initControls(), this.initSectionHeaders(), this.updateShowAllButton(this.areAllSectionsOpen())
     }
     initControls() {
         this.$showAllButton = document.createElement("button"), this.$showAllButton.setAttribute("type", "button"), this.$showAllButton.setAttribute("class", this.showAllClass), this.$showAllButton.setAttribute("aria-expanded", "false"), this.$showAllIcon = document.createElement("span"), this.$showAllIcon.classList.add(this.upChevronIconClass), this.$showAllButton.appendChild(this.$showAllIcon);
@@ -240,9 +238,9 @@ class Accordion extends GOVUKFrontendComponent {
     }
     constructHeaderMarkup(e, t) {
         const n = e.querySelector(`.${this.sectionButtonClass}`),
-            s = e.querySelector(`.${this.sectionHeadingClass}`),
-            i = e.querySelector(`.${this.sectionSummaryClass}`);
-        if (!s) throw new ElementError({
+            i = e.querySelector(`.${this.sectionHeadingClass}`),
+            s = e.querySelector(`.${this.sectionSummaryClass}`);
+        if (!i) throw new ElementError({
             componentName: "Accordion",
             identifier: `Section heading (\`.${this.sectionHeadingClass}\`)`
         });
@@ -252,25 +250,25 @@ class Accordion extends GOVUKFrontendComponent {
         });
         const o = document.createElement("button");
         o.setAttribute("type", "button"), o.setAttribute("aria-controls", `${this.$module.id}-content-${t+1}`);
-        for (const d of Array.from(n.attributes)) "id" !== d.nodeName && o.setAttribute(d.nodeName, `${d.nodeValue}`);
+        for (const d of Array.from(n.attributes)) "id" !== d.name && o.setAttribute(d.name, d.value);
         const r = document.createElement("span");
         r.classList.add(this.sectionHeadingTextClass), r.id = n.id;
         const a = document.createElement("span");
-        a.classList.add(this.sectionHeadingTextFocusClass), r.appendChild(a), a.innerHTML = n.innerHTML;
+        a.classList.add(this.sectionHeadingTextFocusClass), r.appendChild(a), Array.from(n.childNodes).forEach((e => a.appendChild(e)));
         const l = document.createElement("span");
         l.classList.add(this.sectionShowHideToggleClass), l.setAttribute("data-nosnippet", "");
         const c = document.createElement("span");
         c.classList.add(this.sectionShowHideToggleFocusClass), l.appendChild(c);
         const h = document.createElement("span"),
             u = document.createElement("span");
-        if (u.classList.add(this.upChevronIconClass), c.appendChild(u), h.classList.add(this.sectionShowHideTextClass), c.appendChild(h), o.appendChild(r), o.appendChild(this.getButtonPunctuationEl()), null != i && i.parentNode) {
+        if (u.classList.add(this.upChevronIconClass), c.appendChild(u), h.classList.add(this.sectionShowHideTextClass), c.appendChild(h), o.appendChild(r), o.appendChild(this.getButtonPunctuationEl()), s) {
             const e = document.createElement("span"),
                 t = document.createElement("span");
             t.classList.add(this.sectionSummaryFocusClass), e.appendChild(t);
-            for (const n of Array.from(i.attributes)) e.setAttribute(n.nodeName, `${n.nodeValue}`);
-            t.innerHTML = i.innerHTML, i.parentNode.replaceChild(e, i), o.appendChild(e), o.appendChild(this.getButtonPunctuationEl())
+            for (const n of Array.from(s.attributes)) e.setAttribute(n.name, n.value);
+            Array.from(s.childNodes).forEach((e => t.appendChild(e))), s.remove(), o.appendChild(e), o.appendChild(this.getButtonPunctuationEl())
         }
-        o.appendChild(l), s.removeChild(n), s.appendChild(o)
+        o.appendChild(l), i.removeChild(n), i.appendChild(o)
     }
     onBeforeMatch(e) {
         const t = e.target;
@@ -279,69 +277,66 @@ class Accordion extends GOVUKFrontendComponent {
         n && this.setExpanded(!0, n)
     }
     onSectionToggle(e) {
-        const t = this.isExpanded(e);
-        this.setExpanded(!t, e), this.storeState(e)
+        const t = !this.isExpanded(e);
+        this.setExpanded(t, e), this.storeState(e, t)
     }
     onShowOrHideAllToggle() {
-        const e = !this.checkIfAllSectionsOpen();
+        const e = !this.areAllSectionsOpen();
         this.$sections.forEach((t => {
-            this.setExpanded(e, t), this.storeState(t)
+            this.setExpanded(e, t), this.storeState(t, e)
         })), this.updateShowAllButton(e)
     }
     setExpanded(e, t) {
         const n = t.querySelector(`.${this.upChevronIconClass}`),
-            s = t.querySelector(`.${this.sectionShowHideTextClass}`),
-            i = t.querySelector(`.${this.sectionButtonClass}`),
+            i = t.querySelector(`.${this.sectionShowHideTextClass}`),
+            s = t.querySelector(`.${this.sectionButtonClass}`),
             o = t.querySelector(`.${this.sectionContentClass}`);
         if (!o) throw new ElementError({
             componentName: "Accordion",
             identifier: `Section content (\`<div class="${this.sectionContentClass}">\`)`
         });
-        if (!n || !s || !i) return;
+        if (!n || !i || !s) return;
         const r = e ? this.i18n.t("hideSection") : this.i18n.t("showSection");
-        s.textContent = r, i.setAttribute("aria-expanded", `${e}`);
+        i.textContent = r, s.setAttribute("aria-expanded", `${e}`);
         const a = [],
             l = t.querySelector(`.${this.sectionHeadingTextClass}`);
         l && a.push(`${l.textContent}`.trim());
         const c = t.querySelector(`.${this.sectionSummaryClass}`);
         c && a.push(`${c.textContent}`.trim());
         const h = e ? this.i18n.t("hideSectionAriaLabel") : this.i18n.t("showSectionAriaLabel");
-        a.push(h), i.setAttribute("aria-label", a.join(" , ")), e ? (o.removeAttribute("hidden"), t.classList.add(this.sectionExpandedClass), n.classList.remove(this.downChevronIconClass)) : (o.setAttribute("hidden", "until-found"), t.classList.remove(this.sectionExpandedClass), n.classList.add(this.downChevronIconClass));
-        const u = this.checkIfAllSectionsOpen();
-        this.updateShowAllButton(u)
+        a.push(h), s.setAttribute("aria-label", a.join(" , ")), e ? (o.removeAttribute("hidden"), t.classList.add(this.sectionExpandedClass), n.classList.remove(this.downChevronIconClass)) : (o.setAttribute("hidden", "until-found"), t.classList.remove(this.sectionExpandedClass), n.classList.add(this.downChevronIconClass)), this.updateShowAllButton(this.areAllSectionsOpen())
     }
     isExpanded(e) {
         return e.classList.contains(this.sectionExpandedClass)
     }
-    checkIfAllSectionsOpen() {
-        return this.$sections.length === this.$module.querySelectorAll(`.${this.sectionExpandedClass}`).length
+    areAllSectionsOpen() {
+        return Array.from(this.$sections).every((e => this.isExpanded(e)))
     }
     updateShowAllButton(e) {
         this.$showAllButton && this.$showAllText && this.$showAllIcon && (this.$showAllButton.setAttribute("aria-expanded", e.toString()), this.$showAllText.textContent = e ? this.i18n.t("hideAllSections") : this.i18n.t("showAllSections"), this.$showAllIcon.classList.toggle(this.downChevronIconClass, !e))
     }
-    storeState(e) {
-        if (this.browserSupportsSessionStorage && this.config.rememberExpanded) {
-            const t = e.querySelector(`.${this.sectionButtonClass}`);
-            if (t) {
-                const e = t.getAttribute("aria-controls"),
-                    n = t.getAttribute("aria-expanded");
-                e && n && window.sessionStorage.setItem(e, n)
-            }
-        }
+    getIdentifier(e) {
+        const t = e.querySelector(`.${this.sectionButtonClass}`);
+        return null == t ? void 0 : t.getAttribute("aria-controls")
+    }
+    storeState(e, t) {
+        if (!this.config.rememberExpanded) return;
+        const n = this.getIdentifier(e);
+        if (n) try {
+            window.sessionStorage.setItem(n, t.toString())
+        } catch (i) {}
     }
     setInitialState(e) {
-        if (this.browserSupportsSessionStorage && this.config.rememberExpanded) {
-            const t = e.querySelector(`.${this.sectionButtonClass}`);
-            if (t) {
-                const n = t.getAttribute("aria-controls"),
-                    s = n ? window.sessionStorage.getItem(n) : null;
-                null !== s && this.setExpanded("true" === s, e)
-            }
-        }
+        if (!this.config.rememberExpanded) return;
+        const t = this.getIdentifier(e);
+        if (t) try {
+            const n = window.sessionStorage.getItem(t);
+            null !== n && this.setExpanded("true" === n, e)
+        } catch (n) {}
     }
     getButtonPunctuationEl() {
         const e = document.createElement("span");
-        return e.classList.add("govuk-visually-hidden", this.sectionHeadingDividerClass), e.innerHTML = ", ", e
+        return e.classList.add("govuk-visually-hidden", this.sectionHeadingDividerClass), e.textContent = ", ", e
     }
 }
 Accordion.moduleName = "govuk-accordion", Accordion.defaults = Object.freeze({
@@ -364,17 +359,6 @@ Accordion.moduleName = "govuk-accordion", Accordion.defaults = Object.freeze({
         }
     }
 });
-const e = {
-    checkForSessionStorage: function() {
-        const e = "this is the test string";
-        let t;
-        try {
-            return window.sessionStorage.setItem(e, e), t = window.sessionStorage.getItem(e) === e.toString(), window.sessionStorage.removeItem(e), t
-        } catch (n) {
-            return !1
-        }
-    }
-};
 class Button extends GOVUKFrontendComponent {
     constructor(e, t = {}) {
         if (super(), this.$module = void 0, this.config = void 0, this.debounceFormSubmitTimer = null, !(e instanceof HTMLElement)) throw new ElementError({
@@ -410,16 +394,16 @@ Button.moduleName = "govuk-button", Button.defaults = Object.freeze({
 });
 class CharacterCount extends GOVUKFrontendComponent {
     constructor(e, t = {}) {
-        var n, s;
+        var n, i;
         if (super(), this.$module = void 0, this.$textarea = void 0, this.$visibleCountMessage = void 0, this.$screenReaderCountMessage = void 0, this.lastInputTimestamp = null, this.lastInputValue = "", this.valueChecker = null, this.config = void 0, this.i18n = void 0, this.maxLength = void 0, !(e instanceof HTMLElement)) throw new ElementError({
             componentName: "Character count",
             element: e,
             identifier: "Root element (`$module`)"
         });
-        const i = e.querySelector(".govuk-js-character-count");
-        if (!(i instanceof HTMLTextAreaElement || i instanceof HTMLInputElement)) throw new ElementError({
+        const s = e.querySelector(".govuk-js-character-count");
+        if (!(s instanceof HTMLTextAreaElement || s instanceof HTMLInputElement)) throw new ElementError({
             componentName: "Character count",
-            element: i,
+            element: s,
             expectedType: "HTMLTextareaElement or HTMLInputElement",
             identifier: "Form field (`.govuk-js-character-count`)"
         });
@@ -431,15 +415,15 @@ class CharacterCount extends GOVUKFrontendComponent {
         }), this.config = mergeConfigs(CharacterCount.defaults, t, r, o);
         const a = function(e, t) {
             const n = [];
-            for (const [s, i] of Object.entries(e)) {
+            for (const [i, s] of Object.entries(e)) {
                 const e = [];
-                if (Array.isArray(i)) {
+                if (Array.isArray(s)) {
                     for (const {
                             required: n,
-                            errorMessage: s
+                            errorMessage: i
                         }
-                        of i) n.every((e => !!t[e])) || e.push(s);
-                    "anyOf" !== s || i.length - e.length >= 1 || n.push(...e)
+                        of s) n.every((e => !!t[e])) || e.push(i);
+                    "anyOf" !== i || s.length - e.length >= 1 || n.push(...e)
                 }
             }
             return n
@@ -447,7 +431,7 @@ class CharacterCount extends GOVUKFrontendComponent {
         if (a[0]) throw new ConfigError(`Character count: ${a[0]}`);
         this.i18n = new I18n(this.config.i18n, {
             locale: closestAttributeValue(e, "lang")
-        }), this.maxLength = null != (n = null != (s = this.config.maxwords) ? s : this.config.maxlength) ? n : 1 / 0, this.$module = e, this.$textarea = i;
+        }), this.maxLength = null != (n = null != (i = this.config.maxwords) ? i : this.config.maxlength) ? n : 1 / 0, this.$module = e, this.$textarea = s;
         const l = `${this.$textarea.id}-info`,
             c = document.getElementById(l);
         if (!c) throw new ElementError({
@@ -635,8 +619,8 @@ class ErrorSummary extends GOVUKFrontendComponent {
         if (!t) return !1;
         const n = document.getElementById(t);
         if (!n) return !1;
-        const s = this.getAssociatedLegendOrLabel(n);
-        return !!s && (s.scrollIntoView(), n.focus({
+        const i = this.getAssociatedLegendOrLabel(n);
+        return !!i && (i.scrollIntoView(), n.focus({
             preventScroll: !0
         }), !0)
     }
@@ -648,10 +632,10 @@ class ErrorSummary extends GOVUKFrontendComponent {
             if (t.length) {
                 const n = t[0];
                 if (e instanceof HTMLInputElement && ("checkbox" === e.type || "radio" === e.type)) return n;
-                const s = n.getBoundingClientRect().top,
-                    i = e.getBoundingClientRect();
-                if (i.height && window.innerHeight) {
-                    if (i.top + i.height - s < window.innerHeight / 2) return n
+                const i = n.getBoundingClientRect().top,
+                    s = e.getBoundingClientRect();
+                if (s.height && window.innerHeight) {
+                    if (s.top + s.height - i < window.innerHeight / 2) return n
                 }
             }
         }
@@ -682,8 +666,8 @@ class ExitThisPage extends GOVUKFrontendComponent {
             identifier: "Button (`.govuk-exit-this-page__button`)"
         });
         this.config = mergeConfigs(ExitThisPage.defaults, t, normaliseDataset(ExitThisPage, e.dataset)), this.i18n = new I18n(this.config.i18n), this.$module = e, this.$button = n;
-        const s = document.querySelector(".govuk-js-exit-this-page-skiplink");
-        s instanceof HTMLAnchorElement && (this.$skiplinkButton = s), this.buildIndicator(), this.initUpdateSpan(), this.initButtonClickHandler(), "govukFrontendExitThisPageKeypress" in document.body.dataset || (document.addEventListener("keyup", this.handleKeypress.bind(this), !0), document.body.dataset.govukFrontendExitThisPageKeypress = "true"), window.addEventListener("pageshow", this.resetPage.bind(this))
+        const i = document.querySelector(".govuk-js-exit-this-page-skiplink");
+        i instanceof HTMLAnchorElement && (this.$skiplinkButton = i), this.buildIndicator(), this.initUpdateSpan(), this.initButtonClickHandler(), "govukFrontendExitThisPageKeypress" in document.body.dataset || (document.addEventListener("keyup", this.handleKeypress.bind(this), !0), document.body.dataset.govukFrontendExitThisPageKeypress = "true"), window.addEventListener("pageshow", this.resetPage.bind(this))
     }
     initUpdateSpan() {
         this.$updateSpan = document.createElement("span"), this.$updateSpan.setAttribute("role", "status"), this.$updateSpan.className = "govuk-visually-hidden", this.$module.appendChild(this.$updateSpan)
@@ -759,13 +743,13 @@ class Header extends GOVUKFrontendComponent {
             componentName: "Header",
             identifier: 'Navigation button (`<button class="govuk-js-header-toggle">`) attribute (`aria-controls`)'
         });
-        const s = document.getElementById(n);
-        if (!s) throw new ElementError({
+        const i = document.getElementById(n);
+        if (!i) throw new ElementError({
             componentName: "Header",
-            element: s,
+            element: i,
             identifier: `Navigation (\`<ul id="${n}">\`)`
         });
-        this.$menu = s, this.$menuButton = t, this.setupResponsiveChecks(), this.$menuButton.addEventListener("click", (() => this.handleMenuButtonClick()))
+        this.$menu = i, this.$menuButton = t, this.setupResponsiveChecks(), this.$menuButton.addEventListener("click", (() => this.handleMenuButtonClick()))
     }
     setupResponsiveChecks() {
         const e = getBreakpoint("desktop");
@@ -817,19 +801,19 @@ class PasswordInput extends GOVUKFrontendComponent {
             identifier: "Form field (`.govuk-js-password-input-input`)"
         });
         if ("password" !== n.type) throw new ElementError("Password input: Form field (`.govuk-js-password-input-input`) must be of type `password`.");
-        const s = e.querySelector(".govuk-js-password-input-toggle");
-        if (!(s instanceof HTMLButtonElement)) throw new ElementError({
+        const i = e.querySelector(".govuk-js-password-input-toggle");
+        if (!(i instanceof HTMLButtonElement)) throw new ElementError({
             componentName: "Password input",
-            element: s,
+            element: i,
             expectedType: "HTMLButtonElement",
             identifier: "Button (`.govuk-js-password-input-toggle`)"
         });
-        if ("button" !== s.type) throw new ElementError("Password input: Button (`.govuk-js-password-input-toggle`) must be of type `button`.");
-        this.$module = e, this.$input = n, this.$showHideButton = s, this.config = mergeConfigs(PasswordInput.defaults, t, normaliseDataset(PasswordInput, e.dataset)), this.i18n = new I18n(this.config.i18n, {
+        if ("button" !== i.type) throw new ElementError("Password input: Button (`.govuk-js-password-input-toggle`) must be of type `button`.");
+        this.$module = e, this.$input = n, this.$showHideButton = i, this.config = mergeConfigs(PasswordInput.defaults, t, normaliseDataset(PasswordInput, e.dataset)), this.i18n = new I18n(this.config.i18n, {
             locale: closestAttributeValue(e, "lang")
         }), this.$showHideButton.removeAttribute("hidden");
-        const i = document.createElement("div");
-        i.className = "govuk-password-input__sr-status govuk-visually-hidden", i.setAttribute("aria-live", "polite"), this.$screenReaderStatusMessage = i, this.$input.insertAdjacentElement("afterend", i), this.$showHideButton.addEventListener("click", this.toggle.bind(this)), this.$input.form && this.$input.form.addEventListener("submit", (() => this.hide())), window.addEventListener("pageshow", (e => {
+        const s = document.createElement("div");
+        s.className = "govuk-password-input__sr-status govuk-visually-hidden", s.setAttribute("aria-live", "polite"), this.$screenReaderStatusMessage = s, this.$input.insertAdjacentElement("afterend", s), this.$showHideButton.addEventListener("click", this.toggle.bind(this)), this.$input.form && this.$input.form.addEventListener("submit", (() => this.hide())), window.addEventListener("pageshow", (e => {
             e.persisted && "password" !== this.$input.type && this.hide()
         })), this.hide()
     }
@@ -847,8 +831,8 @@ class PasswordInput extends GOVUKFrontendComponent {
         this.$input.setAttribute("type", e);
         const t = "password" === e,
             n = t ? "show" : "hide",
-            s = t ? "passwordHidden" : "passwordShown";
-        this.$showHideButton.innerText = this.i18n.t(`${n}Password`), this.$showHideButton.setAttribute("aria-label", this.i18n.t(`${n}PasswordAriaLabel`)), this.$screenReaderStatusMessage.innerText = this.i18n.t(`${s}Announcement`)
+            i = t ? "passwordHidden" : "passwordShown";
+        this.$showHideButton.innerText = this.i18n.t(`${n}Password`), this.$showHideButton.setAttribute("aria-label", this.i18n.t(`${n}PasswordAriaLabel`)), this.$screenReaderStatusMessage.innerText = this.i18n.t(`${i}Announcement`)
     }
 }
 PasswordInput.moduleName = "govuk-password-input", PasswordInput.defaults = Object.freeze({
@@ -906,11 +890,11 @@ class Radios extends GOVUKFrontendComponent {
         const t = e.target;
         if (!(t instanceof HTMLInputElement) || "radio" !== t.type) return;
         const n = document.querySelectorAll('input[type="radio"][aria-controls]'),
-            s = t.form,
-            i = t.name;
+            i = t.form,
+            s = t.name;
         n.forEach((e => {
-            const t = e.form === s;
-            e.name === i && t && this.syncConditionalRevealWithInputState(e)
+            const t = e.form === i;
+            e.name === s && t && this.syncConditionalRevealWithInputState(e)
         }))
     }
 }
@@ -926,16 +910,16 @@ class SkipLink extends GOVUKFrontendComponent {
         });
         this.$module = e;
         const n = this.$module.hash,
-            s = null != (t = this.$module.getAttribute("href")) ? t : "";
-        let i;
+            i = null != (t = this.$module.getAttribute("href")) ? t : "";
+        let s;
         try {
-            i = new window.URL(this.$module.href)
+            s = new window.URL(this.$module.href)
         } catch (a) {
-            throw new ElementError(`Skip link: Target link (\`href="${s}"\`) is invalid`)
+            throw new ElementError(`Skip link: Target link (\`href="${i}"\`) is invalid`)
         }
-        if (i.origin !== window.location.origin || i.pathname !== window.location.pathname) return;
+        if (s.origin !== window.location.origin || s.pathname !== window.location.pathname) return;
         const o = getFragmentFromUrl(n);
-        if (!o) throw new ElementError(`Skip link: Target link (\`href="${s}"\`) has no hash fragment`);
+        if (!o) throw new ElementError(`Skip link: Target link (\`href="${i}"\`) has no hash fragment`);
         const r = document.getElementById(o);
         if (!r) throw new ElementError({
             componentName: "Skip link",
@@ -967,16 +951,16 @@ class Tabs extends GOVUKFrontendComponent {
         });
         this.$module = e, this.$tabs = t, this.boundTabClick = this.onTabClick.bind(this), this.boundTabKeydown = this.onTabKeydown.bind(this), this.boundOnHashChange = this.onHashChange.bind(this);
         const n = this.$module.querySelector(".govuk-tabs__list"),
-            s = this.$module.querySelectorAll("li.govuk-tabs__list-item");
+            i = this.$module.querySelectorAll("li.govuk-tabs__list-item");
         if (!n) throw new ElementError({
             componentName: "Tabs",
             identifier: 'List (`<ul class="govuk-tabs__list">`)'
         });
-        if (!s.length) throw new ElementError({
+        if (!i.length) throw new ElementError({
             componentName: "Tabs",
             identifier: 'List items (`<li class="govuk-tabs__list-item">`)'
         });
-        this.$tabList = n, this.$tabListItems = s, this.setupResponsiveChecks()
+        this.$tabList = n, this.$tabListItems = i, this.setupResponsiveChecks()
     }
     setupResponsiveChecks() {
         const e = getBreakpoint("tablet");
@@ -1118,19 +1102,19 @@ function initAll(e) {
             [SkipLink],
             [Tabs]
         ],
-        s = null != (t = e.scope) ? t : document;
+        i = null != (t = e.scope) ? t : document;
     n.forEach((([e, t]) => {
-        createAll(e, t, s)
+        createAll(e, t, i)
     }))
 }
 
 function createAll(e, t, n = document) {
-    const s = n.querySelectorAll(`[data-module="${e.moduleName}"]`);
-    return Array.from(s).map((n => {
+    const i = n.querySelectorAll(`[data-module="${e.moduleName}"]`);
+    return Array.from(i).map((n => {
         try {
             return "defaults" in e && void 0 !== t ? new e(n, t) : new e(n)
-        } catch (s) {
-            return console.log(s), null
+        } catch (i) {
+            return console.log(i), null
         }
     })).filter(Boolean)
 }
@@ -1151,4 +1135,4 @@ export {
     createAll,
     initAll,
     version
-}; //# sourceMappingURL=govuk-frontend-5.4.0.min.js.map
\ No newline at end of file
+}; //# sourceMappingURL=govuk-frontend-5.4.1.min.js.map
\ No newline at end of file

Action run for 720a7b3

Copy link

Stylesheets changes to GitHub release

diff --git a/dist/govuk-frontend-5.4.0.min.css b/dist/govuk-frontend-5.4.1.min.css
index 0ef389ae2..86666b7cb 100644
--- a/dist/govuk-frontend-5.4.0.min.css
+++ b/dist/govuk-frontend-5.4.1.min.css
@@ -1,7 +1,7 @@
 @charset "UTF-8";
 
 :root {
-    --govuk-frontend-version: "5.4.0";
+    --govuk-frontend-version: "5.4.1";
     --govuk-frontend-breakpoint-mobile: 20rem;
     --govuk-frontend-breakpoint-tablet: 40.0625rem;
     --govuk-frontend-breakpoint-desktop: 48.0625rem
@@ -2597,8 +2597,8 @@ screen and (forced-colors:active) {
 
 .govuk-checkboxes__conditional {
     margin-bottom: 15px;
-    margin-left: 18px;
-    padding-left: 33px;
+    margin-left: 20px;
+    padding-left: 35px;
     border-left: 4px solid #b1b4b6
 }
 
@@ -2649,6 +2649,11 @@ screen and (forced-colors:active) {
     padding-left: 20px
 }
 
+.govuk-checkboxes--small .govuk-checkboxes__divider {
+    width: 24px;
+    margin-bottom: 5px
+}
+
 .govuk-checkboxes--small .govuk-checkboxes__item:hover .govuk-checkboxes__input:not(:disabled)+.govuk-checkboxes__label:before {
     outline: 3px dashed transparent;
     outline-offset: 1px;
@@ -3184,6 +3189,10 @@ screen and (forced-colors:active) {
     }
 }
 
+.govuk-error-summary__body>:last-child {
+    margin-bottom: 5px
+}
+
 .govuk-error-summary__list,
 .govuk-error-summary__list li:last-child {
     margin-bottom: 0
@@ -4829,12 +4838,6 @@ only screen and (min-resolution:2dppx) {
     }
 }
 
-@media screen and (forced-colors:active) {
-    .govuk-phase-banner__content__tag {
-        font-weight: 700
-    }
-}
-
 .govuk-phase-banner__text {
     display: table-cell;
     vertical-align: middle
@@ -4984,8 +4987,8 @@ screen and (forced-colors:active) {
 
 .govuk-radios__conditional {
     margin-bottom: 15px;
-    margin-left: 18px;
-    padding-left: 33px;
+    margin-left: 20px;
+    padding-left: 35px;
     border-left: 4px solid #b1b4b6
 }
 
@@ -5132,18 +5135,6 @@ screen and (forced-colors:active) {
 }
 
 .govuk-skip-link {
-    position: absolute !important;
-    width: 1px !important;
-    height: 1px !important;
-    margin: 0 !important;
-    overflow: hidden !important;
-    clip: rect(0 0 0 0) !important;
-    -webkit-clip-path: inset(50%) !important;
-    clip-path: inset(50%) !important;
-    white-space: nowrap !important;
-    -webkit-user-select: none;
-    -ms-user-select: none;
-    user-select: none;
     font-family: GDS Transport, arial, sans-serif;
     -webkit-font-smoothing: antialiased;
     -moz-osx-font-smoothing: grayscale;
@@ -5156,20 +5147,21 @@ screen and (forced-colors:active) {
     padding: 10px 15px
 }
 
-.govuk-skip-link:active,
-.govuk-skip-link:focus {
-    position: static !important;
-    width: auto !important;
-    height: auto !important;
-    margin: inherit !important;
-    overflow: visible !important;
-    clip: auto !important;
-    -webkit-clip-path: none !important;
-    clip-path: none !important;
-    white-space: inherit !important;
-    -webkit-user-select: text;
-    -ms-user-select: text;
-    user-select: text
+.govuk-skip-link:not(:active):not(:focus) {
+    position: absolute !important;
+    width: 1px !important;
+    height: 1px !important;
+    margin: 0 !important;
+    padding: 0 !important;
+    overflow: hidden !important;
+    clip: rect(0 0 0 0) !important;
+    -webkit-clip-path: inset(50%) !important;
+    clip-path: inset(50%) !important;
+    border: 0 !important;
+    white-space: nowrap !important;
+    -webkit-user-select: none;
+    -ms-user-select: none;
+    user-select: none
 }
 
 @media print {
@@ -6203,37 +6195,23 @@ screen and (-ms-high-contrast:active) {
     content: " "
 }
 
-.govuk-visually-hidden-focusable {
+.govuk-visually-hidden-focusable:not(:active):not(:focus) {
     position: absolute !important;
     width: 1px !important;
     height: 1px !important;
     margin: 0 !important;
+    padding: 0 !important;
     overflow: hidden !important;
     clip: rect(0 0 0 0) !important;
     -webkit-clip-path: inset(50%) !important;
     clip-path: inset(50%) !important;
+    border: 0 !important;
     white-space: nowrap !important;
     -webkit-user-select: none;
     -ms-user-select: none;
     user-select: none
 }
 
-.govuk-visually-hidden-focusable:active,
-.govuk-visually-hidden-focusable:focus {
-    position: static !important;
-    width: auto !important;
-    height: auto !important;
-    margin: inherit !important;
-    overflow: visible !important;
-    clip: auto !important;
-    -webkit-clip-path: none !important;
-    clip-path: none !important;
-    white-space: inherit !important;
-    -webkit-user-select: text;
-    -ms-user-select: text;
-    user-select: text
-}
-
 .govuk-\!-display-inline {
     display: inline !important
 }
@@ -7643,4 +7621,4 @@ screen and (-ms-high-contrast:active) {
     }
 }
 
-/*# sourceMappingURL=govuk-frontend-5.4.0.min.css.map */
\ No newline at end of file
+/*# sourceMappingURL=govuk-frontend-5.4.1.min.css.map */
\ No newline at end of file

Action run for 720a7b3

Copy link

Other changes to GitHub release

diff --git a/dist/VERSION.txt b/dist/VERSION.txt
index 8a30e8f94..ade65226e 100644
--- a/dist/VERSION.txt
+++ b/dist/VERSION.txt
@@ -1 +1 @@
-5.4.0
+5.4.1
diff --git a/dist/assets/fonts/bold-affa96571d-v2.woff b/dist/assets/fonts/bold-affa96571d-v2.woff
index 48fbcf59c..1463e7a92 100755
Binary files a/dist/assets/fonts/bold-affa96571d-v2.woff and b/dist/assets/fonts/bold-affa96571d-v2.woff differ
diff --git a/dist/assets/fonts/bold-b542beb274-v2.woff2 b/dist/assets/fonts/bold-b542beb274-v2.woff2
index 81fd14985..5f87f101a 100755
Binary files a/dist/assets/fonts/bold-b542beb274-v2.woff2 and b/dist/assets/fonts/bold-b542beb274-v2.woff2 differ
diff --git a/dist/assets/fonts/light-94a07e06a1-v2.woff2 b/dist/assets/fonts/light-94a07e06a1-v2.woff2
index 1eb101571..29b49b7b6 100755
Binary files a/dist/assets/fonts/light-94a07e06a1-v2.woff2 and b/dist/assets/fonts/light-94a07e06a1-v2.woff2 differ
diff --git a/dist/assets/fonts/light-f591b13f7d-v2.woff b/dist/assets/fonts/light-f591b13f7d-v2.woff
index 3b26d5ffd..2967fad32 100755
Binary files a/dist/assets/fonts/light-f591b13f7d-v2.woff and b/dist/assets/fonts/light-f591b13f7d-v2.woff differ
diff --git a/dist/assets/images/favicon.ico b/dist/assets/images/favicon.ico
index 20129a0bb..aed44123c 100644
Binary files a/dist/assets/images/favicon.ico and b/dist/assets/images/favicon.ico differ
diff --git a/dist/assets/images/govuk-crest-2x.png b/dist/assets/images/govuk-crest-2x.png
index 78e751cc2..75571f115 100644
Binary files a/dist/assets/images/govuk-crest-2x.png and b/dist/assets/images/govuk-crest-2x.png differ
diff --git a/dist/assets/images/govuk-crest.png b/dist/assets/images/govuk-crest.png
index bed4efe41..208c84eba 100644
Binary files a/dist/assets/images/govuk-crest.png and b/dist/assets/images/govuk-crest.png differ
diff --git a/dist/assets/images/govuk-icon-180.png b/dist/assets/images/govuk-icon-180.png
index 7c33beba8..68348c68f 100644
Binary files a/dist/assets/images/govuk-icon-180.png and b/dist/assets/images/govuk-icon-180.png differ
diff --git a/dist/assets/images/govuk-icon-192.png b/dist/assets/images/govuk-icon-192.png
index 35e51d7a7..f86ff1bfe 100644
Binary files a/dist/assets/images/govuk-icon-192.png and b/dist/assets/images/govuk-icon-192.png differ
diff --git a/dist/assets/images/govuk-icon-512.png b/dist/assets/images/govuk-icon-512.png
index f5eb6f461..2d78aa060 100644
Binary files a/dist/assets/images/govuk-icon-512.png and b/dist/assets/images/govuk-icon-512.png differ
diff --git a/dist/assets/images/govuk-opengraph-image.png b/dist/assets/images/govuk-opengraph-image.png
index 4d0e312ff..12e5349fa 100644
Binary files a/dist/assets/images/govuk-opengraph-image.png and b/dist/assets/images/govuk-opengraph-image.png differ

Action run for 720a7b3

Copy link

📋 Stats

File sizes

File Size
dist/govuk-frontend-development.min.css 112.87 KiB
dist/govuk-frontend-development.min.js 41.88 KiB
packages/govuk-frontend/dist/govuk/all.bundle.js 87.42 KiB
packages/govuk-frontend/dist/govuk/all.bundle.mjs 82.11 KiB
packages/govuk-frontend/dist/govuk/all.mjs 981 B
packages/govuk-frontend/dist/govuk/govuk-frontend-component.mjs 359 B
packages/govuk-frontend/dist/govuk/govuk-frontend.min.css 112.85 KiB
packages/govuk-frontend/dist/govuk/govuk-frontend.min.js 41.87 KiB
packages/govuk-frontend/dist/govuk/i18n.mjs 5.55 KiB
packages/govuk-frontend/dist/govuk/init.mjs 4.86 KiB

Modules

File Size (bundled) Size (minified)
all.mjs 79.24 KiB 39.84 KiB
accordion.mjs 23.5 KiB 12.39 KiB
button.mjs 5.98 KiB 2.69 KiB
character-count.mjs 22.4 KiB 9.92 KiB
checkboxes.mjs 5.83 KiB 2.83 KiB
error-summary.mjs 7.89 KiB 3.46 KiB
exit-this-page.mjs 17.1 KiB 9.26 KiB
header.mjs 4.46 KiB 2.6 KiB
notification-banner.mjs 6.26 KiB 2.62 KiB
password-input.mjs 15.15 KiB 7.25 KiB
radios.mjs 4.83 KiB 2.38 KiB
skip-link.mjs 4.39 KiB 2.18 KiB
tabs.mjs 10.13 KiB 6.11 KiB

View stats and visualisations on the review app


Action run for 720a7b3

@romaricpascal
Copy link
Member Author

Fonts diff likely linked to this update of Gulp. Percy shows no diff so all good! ⛵

@romaricpascal romaricpascal merged commit 2852b38 into main Jul 12, 2024
54 checks passed
@romaricpascal romaricpascal deleted the release-5.4.1 branch July 12, 2024 11:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants