-
Notifications
You must be signed in to change notification settings - Fork 336
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
File input new dropzone design #5642
base: spike-enhanced-file-upload
Are you sure you want to change the base?
File input new dropzone design #5642
Conversation
📋 StatsFile sizes
Modules
View stats and visualisations on the review app Action run for 00cb7d9 |
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 374ce22cc..6b859649b 100644
--- a/packages/govuk-frontend/dist/govuk/govuk-frontend.min.js
+++ b/packages/govuk-frontend/dist/govuk/govuk-frontend.min.js
@@ -754,15 +754,21 @@ class FileUpload extends ConfigurableComponent {
if (!this.$root.id.length) throw new ElementError(formatErrorMessage(FileUpload, "Form field must specify an `id`."));
this.id = this.$root.id, this.i18n = new I18n(this.config.i18n, {
locale: closestAttributeValue(this.$root, "lang")
- }), this.$label = this.findLabel(), this.$root.id = `${this.id}-input`;
+ }), this.$label = this.findLabel(), this.$root.id = `${this.id}-input`, this.$label.setAttribute("for", `${this.id}-input`);
const n = document.createElement("div");
n.className = "govuk-file-upload-wrapper";
- const i = document.createElement("button");
- i.classList.add("govuk-file-upload__button"), i.type = "button", i.id = this.id;
- const s = document.createElement("span");
- s.className = "govuk-button govuk-button--secondary govuk-file-upload__pseudo-button", s.innerText = this.i18n.t("selectFilesButton"), s.setAttribute("aria-hidden", "true"), i.appendChild(s), i.addEventListener("click", this.onClick.bind(this));
+ const i = document.createElement("span");
+ i.className = "govuk-visually-hidden", i.innerText = ", ";
+ const s = document.createElement("button");
+ s.classList.add("govuk-file-upload__button"), s.type = "button", s.id = this.id;
const o = document.createElement("span");
- o.className = "govuk-body govuk-file-upload__status", o.innerText = this.i18n.t("filesSelectedDefault"), o.setAttribute("aria-hidden", "true"), i.appendChild(o), i.setAttribute("aria-label", `${this.$label.innerText}, ${this.i18n.t("selectFilesButton")}, ${this.i18n.t("filesSelectedDefault")}`), n.insertAdjacentElement("beforeend", i), this.$root.insertAdjacentElement("afterend", n), this.$root.setAttribute("tabindex", "-1"), this.$root.setAttribute("aria-hidden", "true"), n.insertAdjacentElement("afterbegin", this.$root), this.$wrapper = n, this.$button = i, this.$status = o, this.$root.addEventListener("change", this.onChange.bind(this)), this.updateDisabledState(), this.observeDisabledState(), this.$root.addEventListener("change", this.onChange.bind(this)), this.$announcements = document.createElement("span"), this.$announcements.classList.add("govuk-file-upload-announcements"), this.$announcements.classList.add("govuk-visually-hidden"), this.$announcements.setAttribute("aria-live", "assertive"), this.$wrapper.insertAdjacentElement("afterend", this.$announcements), this.$wrapper.addEventListener("drop", this.hideDropZone.bind(this)), document.addEventListener("dragenter", this.updateDropzoneVisibility.bind(this)), document.addEventListener("dragenter", (() => {
+ o.className = "govuk-body govuk-file-upload__status", o.innerText = this.i18n.t("filesSelectedDefault"), o.setAttribute("aria-hidden", "true"), this.$root.files.length || o.classList.add("govuk-tag--light-blue"), s.appendChild(o), s.appendChild(i.cloneNode(!0));
+ const r = document.createElement("span");
+ r.className = "govuk-file-upload__pseudo-button-container";
+ const a = document.createElement("span");
+ a.className = "govuk-button govuk-button--secondary govuk-file-upload__pseudo-button", a.innerText = this.i18n.t("selectFilesButton"), a.setAttribute("aria-hidden", "true"), r.appendChild(a), r.appendChild(i.cloneNode(!0));
+ const l = document.createElement("span");
+ l.className = "govuk-body govuk-file-upload__instruction", l.innerText = this.i18n.t("instruction"), r.appendChild(l), s.appendChild(r), s.setAttribute("aria-label", `${this.$label.innerText}, ${this.i18n.t("selectFilesButton")} ${this.i18n.t("instruction")}, ${o.innerText}`), s.addEventListener("click", this.onClick.bind(this)), n.insertAdjacentElement("beforeend", s), this.$root.insertAdjacentElement("afterend", n), this.$root.setAttribute("tabindex", "-1"), this.$root.setAttribute("aria-hidden", "true"), n.insertAdjacentElement("afterbegin", this.$root), this.$wrapper = n, this.$button = s, this.$status = o, this.$root.addEventListener("change", this.onChange.bind(this)), this.updateDisabledState(), this.observeDisabledState(), this.$root.addEventListener("change", this.onChange.bind(this)), this.$announcements = document.createElement("span"), this.$announcements.classList.add("govuk-file-upload-announcements"), this.$announcements.classList.add("govuk-visually-hidden"), this.$announcements.setAttribute("aria-live", "assertive"), this.$wrapper.insertAdjacentElement("afterend", this.$announcements), this.$wrapper.addEventListener("drop", this.hideDropZone.bind(this)), document.addEventListener("dragenter", this.updateDropzoneVisibility.bind(this)), document.addEventListener("dragenter", (() => {
this.enteredAnotherElement = !0
})), document.addEventListener("dragleave", (() => {
this.enteredAnotherElement || this.hideDropZone(), this.enteredAnotherElement = !1
@@ -780,9 +786,9 @@ class FileUpload extends ConfigurableComponent {
}
onChange() {
const t = this.$root.files.length;
- this.$status.innerText = 0 === t ? this.i18n.t("filesSelectedDefault") : 1 === t ? this.$root.files[0].name : this.i18n.t("filesSelected", {
+ 0 === t ? (this.$status.innerText = this.i18n.t("filesSelectedDefault"), this.$status.classList.add("govuk-tag--light-blue")) : (this.$status.innerText = 1 === t ? this.$root.files[0].name : this.i18n.t("filesSelected", {
count: t
- }), this.$button.setAttribute("aria-label", `${this.$label.innerText}, ${this.i18n.t("selectFilesButton")}, ${this.$status.innerText}`)
+ }), this.$status.classList.remove("govuk-tag--light-blue")), this.$button.setAttribute("aria-label", `${this.$label.innerText}, ${this.i18n.t("selectFilesButton")} ${this.i18n.t("instruction")}, ${this.$status.innerText}`)
}
findLabel() {
const t = document.querySelector(`label[for="${this.$root.id}"]`);
@@ -815,7 +821,8 @@ FileUpload.moduleName = "govuk-file-upload", FileUpload.defaults = Object.freeze
other: "%{count} files chosen"
},
dropZoneEntered: "Entered drop zone",
- dropZoneLeft: "Left drop zone"
+ dropZoneLeft: "Left drop zone",
+ instruction: "or drop file"
}
}), FileUpload.schema = Object.freeze({
properties: {
Action run for 00cb7d9 |
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 9417707ca..343ab1ce7 100644
--- a/packages/govuk-frontend/dist/govuk/govuk-frontend.min.css
+++ b/packages/govuk-frontend/dist/govuk/govuk-frontend.min.css
@@ -3385,25 +3385,23 @@ screen and (forced-colors:active) {
}
.govuk-file-upload-wrapper {
- display: inline-flex;
- align-items: baseline;
- position: relative
+ display: block;
+ position: relative;
+ z-index: 0
}
.govuk-file-upload-wrapper--show-dropzone {
- margin: -12px;
- padding: 10px;
- border: 2px dashed #0b0c0c;
+ outline: 3px solid #fd0;
background-color: #fff
}
-.govuk-file-upload-wrapper--show-dropzone .govuk-file-upload__pseudo-button,
-.govuk-file-upload-wrapper--show-dropzone .govuk-file-upload__status {
- pointer-events: none
+.govuk-file-upload-wrapper--show-dropzone .govuk-file-upload {
+ z-index: 1
}
.govuk-file-upload-wrapper .govuk-file-upload {
position: absolute;
+ z-index: -1;
top: 0;
left: 0;
width: 100%;
@@ -3415,61 +3413,85 @@ screen and (forced-colors:active) {
.govuk-file-upload__pseudo-button {
width: auto;
- margin-bottom: 0;
- flex-grow: 0;
flex-shrink: 0
}
-.govuk-file-upload__status {
- margin-bottom: 0;
+.govuk-file-upload__pseudo-button-container>* {
+ margin-bottom: 0
+}
+
+.govuk-file-upload__instruction {
margin-left: 10px
}
-.govuk-file-upload__button:focus {
- outline: none
+.govuk-file-upload__status {
+ display: block;
+ margin-bottom: 10px;
+ padding: 15px 10px;
+ text-align: left
}
-.govuk-file-upload__button:focus .govuk-file-upload__pseudo-button {
- outline: 3px solid transparent;
- background-color: #fd0;
- box-shadow: 0 2px 0 #0b0c0c
+.govuk-file-upload__pseudo-button-container {
+ display: flex;
+ align-items: baseline
}
-.govuk-file-upload__button:focus .govuk-file-upload__pseudo-button:hover {
- border-color: #fd0;
- outline: 3px solid transparent;
- background-color: #f3f2f1;
- box-shadow: inset 0 0 0 1px #fd0
+.govuk-file-upload__button {
+ width: 100%;
+ padding: 15px 18px;
+ border: 2px dashed #b1b4b6;
+ background-color: #fff;
+ cursor: pointer
}
-.govuk-file-upload__button:active .govuk-file-upload__pseudo-button:hover {
- background-color: #c2c2c1
+@media (min-width:40.0625em) {
+ .govuk-file-upload__button {
+ padding: 15px 23px
+ }
}
-.govuk-file-upload__button {
- align-items: center;
- display: flex;
- padding: 0;
- border: 0;
- background-color: transparent
+.govuk-file-upload__button:hover {
+ border-color: #8e9092
}
-.govuk-file-upload:disabled+.govuk-file-upload__button {
- pointer-events: none
+.govuk-file-upload-wrapper--show-dropzone .govuk-file-upload__button,
+.govuk-file-upload__button:hover,
+.govuk-file-upload__button:hover .govuk-file-upload__pseudo-button {
+ background-color: #f3f2f1
}
-.govuk-file-upload:disabled+.govuk-file-upload__button .govuk-file-upload__pseudo-button {
- opacity: .5
+.govuk-file-upload-wrapper--show-dropzone .govuk-file-upload__status,
+.govuk-file-upload__button:focus .govuk-file-upload__status,
+.govuk-file-upload__button:hover .govuk-file-upload__status {
+ background-color: #d2e2f1
+}
+
+.govuk-file-upload-wrapper--show-dropzone .govuk-file-upload__button {
+ border-color: transparent
+}
+
+.govuk-file-upload-wrapper--show-dropzone .govuk-file-upload__pseudo-button {
+ background-color: #fff
}
-.govuk-file-upload:disabled+.govuk-file-upload__button .govuk-file-upload__pseudo-button:hover {
+.govuk-file-upload__button:active,
+.govuk-file-upload__button:focus {
+ border: 2px solid #0b0c0c;
+ outline: 3px solid #fd0;
+ outline-offset: 0;
background-color: #f3f2f1;
- cursor: not-allowed
+ box-shadow: inset 0 0 0 2px
}
-.govuk-file-upload:disabled+.govuk-file-upload__button .govuk-file-upload__pseudo-button:active {
- top: 0;
- box-shadow: 0 2px 0 #666
+.govuk-file-upload__button:focus .govuk-file-upload__pseudo-button {
+ background-color: #fd0
+}
+
+.govuk-file-upload__button:focus:hover .govuk-file-upload__pseudo-button {
+ border-color: #fd0;
+ outline: 3px solid transparent;
+ background-color: #f3f2f1;
+ box-shadow: inset 0 0 0 1px #fd0
}
.govuk-footer {
Action run for 00cb7d9 |
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 a6d922cdd..05abbd7dc 100644
--- a/packages/govuk-frontend/dist/govuk/all.bundle.js
+++ b/packages/govuk-frontend/dist/govuk/all.bundle.js
@@ -1684,24 +1684,40 @@
});
this.$label = this.findLabel();
this.$root.id = `${this.id}-input`;
+ this.$label.setAttribute('for', `${this.id}-input`);
const $wrapper = document.createElement('div');
$wrapper.className = 'govuk-file-upload-wrapper';
+ const commaSpan = document.createElement('span');
+ commaSpan.className = 'govuk-visually-hidden';
+ commaSpan.innerText = ', ';
const $button = document.createElement('button');
$button.classList.add('govuk-file-upload__button');
$button.type = 'button';
$button.id = this.id;
- const buttonSpan = document.createElement('span');
- buttonSpan.className = 'govuk-button govuk-button--secondary govuk-file-upload__pseudo-button';
- buttonSpan.innerText = this.i18n.t('selectFilesButton');
- buttonSpan.setAttribute('aria-hidden', 'true');
- $button.appendChild(buttonSpan);
- $button.addEventListener('click', this.onClick.bind(this));
const $status = document.createElement('span');
$status.className = 'govuk-body govuk-file-upload__status';
$status.innerText = this.i18n.t('filesSelectedDefault');
$status.setAttribute('aria-hidden', 'true');
+ if (!this.$root.files.length) {
+ $status.classList.add('govuk-tag--light-blue');
+ }
$button.appendChild($status);
- $button.setAttribute('aria-label', `${this.$label.innerText}, ${this.i18n.t('selectFilesButton')}, ${this.i18n.t('filesSelectedDefault')}`);
+ $button.appendChild(commaSpan.cloneNode(true));
+ const buttonParentSpan = document.createElement('span');
+ buttonParentSpan.className = 'govuk-file-upload__pseudo-button-container';
+ const buttonSpan = document.createElement('span');
+ buttonSpan.className = 'govuk-button govuk-button--secondary govuk-file-upload__pseudo-button';
+ buttonSpan.innerText = this.i18n.t('selectFilesButton');
+ buttonSpan.setAttribute('aria-hidden', 'true');
+ buttonParentSpan.appendChild(buttonSpan);
+ buttonParentSpan.appendChild(commaSpan.cloneNode(true));
+ const instructionSpan = document.createElement('span');
+ instructionSpan.className = 'govuk-body govuk-file-upload__instruction';
+ instructionSpan.innerText = this.i18n.t('instruction');
+ buttonParentSpan.appendChild(instructionSpan);
+ $button.appendChild(buttonParentSpan);
+ $button.setAttribute('aria-label', `${this.$label.innerText}, ${this.i18n.t('selectFilesButton')} ${this.i18n.t('instruction')}, ${$status.innerText}`);
+ $button.addEventListener('click', this.onClick.bind(this));
$wrapper.insertAdjacentElement('beforeend', $button);
this.$root.insertAdjacentElement('afterend', $wrapper);
this.$root.setAttribute('tabindex', '-1');
@@ -1761,14 +1777,18 @@
const fileCount = this.$root.files.length;
if (fileCount === 0) {
this.$status.innerText = this.i18n.t('filesSelectedDefault');
- } else if (fileCount === 1) {
- this.$status.innerText = this.$root.files[0].name;
+ this.$status.classList.add('govuk-tag--light-blue');
} else {
- this.$status.innerText = this.i18n.t('filesSelected', {
- count: fileCount
- });
+ if (fileCount === 1) {
+ this.$status.innerText = this.$root.files[0].name;
+ } else {
+ this.$status.innerText = this.i18n.t('filesSelected', {
+ count: fileCount
+ });
+ }
+ this.$status.classList.remove('govuk-tag--light-blue');
}
- this.$button.setAttribute('aria-label', `${this.$label.innerText}, ${this.i18n.t('selectFilesButton')}, ${this.$status.innerText}`);
+ this.$button.setAttribute('aria-label', `${this.$label.innerText}, ${this.i18n.t('selectFilesButton')} ${this.i18n.t('instruction')}, ${this.$status.innerText}`);
}
findLabel() {
const $label = document.querySelector(`label[for="${this.$root.id}"]`);
@@ -1810,7 +1830,8 @@
other: '%{count} files chosen'
},
dropZoneEntered: 'Entered drop zone',
- dropZoneLeft: 'Left drop zone'
+ dropZoneLeft: 'Left drop zone',
+ instruction: 'or drop file'
}
});
FileUpload.schema = Object.freeze({
diff --git a/packages/govuk-frontend/dist/govuk/all.bundle.mjs b/packages/govuk-frontend/dist/govuk/all.bundle.mjs
index 62c861a22..e2c8aba80 100644
--- a/packages/govuk-frontend/dist/govuk/all.bundle.mjs
+++ b/packages/govuk-frontend/dist/govuk/all.bundle.mjs
@@ -1678,24 +1678,40 @@ class FileUpload extends ConfigurableComponent {
});
this.$label = this.findLabel();
this.$root.id = `${this.id}-input`;
+ this.$label.setAttribute('for', `${this.id}-input`);
const $wrapper = document.createElement('div');
$wrapper.className = 'govuk-file-upload-wrapper';
+ const commaSpan = document.createElement('span');
+ commaSpan.className = 'govuk-visually-hidden';
+ commaSpan.innerText = ', ';
const $button = document.createElement('button');
$button.classList.add('govuk-file-upload__button');
$button.type = 'button';
$button.id = this.id;
- const buttonSpan = document.createElement('span');
- buttonSpan.className = 'govuk-button govuk-button--secondary govuk-file-upload__pseudo-button';
- buttonSpan.innerText = this.i18n.t('selectFilesButton');
- buttonSpan.setAttribute('aria-hidden', 'true');
- $button.appendChild(buttonSpan);
- $button.addEventListener('click', this.onClick.bind(this));
const $status = document.createElement('span');
$status.className = 'govuk-body govuk-file-upload__status';
$status.innerText = this.i18n.t('filesSelectedDefault');
$status.setAttribute('aria-hidden', 'true');
+ if (!this.$root.files.length) {
+ $status.classList.add('govuk-tag--light-blue');
+ }
$button.appendChild($status);
- $button.setAttribute('aria-label', `${this.$label.innerText}, ${this.i18n.t('selectFilesButton')}, ${this.i18n.t('filesSelectedDefault')}`);
+ $button.appendChild(commaSpan.cloneNode(true));
+ const buttonParentSpan = document.createElement('span');
+ buttonParentSpan.className = 'govuk-file-upload__pseudo-button-container';
+ const buttonSpan = document.createElement('span');
+ buttonSpan.className = 'govuk-button govuk-button--secondary govuk-file-upload__pseudo-button';
+ buttonSpan.innerText = this.i18n.t('selectFilesButton');
+ buttonSpan.setAttribute('aria-hidden', 'true');
+ buttonParentSpan.appendChild(buttonSpan);
+ buttonParentSpan.appendChild(commaSpan.cloneNode(true));
+ const instructionSpan = document.createElement('span');
+ instructionSpan.className = 'govuk-body govuk-file-upload__instruction';
+ instructionSpan.innerText = this.i18n.t('instruction');
+ buttonParentSpan.appendChild(instructionSpan);
+ $button.appendChild(buttonParentSpan);
+ $button.setAttribute('aria-label', `${this.$label.innerText}, ${this.i18n.t('selectFilesButton')} ${this.i18n.t('instruction')}, ${$status.innerText}`);
+ $button.addEventListener('click', this.onClick.bind(this));
$wrapper.insertAdjacentElement('beforeend', $button);
this.$root.insertAdjacentElement('afterend', $wrapper);
this.$root.setAttribute('tabindex', '-1');
@@ -1755,14 +1771,18 @@ class FileUpload extends ConfigurableComponent {
const fileCount = this.$root.files.length;
if (fileCount === 0) {
this.$status.innerText = this.i18n.t('filesSelectedDefault');
- } else if (fileCount === 1) {
- this.$status.innerText = this.$root.files[0].name;
+ this.$status.classList.add('govuk-tag--light-blue');
} else {
- this.$status.innerText = this.i18n.t('filesSelected', {
- count: fileCount
- });
+ if (fileCount === 1) {
+ this.$status.innerText = this.$root.files[0].name;
+ } else {
+ this.$status.innerText = this.i18n.t('filesSelected', {
+ count: fileCount
+ });
+ }
+ this.$status.classList.remove('govuk-tag--light-blue');
}
- this.$button.setAttribute('aria-label', `${this.$label.innerText}, ${this.i18n.t('selectFilesButton')}, ${this.$status.innerText}`);
+ this.$button.setAttribute('aria-label', `${this.$label.innerText}, ${this.i18n.t('selectFilesButton')} ${this.i18n.t('instruction')}, ${this.$status.innerText}`);
}
findLabel() {
const $label = document.querySelector(`label[for="${this.$root.id}"]`);
@@ -1804,7 +1824,8 @@ FileUpload.defaults = Object.freeze({
other: '%{count} files chosen'
},
dropZoneEntered: 'Entered drop zone',
- dropZoneLeft: 'Left drop zone'
+ dropZoneLeft: 'Left drop zone',
+ instruction: 'or drop file'
}
});
FileUpload.schema = Object.freeze({
diff --git a/packages/govuk-frontend/dist/govuk/components/file-upload/_index.scss b/packages/govuk-frontend/dist/govuk/components/file-upload/_index.scss
index 4dc478173..9b7a57aed 100644
--- a/packages/govuk-frontend/dist/govuk/components/file-upload/_index.scss
+++ b/packages/govuk-frontend/dist/govuk/components/file-upload/_index.scss
@@ -3,6 +3,7 @@
@import "../label/index";
@include govuk-exports("govuk/component/file-upload") {
+ $file-upload-border-width: 2px;
$component-padding: govuk-spacing(1);
.govuk-file-upload {
@@ -48,34 +49,25 @@
}
.govuk-file-upload-wrapper {
- display: inline-flex;
- align-items: baseline;
+ display: block;
position: relative;
+ z-index: 0;
}
.govuk-file-upload-wrapper--show-dropzone {
- $dropzone-padding: govuk-spacing(2);
- $dropzone-offset: $dropzone-padding + $govuk-border-width-form-element;
-
- // Add negative margins to all sides so that content doesn't jump due to
- // the addition of the padding and border.
- margin: -$dropzone-offset;
- padding: $dropzone-padding;
- border: $govuk-border-width-form-element dashed $govuk-input-border-colour;
+ outline: 3px solid #ffdd00;
background-color: $govuk-body-background-colour;
+ }
- .govuk-file-upload__pseudo-button,
- .govuk-file-upload__status {
- // When the dropzone is hovered over, make these aspects not accept
- // mouse events, so dropped files fall through to the input beneath them
- pointer-events: none;
- }
+ .govuk-file-upload-wrapper--show-dropzone .govuk-file-upload {
+ z-index: 1;
}
.govuk-file-upload-wrapper .govuk-file-upload {
+ position: absolute;
// Make the native control take up the entire space of the element, but
// invisible and behind the other elements until we need it
- position: absolute;
+ z-index: -1;
top: 0;
left: 0;
width: 100%;
@@ -87,61 +79,90 @@
.govuk-file-upload__pseudo-button {
width: auto;
- margin-bottom: 0;
- flex-grow: 0;
flex-shrink: 0;
}
- .govuk-file-upload__status {
+ .govuk-file-upload__pseudo-button-container > * {
margin-bottom: 0;
+ }
+
+ .govuk-file-upload__instruction {
margin-left: govuk-spacing(2);
}
-}
-.govuk-file-upload__button:focus {
- outline: none;
-}
+ .govuk-file-upload__status {
+ display: block;
+ margin-bottom: govuk-spacing(2);
+ padding: govuk-spacing(3) govuk-spacing(2);
+ text-align: left;
+ }
-.govuk-file-upload__button:focus .govuk-file-upload__pseudo-button {
- outline: 3px solid transparent;
- background-color: $govuk-focus-colour;
- box-shadow: 0 2px 0 govuk-colour("black");
-}
+ .govuk-file-upload__pseudo-button-container {
+ display: flex;
+ align-items: baseline;
+ }
-.govuk-file-upload__button:focus .govuk-file-upload__pseudo-button:hover {
- border-color: $govuk-focus-colour;
- outline: 3px solid transparent;
- background-color: govuk-colour("light-grey");
- box-shadow: inset 0 0 0 1px $govuk-focus-colour;
-}
+ .govuk-file-upload__button {
+ width: 100%;
+ // align the padding to be same as notification banner and error summary accounting for the thicker borders
+ padding: govuk-spacing(3) (govuk-spacing(3) + $govuk-border-width - $file-upload-border-width);
+ border: $file-upload-border-width govuk-colour("mid-grey") dashed;
+ background-color: govuk-colour("white");
+ cursor: pointer;
+
+ @include govuk-media-query($from: tablet) {
+ padding: govuk-spacing(3) (govuk-spacing(4) + $govuk-border-width - $file-upload-border-width);
+ }
+ }
-.govuk-file-upload__button:active .govuk-file-upload__pseudo-button:hover {
- background-color: govuk-shade(govuk-colour("light-grey"), 20%);
-}
+ .govuk-file-upload__button:hover {
+ border-color: govuk-shade(govuk-colour("mid-grey"), 20%);
+ }
-.govuk-file-upload__button {
- align-items: center;
- display: flex;
- padding: 0;
- border: 0;
- background-color: transparent;
-}
+ .govuk-file-upload-wrapper--show-dropzone .govuk-file-upload__button,
+ .govuk-file-upload__button:hover,
+ .govuk-file-upload__button:hover .govuk-file-upload__pseudo-button {
+ background-color: govuk-colour("light-grey");
+ }
-.govuk-file-upload:disabled + .govuk-file-upload__button {
- pointer-events: none;
-}
+ .govuk-file-upload-wrapper--show-dropzone .govuk-file-upload__status,
+ .govuk-file-upload__button:hover .govuk-file-upload__status,
+ .govuk-file-upload__button:focus .govuk-file-upload__status {
+ background-color: govuk-tint(govuk-colour("blue"), 80%);
+ }
+
+ .govuk-file-upload-wrapper--show-dropzone .govuk-file-upload__button {
+ border-color: transparent;
+ }
-.govuk-file-upload:disabled + .govuk-file-upload__button .govuk-file-upload__pseudo-button {
- opacity: (0.5);
+ .govuk-file-upload-wrapper--show-dropzone .govuk-file-upload__pseudo-button {
+ background-color: govuk-colour("white");
+ }
- &:hover {
+ .govuk-file-upload__button:active,
+ .govuk-file-upload__button:focus {
+ border: 2px solid govuk-colour("black");
+ outline: $govuk-focus-width solid $govuk-focus-colour;
+ // Ensure outline appears outside of the element
+ outline-offset: 0;
background-color: govuk-colour("light-grey");
- cursor: not-allowed;
+ // Double the border by adding its width again. Use `box-shadow` for this
+ // instead of changing `border-width` - this is for consistency with
+ // components such as textarea where we avoid changing `border-width` as
+ // it will change the element size. Also, `outline` cannot be utilised
+ // here as it is already used for the yellow focus state.
+ box-shadow: inset 0 0 0 $govuk-border-width-form-element;
}
- &:active {
- top: 0;
- box-shadow: 0 $govuk-border-width-form-element 0 govuk-shade(govuk-colour("white"), 60%); // s0
+ .govuk-file-upload__button:focus .govuk-file-upload__pseudo-button {
+ background-color: $govuk-focus-colour;
+ }
+
+ .govuk-file-upload__button:focus:hover .govuk-file-upload__pseudo-button {
+ border-color: $govuk-focus-colour;
+ outline: 3px solid transparent;
+ background-color: govuk-colour("light-grey");
+ box-shadow: inset 0 0 0 1px $govuk-focus-colour;
}
}
diff --git a/packages/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.js b/packages/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.js
index 905b3c3e4..a138ee559 100644
--- a/packages/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.js
+++ b/packages/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.js
@@ -511,24 +511,40 @@
});
this.$label = this.findLabel();
this.$root.id = `${this.id}-input`;
+ this.$label.setAttribute('for', `${this.id}-input`);
const $wrapper = document.createElement('div');
$wrapper.className = 'govuk-file-upload-wrapper';
+ const commaSpan = document.createElement('span');
+ commaSpan.className = 'govuk-visually-hidden';
+ commaSpan.innerText = ', ';
const $button = document.createElement('button');
$button.classList.add('govuk-file-upload__button');
$button.type = 'button';
$button.id = this.id;
- const buttonSpan = document.createElement('span');
- buttonSpan.className = 'govuk-button govuk-button--secondary govuk-file-upload__pseudo-button';
- buttonSpan.innerText = this.i18n.t('selectFilesButton');
- buttonSpan.setAttribute('aria-hidden', 'true');
- $button.appendChild(buttonSpan);
- $button.addEventListener('click', this.onClick.bind(this));
const $status = document.createElement('span');
$status.className = 'govuk-body govuk-file-upload__status';
$status.innerText = this.i18n.t('filesSelectedDefault');
$status.setAttribute('aria-hidden', 'true');
+ if (!this.$root.files.length) {
+ $status.classList.add('govuk-tag--light-blue');
+ }
$button.appendChild($status);
- $button.setAttribute('aria-label', `${this.$label.innerText}, ${this.i18n.t('selectFilesButton')}, ${this.i18n.t('filesSelectedDefault')}`);
+ $button.appendChild(commaSpan.cloneNode(true));
+ const buttonParentSpan = document.createElement('span');
+ buttonParentSpan.className = 'govuk-file-upload__pseudo-button-container';
+ const buttonSpan = document.createElement('span');
+ buttonSpan.className = 'govuk-button govuk-button--secondary govuk-file-upload__pseudo-button';
+ buttonSpan.innerText = this.i18n.t('selectFilesButton');
+ buttonSpan.setAttribute('aria-hidden', 'true');
+ buttonParentSpan.appendChild(buttonSpan);
+ buttonParentSpan.appendChild(commaSpan.cloneNode(true));
+ const instructionSpan = document.createElement('span');
+ instructionSpan.className = 'govuk-body govuk-file-upload__instruction';
+ instructionSpan.innerText = this.i18n.t('instruction');
+ buttonParentSpan.appendChild(instructionSpan);
+ $button.appendChild(buttonParentSpan);
+ $button.setAttribute('aria-label', `${this.$label.innerText}, ${this.i18n.t('selectFilesButton')} ${this.i18n.t('instruction')}, ${$status.innerText}`);
+ $button.addEventListener('click', this.onClick.bind(this));
$wrapper.insertAdjacentElement('beforeend', $button);
this.$root.insertAdjacentElement('afterend', $wrapper);
this.$root.setAttribute('tabindex', '-1');
@@ -588,14 +604,18 @@
const fileCount = this.$root.files.length;
if (fileCount === 0) {
this.$status.innerText = this.i18n.t('filesSelectedDefault');
- } else if (fileCount === 1) {
- this.$status.innerText = this.$root.files[0].name;
+ this.$status.classList.add('govuk-tag--light-blue');
} else {
- this.$status.innerText = this.i18n.t('filesSelected', {
- count: fileCount
- });
+ if (fileCount === 1) {
+ this.$status.innerText = this.$root.files[0].name;
+ } else {
+ this.$status.innerText = this.i18n.t('filesSelected', {
+ count: fileCount
+ });
+ }
+ this.$status.classList.remove('govuk-tag--light-blue');
}
- this.$button.setAttribute('aria-label', `${this.$label.innerText}, ${this.i18n.t('selectFilesButton')}, ${this.$status.innerText}`);
+ this.$button.setAttribute('aria-label', `${this.$label.innerText}, ${this.i18n.t('selectFilesButton')} ${this.i18n.t('instruction')}, ${this.$status.innerText}`);
}
findLabel() {
const $label = document.querySelector(`label[for="${this.$root.id}"]`);
@@ -637,7 +657,8 @@
other: '%{count} files chosen'
},
dropZoneEntered: 'Entered drop zone',
- dropZoneLeft: 'Left drop zone'
+ dropZoneLeft: 'Left drop zone',
+ instruction: 'or drop file'
}
});
FileUpload.schema = Object.freeze({
diff --git a/packages/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.mjs b/packages/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.mjs
index 72724da01..d53f5ef9d 100644
--- a/packages/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.mjs
+++ b/packages/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.mjs
@@ -505,24 +505,40 @@ class FileUpload extends ConfigurableComponent {
});
this.$label = this.findLabel();
this.$root.id = `${this.id}-input`;
+ this.$label.setAttribute('for', `${this.id}-input`);
const $wrapper = document.createElement('div');
$wrapper.className = 'govuk-file-upload-wrapper';
+ const commaSpan = document.createElement('span');
+ commaSpan.className = 'govuk-visually-hidden';
+ commaSpan.innerText = ', ';
const $button = document.createElement('button');
$button.classList.add('govuk-file-upload__button');
$button.type = 'button';
$button.id = this.id;
- const buttonSpan = document.createElement('span');
- buttonSpan.className = 'govuk-button govuk-button--secondary govuk-file-upload__pseudo-button';
- buttonSpan.innerText = this.i18n.t('selectFilesButton');
- buttonSpan.setAttribute('aria-hidden', 'true');
- $button.appendChild(buttonSpan);
- $button.addEventListener('click', this.onClick.bind(this));
const $status = document.createElement('span');
$status.className = 'govuk-body govuk-file-upload__status';
$status.innerText = this.i18n.t('filesSelectedDefault');
$status.setAttribute('aria-hidden', 'true');
+ if (!this.$root.files.length) {
+ $status.classList.add('govuk-tag--light-blue');
+ }
$button.appendChild($status);
- $button.setAttribute('aria-label', `${this.$label.innerText}, ${this.i18n.t('selectFilesButton')}, ${this.i18n.t('filesSelectedDefault')}`);
+ $button.appendChild(commaSpan.cloneNode(true));
+ const buttonParentSpan = document.createElement('span');
+ buttonParentSpan.className = 'govuk-file-upload__pseudo-button-container';
+ const buttonSpan = document.createElement('span');
+ buttonSpan.className = 'govuk-button govuk-button--secondary govuk-file-upload__pseudo-button';
+ buttonSpan.innerText = this.i18n.t('selectFilesButton');
+ buttonSpan.setAttribute('aria-hidden', 'true');
+ buttonParentSpan.appendChild(buttonSpan);
+ buttonParentSpan.appendChild(commaSpan.cloneNode(true));
+ const instructionSpan = document.createElement('span');
+ instructionSpan.className = 'govuk-body govuk-file-upload__instruction';
+ instructionSpan.innerText = this.i18n.t('instruction');
+ buttonParentSpan.appendChild(instructionSpan);
+ $button.appendChild(buttonParentSpan);
+ $button.setAttribute('aria-label', `${this.$label.innerText}, ${this.i18n.t('selectFilesButton')} ${this.i18n.t('instruction')}, ${$status.innerText}`);
+ $button.addEventListener('click', this.onClick.bind(this));
$wrapper.insertAdjacentElement('beforeend', $button);
this.$root.insertAdjacentElement('afterend', $wrapper);
this.$root.setAttribute('tabindex', '-1');
@@ -582,14 +598,18 @@ class FileUpload extends ConfigurableComponent {
const fileCount = this.$root.files.length;
if (fileCount === 0) {
this.$status.innerText = this.i18n.t('filesSelectedDefault');
- } else if (fileCount === 1) {
- this.$status.innerText = this.$root.files[0].name;
+ this.$status.classList.add('govuk-tag--light-blue');
} else {
- this.$status.innerText = this.i18n.t('filesSelected', {
- count: fileCount
- });
+ if (fileCount === 1) {
+ this.$status.innerText = this.$root.files[0].name;
+ } else {
+ this.$status.innerText = this.i18n.t('filesSelected', {
+ count: fileCount
+ });
+ }
+ this.$status.classList.remove('govuk-tag--light-blue');
}
- this.$button.setAttribute('aria-label', `${this.$label.innerText}, ${this.i18n.t('selectFilesButton')}, ${this.$status.innerText}`);
+ this.$button.setAttribute('aria-label', `${this.$label.innerText}, ${this.i18n.t('selectFilesButton')} ${this.i18n.t('instruction')}, ${this.$status.innerText}`);
}
findLabel() {
const $label = document.querySelector(`label[for="${this.$root.id}"]`);
@@ -631,7 +651,8 @@ FileUpload.defaults = Object.freeze({
other: '%{count} files chosen'
},
dropZoneEntered: 'Entered drop zone',
- dropZoneLeft: 'Left drop zone'
+ dropZoneLeft: 'Left drop zone',
+ instruction: 'or drop file'
}
});
FileUpload.schema = Object.freeze({
diff --git a/packages/govuk-frontend/dist/govuk/components/file-upload/file-upload.mjs b/packages/govuk-frontend/dist/govuk/components/file-upload/file-upload.mjs
index 3eeaf0c49..8cae2bfa2 100644
--- a/packages/govuk-frontend/dist/govuk/components/file-upload/file-upload.mjs
+++ b/packages/govuk-frontend/dist/govuk/components/file-upload/file-upload.mjs
@@ -34,24 +34,40 @@ class FileUpload extends ConfigurableComponent {
});
this.$label = this.findLabel();
this.$root.id = `${this.id}-input`;
+ this.$label.setAttribute('for', `${this.id}-input`);
const $wrapper = document.createElement('div');
$wrapper.className = 'govuk-file-upload-wrapper';
+ const commaSpan = document.createElement('span');
+ commaSpan.className = 'govuk-visually-hidden';
+ commaSpan.innerText = ', ';
const $button = document.createElement('button');
$button.classList.add('govuk-file-upload__button');
$button.type = 'button';
$button.id = this.id;
- const buttonSpan = document.createElement('span');
- buttonSpan.className = 'govuk-button govuk-button--secondary govuk-file-upload__pseudo-button';
- buttonSpan.innerText = this.i18n.t('selectFilesButton');
- buttonSpan.setAttribute('aria-hidden', 'true');
- $button.appendChild(buttonSpan);
- $button.addEventListener('click', this.onClick.bind(this));
const $status = document.createElement('span');
$status.className = 'govuk-body govuk-file-upload__status';
$status.innerText = this.i18n.t('filesSelectedDefault');
$status.setAttribute('aria-hidden', 'true');
+ if (!this.$root.files.length) {
+ $status.classList.add('govuk-tag--light-blue');
+ }
$button.appendChild($status);
- $button.setAttribute('aria-label', `${this.$label.innerText}, ${this.i18n.t('selectFilesButton')}, ${this.i18n.t('filesSelectedDefault')}`);
+ $button.appendChild(commaSpan.cloneNode(true));
+ const buttonParentSpan = document.createElement('span');
+ buttonParentSpan.className = 'govuk-file-upload__pseudo-button-container';
+ const buttonSpan = document.createElement('span');
+ buttonSpan.className = 'govuk-button govuk-button--secondary govuk-file-upload__pseudo-button';
+ buttonSpan.innerText = this.i18n.t('selectFilesButton');
+ buttonSpan.setAttribute('aria-hidden', 'true');
+ buttonParentSpan.appendChild(buttonSpan);
+ buttonParentSpan.appendChild(commaSpan.cloneNode(true));
+ const instructionSpan = document.createElement('span');
+ instructionSpan.className = 'govuk-body govuk-file-upload__instruction';
+ instructionSpan.innerText = this.i18n.t('instruction');
+ buttonParentSpan.appendChild(instructionSpan);
+ $button.appendChild(buttonParentSpan);
+ $button.setAttribute('aria-label', `${this.$label.innerText}, ${this.i18n.t('selectFilesButton')} ${this.i18n.t('instruction')}, ${$status.innerText}`);
+ $button.addEventListener('click', this.onClick.bind(this));
$wrapper.insertAdjacentElement('beforeend', $button);
this.$root.insertAdjacentElement('afterend', $wrapper);
this.$root.setAttribute('tabindex', '-1');
@@ -111,14 +127,18 @@ class FileUpload extends ConfigurableComponent {
const fileCount = this.$root.files.length;
if (fileCount === 0) {
this.$status.innerText = this.i18n.t('filesSelectedDefault');
- } else if (fileCount === 1) {
- this.$status.innerText = this.$root.files[0].name;
+ this.$status.classList.add('govuk-tag--light-blue');
} else {
- this.$status.innerText = this.i18n.t('filesSelected', {
- count: fileCount
- });
+ if (fileCount === 1) {
+ this.$status.innerText = this.$root.files[0].name;
+ } else {
+ this.$status.innerText = this.i18n.t('filesSelected', {
+ count: fileCount
+ });
+ }
+ this.$status.classList.remove('govuk-tag--light-blue');
}
- this.$button.setAttribute('aria-label', `${this.$label.innerText}, ${this.i18n.t('selectFilesButton')}, ${this.$status.innerText}`);
+ this.$button.setAttribute('aria-label', `${this.$label.innerText}, ${this.i18n.t('selectFilesButton')} ${this.i18n.t('instruction')}, ${this.$status.innerText}`);
}
findLabel() {
const $label = document.querySelector(`label[for="${this.$root.id}"]`);
@@ -160,7 +180,8 @@ FileUpload.defaults = Object.freeze({
other: '%{count} files chosen'
},
dropZoneEntered: 'Entered drop zone',
- dropZoneLeft: 'Left drop zone'
+ dropZoneLeft: 'Left drop zone',
+ instruction: 'or drop file'
}
});
FileUpload.schema = Object.freeze({
diff --git a/packages/govuk-frontend/dist/govuk/components/file-upload/fixtures.json b/packages/govuk-frontend/dist/govuk/components/file-upload/fixtures.json
index 74645e1bc..dacd5ee56 100644
--- a/packages/govuk-frontend/dist/govuk/components/file-upload/fixtures.json
+++ b/packages/govuk-frontend/dist/govuk/components/file-upload/fixtures.json
@@ -168,6 +168,7 @@
},
"multiple": true,
"selectFilesButtonText": "Dewiswch ffeil",
+ "instructionText": "neu ollwng ffeil",
"filesSelectedDefaultText": "Dim ffeiliau wedi'u dewis",
"filesSelectedText": {
"other": "%{count} ffeil wedi'u dewis",
@@ -178,7 +179,7 @@
"description": "",
"previewLayoutModifiers": [],
"screenshot": false,
- "html": "<div class=\"govuk-form-group\">\n <label class=\"govuk-label\" for=\"file-upload-1\">\n Llwythwch ffeil i fyny\n </label>\n <input class=\"govuk-file-upload\" id=\"file-upload-1\" name=\"file-upload-1\" type=\"file\" data-module=\"govuk-file-upload\" multiple data-i18n.select-files-button=\"Dewiswch ffeil\" data-i18n.files-selected-default=\"Dim ffeiliau wedi'u dewis\" data-i18n.files-selected.other=\"%{count} ffeil wedi'u dewis\" data-i18n.files-selected.one=\"%{count} ffeil wedi'i dewis\">\n</div>"
+ "html": "<div class=\"govuk-form-group\">\n <label class=\"govuk-label\" for=\"file-upload-1\">\n Llwythwch ffeil i fyny\n </label>\n <input class=\"govuk-file-upload\" id=\"file-upload-1\" name=\"file-upload-1\" type=\"file\" data-module=\"govuk-file-upload\" multiple data-i18n.select-files-button=\"Dewiswch ffeil\" data-i18n.files-selected-default=\"Dim ffeiliau wedi'u dewis\" data-i18n.files-selected.other=\"%{count} ffeil wedi'u dewis\" data-i18n.files-selected.one=\"%{count} ffeil wedi'i dewis\" data-i18n.instruction.0=\"n\" data-i18n.instruction.1=\"e\" data-i18n.instruction.2=\"u\" data-i18n.instruction.3=\" \" data-i18n.instruction.4=\"o\" data-i18n.instruction.5=\"l\" data-i18n.instruction.6=\"l\" data-i18n.instruction.7=\"w\" data-i18n.instruction.8=\"n\" data-i18n.instruction.9=\"g\" data-i18n.instruction.10=\" \" data-i18n.instruction.11=\"f\" data-i18n.instruction.12=\"f\" data-i18n.instruction.13=\"e\" data-i18n.instruction.14=\"i\" data-i18n.instruction.15=\"l\">\n</div>"
},
{
"name": "with value",
diff --git a/packages/govuk-frontend/dist/govuk/components/file-upload/macro-options.json b/packages/govuk-frontend/dist/govuk/components/file-upload/macro-options.json
index deb9c3604..1da949426 100644
--- a/packages/govuk-frontend/dist/govuk/components/file-upload/macro-options.json
+++ b/packages/govuk-frontend/dist/govuk/components/file-upload/macro-options.json
@@ -122,6 +122,12 @@
"required": false,
"description": "The text of the button that opens the file picker. JavaScript enhanced version of the component only. Default is \"Choose file\"."
},
+ {
+ "name": "instructionText",
+ "type": "string",
+ "required": false,
+ "description": "The text of the instruction text that follows the button that opens the file picker. JavaScript enhanced version of the component only. Default is \"or drop file\"."
+ },
{
"name": "filesSelected",
"type": "object",
Action run for 00cb7d9 |
cb99c32
to
fabd47e
Compare
fabd47e
to
be4ca83
Compare
be4ca83
to
6824061
Compare
6824061
to
789d1dc
Compare
789d1dc
to
d01c7b7
Compare
Cheers Patrick, that's a good start! I've documented a couple of missed details in the design document (internal link).
@CharlotteDowns It's a bit strange to have such variation in padding. Inspecting the Notification Banner on the Design System site, I'm seeing the following paddings:
Similarly on the Error Summary, the padding seems happily at |
@romaricpascal this could be my poor maths but I'm trying to recreate the same visual properties and alignment to the Notification banner and Error summary but working with a 2px border instead of a 5px border (used on those components). Maybe I should refer to the summary card styling instead 🤔, although that seems to only have a 1px border :(. |
Button creation of file upload needs to be changed in line with the new design. Includes new `instruction span` which has been added to the i18n configuration.
d01c7b7
to
ee7639d
Compare
ee7639d
to
f9fa5fd
Compare
New styles for file upload component. Includes adjusting the `z-index` when the dropzone is toggled.
f9fa5fd
to
d189988
Compare
$status.setAttribute('aria-hidden', 'true') | ||
|
||
if (!this.$root.files.length) { | ||
$status.classList.add('govuk-tag--light-blue') |
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.
@patrickpatrickpatrick Missed that bit earlier. Rather than risking an unexpected change if we update the styles of the Tag component, let's isolate this with a class specific to the file-upload 😊
Same goes with the govuk-body
in line 89 and 113, we can configure the font in the classes specific to the govuk-file-upload
and avoid worrying about other styles brought by govuk-body
(like the margin).
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.
At the point the component is initialised files
won't be filed as the page will just be loaded, so we can drop that if
from the constructor altogether and only update the styles when the user selects a file 😊
Rendered HTML changes to npm packagediff --git a/packages/govuk-frontend/dist/govuk/components/file-upload/template-translated.html b/packages/govuk-frontend/dist/govuk/components/file-upload/template-translated.html
index a39fab0a5..598965d3b 100644
--- a/packages/govuk-frontend/dist/govuk/components/file-upload/template-translated.html
+++ b/packages/govuk-frontend/dist/govuk/components/file-upload/template-translated.html
@@ -2,5 +2,5 @@
<label class="govuk-label" for="file-upload-1">
Llwythwch ffeil i fyny
</label>
- <input class="govuk-file-upload" id="file-upload-1" name="file-upload-1" type="file" data-module="govuk-file-upload" multiple data-i18n.select-files-button="Dewiswch ffeil" data-i18n.files-selected-default="Dim ffeiliau wedi'u dewis" data-i18n.files-selected.other="%{count} ffeil wedi'u dewis" data-i18n.files-selected.one="%{count} ffeil wedi'i dewis">
+ <input class="govuk-file-upload" id="file-upload-1" name="file-upload-1" type="file" data-module="govuk-file-upload" multiple data-i18n.select-files-button="Dewiswch ffeil" data-i18n.files-selected-default="Dim ffeiliau wedi'u dewis" data-i18n.files-selected.other="%{count} ffeil wedi'u dewis" data-i18n.files-selected.one="%{count} ffeil wedi'i dewis" data-i18n.instruction.0="n" data-i18n.instruction.1="e" data-i18n.instruction.2="u" data-i18n.instruction.3=" " data-i18n.instruction.4="o" data-i18n.instruction.5="l" data-i18n.instruction.6="l" data-i18n.instruction.7="w" data-i18n.instruction.8="n" data-i18n.instruction.9="g" data-i18n.instruction.10=" " data-i18n.instruction.11="f" data-i18n.instruction.12="f" data-i18n.instruction.13="e" data-i18n.instruction.14="i" data-i18n.instruction.15="l">
</div>
Action run for 00cb7d9 |
What
Implement the new file input design.
Why
Fixes #5611