]> git.ipfire.org Git - thirdparty/bootstrap.git/commitdiff
Drop custom file upload plugin in favor of CSS
authorMartijn Cuppens <martijn.cuppens@gmail.com>
Thu, 22 Oct 2020 13:20:53 +0000 (15:20 +0200)
committerMartijn Cuppens <martijn.cuppens@gmail.com>
Wed, 28 Oct 2020 17:29:28 +0000 (18:29 +0100)
15 files changed:
scss/_forms.scss
scss/_variables.scss
scss/forms/_form-control.scss
scss/forms/_form-file.scss [deleted file]
scss/forms/_input-group.scss
scss/mixins/_forms.scss
site/assets/js/application.js
site/assets/js/vendor/bs-custom-file-input.min.js [deleted file]
site/content/docs/5.0/forms/file.md [deleted file]
site/content/docs/5.0/forms/form-control.md
site/content/docs/5.0/forms/input-group.md
site/content/docs/5.0/forms/overview.md
site/content/docs/5.0/forms/validation.md
site/content/docs/5.0/migration.md
site/data/sidebar.yml

index d2a15a4f2edb3d563c829d765f209fb9035b849b..7b17d849ac0f6f8aab561e4c54065c3180941658 100644 (file)
@@ -3,7 +3,6 @@
 @import "forms/form-control";
 @import "forms/form-select";
 @import "forms/form-check";
-@import "forms/form-file";
 @import "forms/form-range";
 @import "forms/floating-labels";
 @import "forms/input-group";
index 1c0429f9a997151879749b3c57a503d2ff6a44c5..beb3e8c0caec46ded414d85f7e95d060bd8eec51 100644 (file)
@@ -793,35 +793,9 @@ $form-range-thumb-active-bg:               tint-color($component-active-bg, 70%)
 $form-range-thumb-disabled-bg:             $gray-500 !default;
 $form-range-thumb-transition:              background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;
 
-$form-file-height:                $input-height !default;
-$form-file-focus-border-color:    $input-focus-border-color !default;
-$form-file-focus-box-shadow:      $input-focus-box-shadow !default;
-$form-file-disabled-bg:           $input-disabled-bg !default;
-$form-file-disabled-border-color: $input-disabled-border-color !default;
-
-$form-file-padding-y:             $input-padding-y !default;
-$form-file-padding-x:             $input-padding-x !default;
-$form-file-line-height:           $input-line-height !default;
-$form-file-font-family:           $input-font-family !default;
-$form-file-font-weight:           $input-font-weight !default;
-$form-file-color:                 $input-color !default;
-$form-file-bg:                    $input-bg !default;
-$form-file-border-width:          $input-border-width !default;
-$form-file-border-color:          $input-border-color !default;
-$form-file-border-radius:         $input-border-radius !default;
-$form-file-box-shadow:            $input-box-shadow !default;
-$form-file-button-color:          $form-file-color !default;
+$form-file-button-color:          $input-color !default;
 $form-file-button-bg:             $input-group-addon-bg !default;
-
-$form-file-padding-y-sm:          $input-padding-y-sm !default;
-$form-file-padding-x-sm:          $input-padding-x-sm !default;
-$form-file-font-size-sm:          $input-font-size-sm !default;
-$form-file-height-sm:             $input-height-sm !default;
-
-$form-file-padding-y-lg:          $input-padding-y-lg !default;
-$form-file-padding-x-lg:          $input-padding-x-lg !default;
-$form-file-font-size-lg:          $input-font-size-lg !default;
-$form-file-height-lg:             $input-height-lg !default;
+$form-file-button-hover-bg:       shade-color($input-group-addon-bg, 5%) !default;
 
 $form-floating-height:            add(3.5rem, $input-height-border) !default;
 $form-floating-padding-x:         $input-padding-x !default;
index 6686ecfb8058c979794c78ca4f6fa0873ba22860..9fa9cbae454dc7e29fb3f58cfcfc4cd99b08c6d4 100644 (file)
   @include box-shadow($input-box-shadow);
   @include transition($input-transition);
 
+  &[type="file"] {
+    overflow: hidden; // prevent pseudo element button overlap
+
+    &:not(:disabled):not([readonly]) {
+      cursor: pointer;
+    }
+  }
+
   // Customize the `:focus` state to imitate native WebKit styles.
   &:focus {
     color: $input-focus-color;
     // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655.
     opacity: 1;
   }
