diff options
| author | Bobby <[email protected]> | 2024-08-16 20:47:33 -0400 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-08-16 20:47:33 -0400 |
| commit | 6b28433d9cfde435be8ec2bd6cf91e6324d08865 (patch) | |
| tree | 8343c27b8b95ff5639233e81cf157f92e5688466 /scss/forms | |
| parent | d53094ec16ba385faae2973ddee648698b32ab24 (diff) | |
| parent | 048f56f51460df75e92a2f7b472e1c56baeb68f7 (diff) | |
| download | bootstrap-main.tar.xz bootstrap-main.zip | |
Diffstat (limited to 'scss/forms')
| -rw-r--r-- | scss/forms/_floating-labels.scss | 43 | ||||
| -rw-r--r-- | scss/forms/_form-check.scss | 65 | ||||
| -rw-r--r-- | scss/forms/_form-control.scss | 46 | ||||
| -rw-r--r-- | scss/forms/_form-range.scss | 6 | ||||
| -rw-r--r-- | scss/forms/_form-select.scss | 16 | ||||
| -rw-r--r-- | scss/forms/_input-group.scss | 29 |
6 files changed, 160 insertions, 45 deletions
diff --git a/scss/forms/_floating-labels.scss b/scss/forms/_floating-labels.scss index 2f4295480..b36650588 100644 --- a/scss/forms/_floating-labels.scss +++ b/scss/forms/_floating-labels.scss @@ -2,8 +2,10 @@ position: relative; > .form-control, + > .form-control-plaintext, > .form-select { height: $form-floating-height; + min-height: $form-floating-height; line-height: $form-floating-line-height; } @@ -11,16 +13,23 @@ position: absolute; top: 0; left: 0; + z-index: 2; + max-width: 100%; height: 100%; // allow textareas padding: $form-floating-padding-y $form-floating-padding-x; + overflow: hidden; + color: rgba(var(--#{$prefix}body-color-rgb), #{$form-floating-label-opacity}); + text-align: start; + text-overflow: ellipsis; + white-space: nowrap; pointer-events: none; border: $input-border-width solid transparent; // Required for aligning label's text with the input as it affects inner box model transform-origin: 0 0; @include transition($form-floating-transition); } - // stylelint-disable no-duplicate-selectors - > .form-control { + > .form-control, + > .form-control-plaintext { padding: $form-floating-padding-y $form-floating-padding-x; &::placeholder { @@ -46,18 +55,42 @@ > .form-control:focus, > .form-control:not(:placeholder-shown), + > .form-control-plaintext, > .form-select { ~ label { - opacity: $form-floating-label-opacity; transform: $form-floating-label-transform; } } // Duplicated because `:-webkit-autofill` invalidates other selectors when grouped > .form-control:-webkit-autofill { ~ label { - opacity: $form-floating-label-opacity; transform: $form-floating-label-transform; } } - // stylelint-enable no-duplicate-selectors + > textarea:focus, + > textarea:not(:placeholder-shown) { + ~ label::after { + position: absolute; + inset: $form-floating-padding-y ($form-floating-padding-x * .5); + z-index: -1; + height: $form-floating-label-height; + content: ""; + background-color: $input-bg; + @include border-radius($input-border-radius); + } + } + > textarea:disabled ~ label::after { + background-color: $input-disabled-bg; + } + + > .form-control-plaintext { + ~ label { + border-width: $input-border-width 0; // Required to properly position label text - as explained above + } + } + + > :disabled ~ label, + > .form-control:disabled ~ label { // Required for `.form-control`s because of specificity + color: $form-floating-label-disabled-color; + } } diff --git a/scss/forms/_form-check.scss b/scss/forms/_form-check.scss index 6321b4100..8a1b639df 100644 --- a/scss/forms/_form-check.scss +++ b/scss/forms/_form-check.scss @@ -14,18 +14,34 @@ } } +.form-check-reverse { + padding-right: $form-check-padding-start; + padding-left: 0; + text-align: right; + + .form-check-input { + float: right; + margin-right: $form-check-padding-start * -1; + margin-left: 0; + } +} + .form-check-input { + --#{$prefix}form-check-bg: #{$form-check-input-bg}; + + flex-shrink: 0; width: $form-check-input-width; height: $form-check-input-width; margin-top: ($line-height-base - $form-check-input-width) * .5; // line-height minus check height vertical-align: top; - background-color: $form-check-input-bg; + appearance: none; + background-color: var(--#{$prefix}form-check-bg); + background-image: var(--#{$prefix}form-check-bg-image); background-repeat: no-repeat; background-position: center; background-size: contain; border: $form-check-input-border; - appearance: none; - color-adjust: exact; // Keep themed appearance for print + print-color-adjust: exact; // Keep themed appearance for print @include transition($form-check-transition); &[type="checkbox"] { @@ -53,17 +69,17 @@ &[type="checkbox"] { @if $enable-gradients { - background-image: escape-svg($form-check-input-checked-bg-image), var(--#{$variable-prefix}gradient); + --#{$prefix}form-check-bg-image: #{escape-svg($form-check-input-checked-bg-image)}, var(--#{$prefix}gradient); } @else { - background-image: escape-svg($form-check-input-checked-bg-image); + --#{$prefix}form-check-bg-image: #{escape-svg($form-check-input-checked-bg-image)}; } } &[type="radio"] { @if $enable-gradients { - background-image: escape-svg($form-check-radio-checked-bg-image), var(--#{$variable-prefix}gradient); + --#{$prefix}form-check-bg-image: #{escape-svg($form-check-radio-checked-bg-image)}, var(--#{$prefix}gradient); } @else { - background-image: escape-svg($form-check-radio-checked-bg-image); + --#{$prefix}form-check-bg-image: #{escape-svg($form-check-radio-checked-bg-image)}; } } } @@ -73,9 +89,9 @@ border-color: $form-check-input-indeterminate-border-color; @if $enable-gradients { - background-image: escape-svg($form-check-input-indeterminate-bg-image), var(--#{$variable-prefix}gradient); + --#{$prefix}form-check-bg-image: #{escape-svg($form-check-input-indeterminate-bg-image)}, var(--#{$prefix}gradient); } @else { - background-image: escape-svg($form-check-input-indeterminate-bg-image); + --#{$prefix}form-check-bg-image: #{escape-svg($form-check-input-indeterminate-bg-image)}; } } @@ -90,6 +106,7 @@ &[disabled], &:disabled { ~ .form-check-label { + cursor: default; opacity: $form-check-label-disabled-opacity; } } @@ -108,27 +125,39 @@ padding-left: $form-switch-padding-start; .form-check-input { + --#{$prefix}form-switch-bg: #{escape-svg($form-switch-bg-image)}; + width: $form-switch-width; margin-left: $form-switch-padding-start * -1; - background-image: escape-svg($form-switch-bg-image); + background-image: var(--#{$prefix}form-switch-bg); background-position: left center; - @include border-radius($form-switch-border-radius); + @include border-radius($form-switch-border-radius, 0); @include transition($form-switch-transition); &:focus { - background-image: escape-svg($form-switch-focus-bg-image); + --#{$prefix}form-switch-bg: #{escape-svg($form-switch-focus-bg-image)}; } &:checked { background-position: $form-switch-checked-bg-position; @if $enable-gradients { - background-image: escape-svg($form-switch-checked-bg-image), var(--#{$variable-prefix}gradient); + --#{$prefix}form-switch-bg: #{escape-svg($form-switch-checked-bg-image)}, var(--#{$prefix}gradient); } @else { - background-image: escape-svg($form-switch-checked-bg-image); + --#{$prefix}form-switch-bg: #{escape-svg($form-switch-checked-bg-image)}; } } } + + &.form-check-reverse { + padding-right: $form-switch-padding-start; + padding-left: 0; + + .form-check-input { + margin-right: $form-switch-padding-start * -1; + margin-left: 0; + } + } } .form-check-inline { @@ -150,3 +179,11 @@ } } } + +@if $enable-dark-mode { + @include color-mode(dark) { + .form-switch .form-check-input:not(:checked):not(:focus) { + --#{$prefix}form-switch-bg: #{escape-svg($form-switch-bg-image-dark)}; + } + } +} diff --git a/scss/forms/_form-control.scss b/scss/forms/_form-control.scss index 51b3baa83..67ae5f4f9 100644 --- a/scss/forms/_form-control.scss +++ b/scss/forms/_form-control.scss @@ -11,10 +11,10 @@ font-weight: $input-font-weight; line-height: $input-line-height; color: $input-color; + appearance: none; // Fix appearance for date inputs in Safari background-color: $input-bg; background-clip: padding-box; border: $input-border-width solid $input-border-color; - appearance: none; // Fix appearance for date inputs in Safari // Note: This has no effect on <select>s in some browsers, due to the limited stylability of `<select>`s in CSS. @include border-radius($input-border-radius, 0); @@ -44,12 +44,31 @@ } } - // Add some height to date inputs on iOS - // https://github.com/twbs/bootstrap/issues/23307 - // TODO: we can remove this workaround once https://bugs.webkit.org/show_bug.cgi?id=198959 is resolved &::-webkit-date-and-time-value { + // On Android Chrome, form-control's "width: 100%" makes the input width too small + // Tested under Android 11 / Chrome 89, Android 12 / Chrome 100, Android 13 / Chrome 109 + // + // On iOS Safari, form-control's "appearance: none" + "width: 100%" makes the input width too small + // Tested under iOS 16.2 / Safari 16.2 + min-width: 85px; // Seems to be a good minimum safe width + + // Add some height to date inputs on iOS + // https://github.com/twbs/bootstrap/issues/23307 + // TODO: we can remove this workaround once https://bugs.webkit.org/show_bug.cgi?id=198959 is resolved // Multiply line-height by 1em if it has no unit height: if(unit($input-line-height) == "", $input-line-height * 1em, $input-line-height); + + // Android Chrome type="date" is taller than the other inputs + // because of "margin: 1px 24px 1px 4px" inside the shadow DOM + // Tested under Android 11 / Chrome 89, Android 12 / Chrome 100, Android 13 / Chrome 109 + margin: 0; + } + + // Prevent excessive date input height in Webkit + // https://github.com/twbs/bootstrap/issues/34433 + &::-webkit-datetime-edit { + display: block; + padding: 0; } // Placeholder @@ -59,13 +78,13 @@ opacity: 1; } - // Disabled and read-only inputs + // Disabled inputs // // HTML5 says that controls under a fieldset > legend:first-child won't be // disabled if the fieldset is disabled. Due to implementation difficulty, we // don't honor that edge case; we style them as disabled anyway. - &:disabled, - &[readonly] { + &:disabled { + color: $input-disabled-color; background-color: $input-disabled-bg; border-color: $input-disabled-border-color; // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655. @@ -109,6 +128,10 @@ border: solid transparent; border-width: $input-border-width 0; + &:focus { + outline: 0; + } + &.form-control-sm, &.form-control-lg { padding-right: 0; @@ -169,7 +192,7 @@ textarea { .form-control-color { width: $form-color-width; - height: auto; // Override fixed browser height + height: $input-height; padding: $input-padding-y; &:not(:disabled):not([readonly]) { @@ -177,12 +200,15 @@ textarea { } &::-moz-color-swatch { - height: if(unit($input-line-height) == "", $input-line-height * 1em, $input-line-height); + border: 0 !important; // stylelint-disable-line declaration-no-important @include border-radius($input-border-radius); } &::-webkit-color-swatch { - height: if(unit($input-line-height) == "", $input-line-height * 1em, $input-line-height); + border: 0 !important; // stylelint-disable-line declaration-no-important @include border-radius($input-border-radius); } + + &.form-control-sm { height: $input-height-sm; } + &.form-control-lg { height: $input-height-lg; } } diff --git a/scss/forms/_form-range.scss b/scss/forms/_form-range.scss index 6de42132e..4732213e9 100644 --- a/scss/forms/_form-range.scss +++ b/scss/forms/_form-range.scss @@ -8,8 +8,8 @@ width: 100%; height: add($form-range-thumb-height, $form-range-thumb-focus-box-shadow-width * 2); padding: 0; // Need to reset padding - background-color: transparent; appearance: none; + background-color: transparent; &:focus { outline: 0; @@ -28,12 +28,12 @@ width: $form-range-thumb-width; height: $form-range-thumb-height; margin-top: ($form-range-track-height - $form-range-thumb-height) * .5; // Webkit specific + appearance: none; @include gradient-bg($form-range-thumb-bg); border: $form-range-thumb-border; @include border-radius($form-range-thumb-border-radius); @include box-shadow($form-range-thumb-box-shadow); @include transition($form-range-thumb-transition); - appearance: none; &:active { @include gradient-bg($form-range-thumb-active-bg); @@ -54,12 +54,12 @@ &::-moz-range-thumb { width: $form-range-thumb-width; height: $form-range-thumb-height; + appearance: none; @include gradient-bg($form-range-thumb-bg); border: $form-range-thumb-border; @include border-radius($form-range-thumb-border-radius); @include box-shadow($form-range-thumb-box-shadow); @include transition($form-range-thumb-transition); - appearance: none; &:active { @include gradient-bg($form-range-thumb-active-bg); diff --git a/scss/forms/_form-select.scss b/scss/forms/_form-select.scss index 153ff6cd5..69ace529d 100644 --- a/scss/forms/_form-select.scss +++ b/scss/forms/_form-select.scss @@ -4,18 +4,19 @@ // https://primer.github.io/. .form-select { + --#{$prefix}form-select-bg-img: #{escape-svg($form-select-indicator)}; + display: block; width: 100%; padding: $form-select-padding-y $form-select-indicator-padding $form-select-padding-y $form-select-padding-x; - // stylelint-disable-next-line property-no-vendor-prefix - -moz-padding-start: subtract($form-select-padding-x, 3px); // See https://github.com/twbs/bootstrap/issues/32636 font-family: $form-select-font-family; @include font-size($form-select-font-size); font-weight: $form-select-font-weight; line-height: $form-select-line-height; color: $form-select-color; + appearance: none; background-color: $form-select-bg; - background-image: escape-svg($form-select-indicator); + background-image: var(--#{$prefix}form-select-bg-img), var(--#{$prefix}form-select-bg-icon, none); background-repeat: no-repeat; background-position: $form-select-bg-position; background-size: $form-select-bg-size; @@ -23,7 +24,6 @@ @include border-radius($form-select-border-radius, 0); @include box-shadow($form-select-box-shadow); @include transition($form-select-transition); - appearance: none; &:focus { border-color: $form-select-focus-border-color; @@ -70,3 +70,11 @@ @include font-size($form-select-font-size-lg); @include border-radius($form-select-border-radius-lg); } + +@if $enable-dark-mode { + @include color-mode(dark) { + .form-select { + --#{$prefix}form-select-bg-img: #{escape-svg($form-select-indicator-dark)}; + } + } +} diff --git a/scss/forms/_input-group.scss b/scss/forms/_input-group.scss index 140052936..58e4d409c 100644 --- a/scss/forms/_input-group.scss +++ b/scss/forms/_input-group.scss @@ -10,7 +10,8 @@ width: 100%; > .form-control, - > .form-select { + > .form-select, + > .form-floating { position: relative; // For focus state's z-index flex: 1 1 auto; width: 1%; @@ -19,8 +20,9 @@ // Bring the "active" form control to the top of surrounding elements > .form-control:focus, - > .form-select:focus { - z-index: 3; + > .form-select:focus, + > .form-floating:focus-within { + z-index: 5; } // Ensure buttons are always above inputs for more visually pleasing borders. @@ -31,7 +33,7 @@ z-index: 2; &:focus { - z-index: 3; + z-index: 5; } } } @@ -96,15 +98,19 @@ // stylelint-disable-next-line no-duplicate-selectors .input-group { &:not(.has-validation) { - > :not(:last-child):not(.dropdown-toggle):not(.dropdown-menu), - > .dropdown-toggle:nth-last-child(n + 3) { + > :not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating), + > .dropdown-toggle:nth-last-child(n + 3), + > .form-floating:not(:last-child) > .form-control, + > .form-floating:not(:last-child) > .form-select { @include border-end-radius(0); } } &.has-validation { - > :nth-last-child(n + 3):not(.dropdown-toggle):not(.dropdown-menu), - > .dropdown-toggle:nth-last-child(n + 4) { + > :nth-last-child(n + 3):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating), + > .dropdown-toggle:nth-last-child(n + 4), + > .form-floating:nth-last-child(n + 3) > .form-control, + > .form-floating:nth-last-child(n + 3) > .form-select { @include border-end-radius(0); } } @@ -115,7 +121,12 @@ } > :not(:first-child):not(.dropdown-menu)#{$validation-messages} { - margin-left: -$input-border-width; + margin-left: calc(#{$input-border-width} * -1); // stylelint-disable-line function-disallowed-list + @include border-start-radius(0); + } + + > .form-floating:not(:first-child) > .form-control, + > .form-floating:not(:first-child) > .form-select { @include border-start-radius(0); } } |
