diff --git a/core/src/main/resources/hudson/PluginManager/advanced.jelly b/core/src/main/resources/hudson/PluginManager/advanced.jelly
index caa86089f20d..ea74dc18d53a 100644
--- a/core/src/main/resources/hudson/PluginManager/advanced.jelly
+++ b/core/src/main/resources/hudson/PluginManager/advanced.jelly
@@ -60,8 +60,8 @@ THE SOFTWARE.
${%deploytext}
-
-
+
+
${%Or}
diff --git a/core/src/main/resources/hudson/model/FileParameterDefinition/index.jelly b/core/src/main/resources/hudson/model/FileParameterDefinition/index.jelly
index cffab71468bc..7e8208003ab3 100644
--- a/core/src/main/resources/hudson/model/FileParameterDefinition/index.jelly
+++ b/core/src/main/resources/hudson/model/FileParameterDefinition/index.jelly
@@ -27,10 +27,10 @@ THE SOFTWARE.
xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form"
xmlns:i="jelly:fmt" xmlns:p="/lib/hudson/project">
-
+
-
+
-
\ No newline at end of file
+
diff --git a/core/src/main/resources/jenkins/model/Jenkins/fingerprintCheck.jelly b/core/src/main/resources/jenkins/model/Jenkins/fingerprintCheck.jelly
index d083b8928ddf..911918933357 100644
--- a/core/src/main/resources/jenkins/model/Jenkins/fingerprintCheck.jelly
+++ b/core/src/main/resources/jenkins/model/Jenkins/fingerprintCheck.jelly
@@ -40,8 +40,8 @@ THE SOFTWARE.
${%description} (${%more details})
-
-
+
+
diff --git a/core/src/main/resources/lib/form/file.jelly b/core/src/main/resources/lib/form/file.jelly
new file mode 100644
index 000000000000..ed9ad0b0867c
--- /dev/null
+++ b/core/src/main/resources/lib/form/file.jelly
@@ -0,0 +1,51 @@
+
+
+
+
+
+ Generates an input field <input type="file" ... />
+
+
+ Used for databinding.
+
+
+ Enable structured form submission.
+
+
+ Defines the file types the file input should accept. This string is a comma-separated list.
+
+ @since TODO
+
+
+
+
+
+
+
diff --git a/war/src/main/less/base/style.less b/war/src/main/less/base/style.less
index bedd094f471a..262efd1a8f3f 100644
--- a/war/src/main/less/base/style.less
+++ b/war/src/main/less/base/style.less
@@ -301,7 +301,7 @@ pre.console {
}
.setting-name,
-.setting-main > input,
+.setting-main > input:not([type="file"]),
.setting-main > textarea {
vertical-align: middle;
margin-top: 0;
diff --git a/war/src/main/less/form/file-upload.less b/war/src/main/less/form/file-upload.less
new file mode 100644
index 000000000000..9de4b03d3f4b
--- /dev/null
+++ b/war/src/main/less/form/file-upload.less
@@ -0,0 +1,62 @@
+.jenkins-file-upload {
+ position: relative;
+ width: 100%;
+ margin: -10px 0 0 -10px;
+ padding: 10px 0 10px 10px;
+ outline: none;
+ background: transparent;
+
+ &::before {
+ content: "";
+ position: absolute;
+ display: block;
+ left: calc(10px + 0.9rem);
+ width: 1rem;
+ height: 36px;
+ background: currentColor;
+ mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M320 367.79h76c55 0 100-29.21 100-83.6s-53-81.47-96-83.6c-8.89-85.06-71-136.8-144-136.8-69 0-113.44 45.79-128 91.2-60 5.7-112 43.88-112 106.4s54 106.4 120 106.4h56' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='40'/%3E%3Cpath fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='40' d='M320 255.79l-64-64-64 64M256 448.21V207.79'/%3E%3C/svg%3E");
+ mask-position: center;
+ mask-repeat: no-repeat;
+ pointer-events: none;
+ }
+
+ &::file-selector-button {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ border: none;
+ outline: none;
+ margin: 0 1rem 0 0;
+ padding: 0.5rem 0.85rem 0.5rem 2.5rem;
+ // Firefox doesn't support pseudo elements on inputs so don't increase padding to accommodate
+ @supports (-moz-appearance: none) {
+ padding: 0.5rem 0.85rem;
+ }
+
+ font-size: 0.8rem;
+ font-weight: 500;
+ color: var(--text-color);
+ border-radius: 0.66rem;
+ cursor: pointer;
+ min-height: 36px;
+ white-space: nowrap;
+ background: var(--button-background);
+ transition: var(--standard-transition);
+ box-shadow: 0 0 0 10px transparent;
+
+ &:hover {
+ background: var(--button-background--hover);
+ }
+
+ &:active {
+ background: var(--button-background--active);
+ box-shadow: 0 0 0 5px var(--button-box-shadow--focus);
+ }
+ }
+
+ &:focus-visible {
+ &::file-selector-button {
+ box-shadow: 0 0 0 0.2rem var(--text-color) !important;
+ }
+ }
+}
diff --git a/war/src/main/less/styles.less b/war/src/main/less/styles.less
index 646d5bb0df5f..026b1acf0680 100644
--- a/war/src/main/less/styles.less
+++ b/war/src/main/less/styles.less
@@ -9,6 +9,7 @@
@import url("./base/yui-compatibility");
@import url("./form/checkbox");
@import url("./form/codemirror");
+@import url("./form/file-upload");
@import url("./form/input");
@import url("./form/layout");
@import url("./form/radio");