+
+  // File input buttons theming
+  // stylelint-disable-next-line selector-pseudo-element-no-unknown
+  &::file-selector-button {
+    padding: $input-padding-y $input-padding-x;
+    margin: (-$input-padding-y) (-$input-padding-x);
+    margin-inline-end: $input-padding-x;
+    line-height: inherit;
+    color: $form-file-button-color;
+    @include gradient-bg($form-file-button-bg);
+    pointer-events: none;
+    border-color: inherit;
+    border-style: solid;
+    border-width: 0;
+    border-inline-end-width: $input-border-width;
+    border-radius: 0; // stylelint-disable-line property-disallowed-list
+    @include transition($btn-transition);
+  }
+
+  // stylelint-disable-next-line selector-pseudo-element-no-unknown
+  &:hover:not(:disabled):not([readonly])::file-selector-button {
+    background-color: $form-file-button-hover-bg;
+  }
+
+  &::-webkit-file-upload-button {
+    padding: $input-padding-y $input-padding-x;
+    margin: (-$input-padding-y) (-$input-padding-x);
+    margin-inline-end: $input-padding-x;
+    line-height: inherit;
+    color: $form-file-button-color;
+    @include gradient-bg($form-file-button-bg);
+    pointer-events: none;
+    border-color: inherit;
+    border-style: solid;
+    border-width: 0;
+    border-inline-end-width: $input-border-width;
+    border-radius: 0; // stylelint-disable-line property-disallowed-list
+    @include transition($btn-transition);
+  }
+
+  &:hover:not(:disabled):not([readonly])::-webkit-file-upload-button {
+    background-color: $form-file-button-hover-bg;
+  }
 }
 
 // Readonly controls as plain text
   padding: $input-padding-y-sm $input-padding-x-sm;
   @include font-size($input-font-size-sm);
   @include border-radius($input-border-radius-sm);
+
+  // stylelint-disable-next-line selector-pseudo-element-no-unknown
+  &::file-selector-button {
+    padding: $input-padding-y-sm $input-padding-x-sm;
+    margin: (-$input-padding-y-sm) (-$input-padding-x-sm);
+    margin-inline-end: $input-padding-x-sm;
+  }
+
+  &::-webkit-file-upload-button {
+    padding: $input-padding-y-sm $input-padding-x-sm;
+    margin: (-$input-padding-y-sm) (-$input-padding-x-sm);
+    margin-inline-end: $input-padding-x-sm;
+  }
 }
 
 .form-control-lg {
   padding: $input-padding-y-lg $input-padding-x-lg;
   @include font-size($input-font-size-lg);
   @include border-radius($input-border-radius-lg);
+
+  // stylelint-disable-next-line selector-pseudo-element-no-unknown
+  &::file-selector-button {
+    padding: $input-padding-y-lg $input-padding-x-lg;
+    margin: (-$input-padding-y-lg) (-$input-padding-x-lg);
+    margin-inline-end: $input-padding-x-lg;
+  }
+
+  &::-webkit-file-upload-button {
+    padding: $input-padding-y-lg $input-padding-x-lg;
+    margin: (-$input-padding-y-lg) (-$input-padding-x-lg);
+    margin-inline-end: $input-padding-x-lg;
+  }
 }
 
 .form-control-color {
diff --git a/scss/forms/_form-file.scss b/scss/forms/_form-file.scss
deleted file mode 100644 (file)
index 228d9ad..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-.form-file {
-  --#{$variable-prefix}form-file-height: #{$form-file-height};
-  position: relative;
-}
-
-.form-file-input {
-  position: relative;
-  z-index: 2;
-  width: 100%;
-  height: var(--#{$variable-prefix}form-file-height);
-  margin: 0;
-  opacity: 0;
-
-  &:focus-within ~ .form-file-label {
-    border-color: $form-file-focus-border-color;
-    box-shadow: $form-file-focus-box-shadow;
-  }
-
-  // Use disabled attribute in addition of :disabled pseudo-class
-  // See: https://github.com/twbs/bootstrap/issues/28247
-  &[disabled] ~ .form-file-label .form-file-text,
-  &:disabled ~ .form-file-label .form-file-text {
-    background-color: $form-file-disabled-bg;
-    border-color: $form-file-disabled-border-color;
-  }
-}
-
-.form-file-label {
-  position: absolute;
-  top: 0;
-  right: 0;
-  left: 0;
-  z-index: 1;
-  display: flex;
-  height: var(--#{$variable-prefix}form-file-height);
-  border-color: $form-file-border-color;
-  @include border-radius($form-file-border-radius);
-  @include box-shadow($form-file-box-shadow);
-}
-
-.form-file-text {
-  display: block;
-  flex-grow: 1;
-  padding: $form-file-padding-y $form-file-padding-x;
-  overflow: hidden;
-  font-family: $form-file-font-family;
-  font-weight: $form-file-font-weight;
-  line-height: $form-file-line-height;
-  color: $form-file-color;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-  background-color: $form-file-bg;
-  border-color: inherit;
-  border-style: solid;
-  border-width: $form-file-border-width;
-  @include border-left-radius(inherit);
-}
-
-.form-file-button {
-  display: block;
-  flex-shrink: 0;
-  padding: $form-file-padding-y $form-file-padding-x;
-  margin-left: -$form-file-border-width;
-  line-height: $form-file-line-height;
-  color: $form-file-button-color;
-  @include gradient-bg($form-file-button-bg);
-  border-color: inherit;
-  border-style: solid;
-  border-width: $form-file-border-width;
-  @include border-right-radius(inherit);
-}
-
-.form-file-sm {
-  --#{$variable-prefix}form-file-height: #{$form-file-height-sm};
-  @include font-size($form-file-font-size-sm);
-
-  .form-file-text,
-  .form-file-button {
-    padding: $form-file-padding-y-sm $form-file-padding-x-sm;
-  }
-}
-
-.form-file-lg {
-  --#{$variable-prefix}form-file-height: #{$form-file-height-lg};
-  @include font-size($form-file-font-size-lg);
-
-  .form-file-text,
-  .form-file-button {
-    padding: $form-file-padding-y-lg $form-file-padding-x-lg;
-  }
-}
index 5611f85c5be921ea4c9767b13151d2b8ccfb90b2..938a4185b354bb5ffa7f5d8b848d22d8e657ee95 100644 (file)
@@ -10,8 +10,7 @@
   width: 100%;
 
   > .form-control,
-  > .form-select,
-  > .form-file {
+  > .form-select {
     position: relative; // For focus state's z-index
     flex: 1 1 auto;
     width: 1%;
 
   // Bring the "active" form control to the top of surrounding elements
   > .form-control:focus,
-  > .form-select:focus,
-  > .form-file .form-file-input:focus ~ .form-file-label {
+  > .form-select:focus {
     z-index: 3;
   }
 
-  // Bring the custom file input above the label
-  > .form-file {
-    > .form-file-input:focus {
-      z-index: 4;
-    }
-
-    &:not(:last-child) > .form-file-label {
-      @include border-right-radius(0);
-    }
-
-    &:not(:first-child) > .form-file-label {
-      @include border-left-radius(0);
-    }
-  }
-
   // Ensure buttons are always above inputs for more visually pleasing borders.
   // This isn't needed for `.input-group-text` since it shares the same border-color
   // as our inputs.
index 99ca559846aad84d2363833a63247958ad787dea..9adc0debee4268a0f2705c5d9e4e16eb0890653e 100644 (file)
       margin-left: .5em;
     }
   }
-
-  // custom file
-  .form-file-input {
-    @include form-validation-state-selector($state) {
-      ~ .form-file-label {
-        border-color: $color;
-      }
-
-      &:focus {
-        ~ .form-file-label {
-          border-color: $color;
-          box-shadow: 0 0 0 $input-focus-width rgba($color, .25);
-        }
-      }
-    }
-  }
 }
index 51dc20d42d16535dbc61a83dc4d73ba8b1a076c7..52822dc0ce284b344eb6597726f61122804bbd7b 100644 (file)
@@ -10,7 +10,7 @@
  * For details, see https://creativecommons.org/licenses/by/3.0/.
  */
 
-/* global ClipboardJS: false, anchors: false, bootstrap: false, bsCustomFileInput: false */
+/* global ClipboardJS: false, anchors: false, bootstrap: false */
 
 (function () {
   'use strict'
     icon: '#'
   }
   anchors.add('.bd-content > h2, .bd-content > h3, .bd-content > h4, .bd-content > h5')
-
-  bsCustomFileInput.init()
 })()
diff --git a/site/assets/js/vendor/bs-custom-file-input.min.js b/site/assets/js/vendor/bs-custom-file-input.min.js
deleted file mode 100644 (file)
index 0815f37..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-/*!
- * bsCustomFileInput v1.3.4 (https://github.com/Johann-S/bs-custom-file-input)
- * Copyright 2018 - 2020 Johann-S <johann.servoire@gmail.com>
- * Licensed under MIT (https://github.com/Johann-S/bs-custom-file-input/blob/master/LICENSE)
- */
-!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).bsCustomFileInput=t()}(this,function(){"use strict";var s={CUSTOMFILE:'.custom-file input[type="file"]',CUSTOMFILELABEL:".custom-file-label",FORM:"form",INPUT:"input"},l=function(e){if(0<e.childNodes.length)for(var t=[].slice.call(e.childNodes),n=0;n<t.length;n++){var l=t[n];if(3!==l.nodeType)return l}return e},u=function(e){var t=e.bsCustomFileInput.defaultText,n=e.parentNode.querySelector(s.CUSTOMFILELABEL);n&&(l(n).textContent=t)},n=!!window.File,r=function(e){if(e.hasAttribute("multiple")&&n)return[].slice.call(e.files).map(function(e){return e.name}).join(", ");if(-1===e.value.indexOf("fakepath"))return e.value;var t=e.value.split("\\");return t[t.length-1]};function d(){var e=this.parentNode.querySelector(s.CUSTOMFILELABEL);if(e){var t=l(e),n=r(this);n.length?t.textContent=n:u(this)}}function v(){for(var e=[].slice.call(this.querySelectorAll(s.INPUT)).filter(function(e){return!!e.bsCustomFileInput}),t=0,n=e.length;t<n;t++)u(e[t])}var p="bsCustomFileInput",m="reset",h="change";return{init:function(e,t){void 0===e&&(e=s.CUSTOMFILE),void 0===t&&(t=s.FORM);for(var n,l,r=[].slice.call(document.querySelectorAll(e)),i=[].slice.call(document.querySelectorAll(t)),o=0,u=r.length;o<u;o++){var c=r[o];Object.defineProperty(c,p,{value:{defaultText:(n=void 0,n="",(l=c.parentNode.querySelector(s.CUSTOMFILELABEL))&&(n=l.textContent),n)},writable:!0}),d.call(c),c.addEventListener(h,d)}for(var f=0,a=i.length;f<a;f++)i[f].addEventListener(m,v),Object.defineProperty(i[f],p,{value:!0,writable:!0})},destroy:function(){for(var e=[].slice.call(document.querySelectorAll(s.FORM)).filter(function(e){return!!e.bsCustomFileInput}),t=[].slice.call(document.querySelectorAll(s.INPUT)).filter(function(e){return!!e.bsCustomFileInput}),n=0,l=t.length;n<l;n++){var r=t[n];u(r),r[p]=void 0,r.removeEventListener(h,d)}for(var i=0,o=e.length;i<o;i++)e[i].removeEventListener(m,v),e[i][p]=void 0}}});
-//# sourceMappingURL=bs-custom-file-input.min.js.map
diff --git a/site/content/docs/5.0/forms/file.md b/site/content/docs/5.0/forms/file.md
deleted file mode 100644 (file)
index 466e7b0..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
----
-layout: docs
-title: File browser
-description: Use our custom file inputs for consistent cross-browser styling, built-in customization, and lightweight JavaScript.
-group: forms
-toc: true
----
-
-{{< callout info >}}
-The recommended plugin to animate custom file inputs is [bs-custom-file-input](https://www.npmjs.com/package/bs-custom-file-input); it's what we use here in our docs.
-{{< /callout >}}
-
-## Default
-
-The file input is the most gnarly of the bunch and requires additional JavaScript if you'd like to hook them up with functional *Choose file...* and selected file name text.
-
-{{< example >}}
-<div class="form-file">
-  <input type="file" class="form-file-input" id="customFile">
-  <label class="form-file-label" for="customFile">
-    <span class="form-file-text">Choose file...</span>
-    <span class="form-file-button">Browse</span>
-  </label>
-</div>
-{{< /example >}}
-
-Add the `disabled` attribute to the `<input>` and the custom markup will be updated to appear disabled.
-
-{{< example >}}
-<div class="form-file">
-  <input type="file" class="form-file-input" id="customFileDisabled" disabled>
-  <label class="form-file-label" for="customFileDisabled">
-    <span class="form-file-text">Choose file...</span>
-    <span class="form-file-button">Browse</span>
-  </label>
-</div>
-{{< /example >}}
-
-Longer placeholder text is truncated and an ellipsis is added when there's not enough space.
-
-{{< example >}}
-<div class="form-file">
-  <input type="file" class="form-file-input" id="customFileLong">
-  <label class="form-file-label" for="customFileLong">
-    <span class="form-file-text">Lorem ipsum posuere consectetur est at lobortis nulla vitae elit libero a pharetra augue fusce dapibus tellus ac cursus commodo tortor mauris condimentum nibh ut fermentum massa justo sit amet risus cras mattis consectetur purus sit amet fermentum</span>
-    <span class="form-file-button">Browse</span>
-  </label>
-</div>
-{{< /example >}}
-
-We hide the default file `<input>` via `opacity` and instead style the `<label>`, and declare a `width` and `height` on the `<input>` for proper spacing for surrounding content.
-
-## Sizing
-
-You may also choose from small and large file inputs to match our similarly sized text inputs.
-
-{{< example >}}
-<div class="form-file form-file-lg mb-3">
-  <input type="file" class="form-file-input" id="customFileLg">
-  <label class="form-file-label" for="customFileLg">
-    <span class="form-file-text">Choose file...</span>
-    <span class="form-file-button">Browse</span>
-  </label>
-</div>
-
-<div class="form-file form-file-sm">
-  <input type="file" class="form-file-input" id="customFileSm">
-  <label class="form-file-label" for="customFileSm">
-    <span class="form-file-text">Choose file...</span>
-    <span class="form-file-button">Browse</span>
-  </label>
-</div>
-{{< /example >}}
index 0287a90d23d8d035a09420de845ebda75cd39b7f..cb86162bead39af2d4b2a6b571588de01d9d812c 100644 (file)
@@ -81,6 +81,31 @@ If you want to have `<input readonly>` elements in your form styled as plain tex
 </form>
 {{< /example >}}
 
+## File input
+
+{{< example >}}
+<div class="mb-3">
+  <label for="formFile" class="form-label">Default file input example</label>
+  <input class="form-control" type="file" id="formFile">
+</div>
+<div class="mb-3">
+  <label for="formFileMultiple" class="form-label">Multiple files input example</label>
+  <input class="form-control" type="file" id="formFileMultiple" multiple>
+</div>
+<div class="mb-3">
+  <label for="formFileDisabled" class="form-label">Disabled file input example</label>
+  <input class="form-control" type="file" id="formFileDisabled" disabled>
+</div>
+<div class="mb-3">
+  <label for="formFileSm" class="form-label">Small file input example</label>
+  <input class="form-control form-control-sm" id="formFileSm" type="file">
+</div>
+<div>
+  <label for="formFileLg" class="form-label">Large file input example</label>
+  <input class="form-control form-control-lg" id="formFileLg" type="file">
+</div>
+{{< /example >}}
+
 ## Color
 
 {{< example >}}
index 83a7f44b9aa1adc427250b84b1798ae95b446146..138d910e8c2fa27f2fdc6c27886273e06abbe017 100644 (file)
@@ -290,45 +290,21 @@ Input groups include support for custom selects and custom file inputs. Browser
 {{< example >}}
 <div class="input-group mb-3">
   <span class="input-group-text" id="inputGroupFileAddon01">Upload</span>
-  <div class="form-file">
-    <input type="file" class="form-file-input" id="inputGroupFile01" aria-describedby="inputGroupFileAddon01">
-    <label class="form-file-label" for="inputGroupFile01">
-      <span class="form-file-text">Choose file...</span>
-      <span class="form-file-button">Browse</span>
-    </label>
-  </div>
+  <input type="file" class="form-control" id="inputGroupFile01" aria-describedby="inputGroupFileAddon01">
 </div>
 
 <div class="input-group mb-3">
-  <div class="form-file">
-    <input type="file" class="form-file-input" id="inputGroupFile02">
-    <label class="form-file-label" for="inputGroupFile02" aria-describedby="inputGroupFileAddon02">
-      <span class="form-file-text">Choose file...</span>
-      <span class="form-file-button">Browse</span>
-    </label>
-  </div>
+  <input type="file" class="form-control" id="inputGroupFile02" aria-describedby="inputGroupFileAddon02">
   <span class="input-group-text" id="inputGroupFileAddon02">Upload</span>
 </div>
 
 <div class="input-group mb-3">
   <button class="btn btn-outline-secondary" type="button" id="inputGroupFileAddon03">Button</button>
-  <div class="form-file">
-    <input type="file" class="form-file-input" id="inputGroupFile03" aria-describedby="inputGroupFileAddon03">
-    <label class="form-file-label" for="inputGroupFile03">
-      <span class="form-file-text">Choose file...</span>
-      <span class="form-file-button">Browse</span>
-    </label>
-  </div>
+  <input type="file" class="form-control" id="inputGroupFile03" aria-describedby="inputGroupFileAddon03">
 </div>
 
 <div class="input-group">
-  <div class="form-file">
-    <input type="file" class="form-file-input" id="inputGroupFile04" aria-describedby="inputGroupFileAddon04">
-    <label class="form-file-label" for="inputGroupFile04">
-      <span class="form-file-text">Choose file...</span>
-      <span class="form-file-button">Browse</span>
-    </label>
-  </div>
+  <input type="file" class="form-control" id="inputGroupFile04" aria-describedby="inputGroupFileAddon04">
   <button class="btn btn-outline-secondary" type="button" id="inputGroupFileAddon04">Button</button>
 </div>
 {{< /example >}}
index 7d30db3570a1f3600970c20707ce1e861393a13c..dcd8e8ccd78b2597168670ca160c11e0d640fd72 100644 (file)
@@ -12,8 +12,6 @@ sections:
     description: Improve browser default select elements with a custom initial appearance.
   - title: Checks & radios
     description: Use our custom radio buttons and checkboxes in forms for selecting input options.
-  - title: File
-    description: Replace browser default file inputs with our custom version with optional JavaScript.
   - title: Range
     description: Replace browser default range inputs with our custom version.
   - title: Input group
index a3fa32689abea0170a6055dfe5a5b3fd1cb6fa14..e01d369b08c0cf4faf98785d692f7ba30e833716 100644 (file)
@@ -241,7 +241,6 @@ Validation styles are available for the following form controls and components:
 - `<input>`s and `<textarea>`s with `.form-control` (including up to one `.form-control` in input groups)
 - `<select>`s with `.form-select`
 - `.form-check`s
-- `.form-file`
 
 {{< example >}}
 <form class="was-validated">
@@ -279,12 +278,8 @@ Validation styles are available for the following form controls and components:
     <div class="invalid-feedback">Example invalid select feedback</div>
   </div>
 
-  <div class="form-file mb-3">
-    <input type="file" class="form-file-input" id="validationFormFile" required>
-    <label class="form-file-label" for="validationFormFile">
-      <span class="form-file-text">Choose file...</span>
-      <span class="form-file-button">Browse</span>
-    </label>
+  <div class="mb-3">
+    <input type="file" class="form-control" aria-label="file example" required>
     <div class="invalid-feedback">Example invalid form file feedback</div>
   </div>
 
index b4eda1130902909cac94c0a17f8f1c7c0add0ed1..ed4070121c8dca4a8b001b2726db2fd4e4b3eb82 100644 (file)
@@ -25,6 +25,7 @@ toc: true
 
 - The longstanding [Missing border radius on input group with validation feedback bug](https://github.com/twbs/bootstrap/issues/25110) is finally fixed by adding an additional `.has-validation` class to input groups with validation.
 - Promoted the Floating labels example to fully supported form component. [See the new Floating labels page.]({{< docsref "/forms/floating-labels" >}})
+- File inputs now use the `.form-control` class and don't require JavaScript, additional HTML, or additional classes. [See #31955](https://github.com/twbs/bootstrap/pull/31955).
 
 ### Utilities
 
@@ -266,7 +267,7 @@ Changes to Reboot, typography, tables, and more.
 - Updated file input component with the same overall design, but improved HTML.
   - Refactored `.form-file` markup to resolve some visual bugs while allowing translation and button text changes via HTML instead of CSS.
   - Dropped native `.form-control-file` and `.form-control-range` components entirely.
-  - Renamed `.custom-file` to `.form-file` (including variables).
+  - Renamed `.custom-file` to `.form-file` (including variables). **Watch out:** `.form-file` was later on dropped in `v5.0.0-alpha3`, now you can use `.form-control`.
   - Added support for `:focus` and `:disabled` styles.
 - Renamed `.custom-range` to `.form-range` (including variables).
 - Dropped `.form-group` for margin utilities (we've replaced our docs examples with `.mb-3`).
index 1e6505c72711138084b84a64c83e3ca0be5bc266..7ee35db95b64da38fbfe508200a7ff7cf1dd0258 100644 (file)
@@ -45,7 +45,6 @@
     - title: Form control
     - title: Select
     - title: Checks & radios
-    - title: File
     - title: Range
     - title: Input group
     - title: Floating labels