Closed romaricpascal closed 4 months ago
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 720a7b3e80d00899491d35258e5d2e47c4b09b99
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 720a7b3e80d00899491d35258e5d2e47c4b09b99
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 720a7b3e80d00899491d35258e5d2e47c4b09b99
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 |
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 720a7b3e80d00899491d35258e5d2e47c4b09b99
Fonts diff likely linked to this update of Gulp. Percy shows no diff so all good! ⛵
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
andaria-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 anaria-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: