From 3ea39841c8049525e31e9f4d6300f0c60cdb42de Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Tue, 24 Jan 2023 13:33:51 +0100 Subject: Adding upstream version 5.2.3+dfsg. Signed-off-by: Daniel Baumann --- scss/forms/_floating-labels.scss | 75 +++++++++++++++ scss/forms/_form-check.scss | 175 +++++++++++++++++++++++++++++++++++ scss/forms/_form-control.scss | 194 +++++++++++++++++++++++++++++++++++++++ scss/forms/_form-range.scss | 91 ++++++++++++++++++ scss/forms/_form-select.scss | 71 ++++++++++++++ scss/forms/_form-text.scss | 11 +++ scss/forms/_input-group.scss | 132 ++++++++++++++++++++++++++ scss/forms/_labels.scss | 36 ++++++++ scss/forms/_validation.scss | 12 +++ 9 files changed, 797 insertions(+) create mode 100644 scss/forms/_floating-labels.scss create mode 100644 scss/forms/_form-check.scss create mode 100644 scss/forms/_form-control.scss create mode 100644 scss/forms/_form-range.scss create mode 100644 scss/forms/_form-select.scss create mode 100644 scss/forms/_form-text.scss create mode 100644 scss/forms/_input-group.scss create mode 100644 scss/forms/_labels.scss create mode 100644 scss/forms/_validation.scss (limited to 'scss/forms') diff --git a/scss/forms/_floating-labels.scss b/scss/forms/_floating-labels.scss new file mode 100644 index 0000000..6e5c9a7 --- /dev/null +++ b/scss/forms/_floating-labels.scss @@ -0,0 +1,75 @@ +.form-floating { + position: relative; + + > .form-control, + > .form-control-plaintext, + > .form-select { + height: $form-floating-height; + line-height: $form-floating-line-height; + } + + > label { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; // allow textareas + padding: $form-floating-padding-y $form-floating-padding-x; + overflow: hidden; + 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); + } + + > .form-control, + > .form-control-plaintext { + padding: $form-floating-padding-y $form-floating-padding-x; + + &::placeholder { + color: transparent; + } + + &:focus, + &:not(:placeholder-shown) { + padding-top: $form-floating-input-padding-t; + padding-bottom: $form-floating-input-padding-b; + } + // Duplicated because `:-webkit-autofill` invalidates other selectors when grouped + &:-webkit-autofill { + padding-top: $form-floating-input-padding-t; + padding-bottom: $form-floating-input-padding-b; + } + } + + > .form-select { + padding-top: $form-floating-input-padding-t; + padding-bottom: $form-floating-input-padding-b; + } + + > .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; + } + } + + > .form-control-plaintext { + ~ label { + border-width: $input-border-width 0; // Required to properly position label text - as explained above + } + } +} diff --git a/scss/forms/_form-check.scss b/scss/forms/_form-check.scss new file mode 100644 index 0000000..42a2a96 --- /dev/null +++ b/scss/forms/_form-check.scss @@ -0,0 +1,175 @@ +// +// Check/radio +// + +.form-check { + display: block; + min-height: $form-check-min-height; + padding-left: $form-check-padding-start; + margin-bottom: $form-check-margin-bottom; + + .form-check-input { + float: left; + margin-left: $form-check-padding-start * -1; + } +} + +.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 { + 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; + background-repeat: no-repeat; + background-position: center; + background-size: contain; + border: $form-check-input-border; + appearance: none; + print-color-adjust: exact; // Keep themed appearance for print + @include transition($form-check-transition); + + &[type="checkbox"] { + @include border-radius($form-check-input-border-radius); + } + + &[type="radio"] { + // stylelint-disable-next-line property-disallowed-list + border-radius: $form-check-radio-border-radius; + } + + &:active { + filter: $form-check-input-active-filter; + } + + &:focus { + border-color: $form-check-input-focus-border; + outline: 0; + box-shadow: $form-check-input-focus-box-shadow; + } + + &:checked { + background-color: $form-check-input-checked-bg-color; + border-color: $form-check-input-checked-border-color; + + &[type="checkbox"] { + @if $enable-gradients { + background-image: escape-svg($form-check-input-checked-bg-image), var(--#{$prefix}gradient); + } @else { + background-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(--#{$prefix}gradient); + } @else { + background-image: escape-svg($form-check-radio-checked-bg-image); + } + } + } + + &[type="checkbox"]:indeterminate { + background-color: $form-check-input-indeterminate-bg-color; + border-color: $form-check-input-indeterminate-border-color; + + @if $enable-gradients { + background-image: escape-svg($form-check-input-indeterminate-bg-image), var(--#{$prefix}gradient); + } @else { + background-image: escape-svg($form-check-input-indeterminate-bg-image); + } + } + + &:disabled { + pointer-events: none; + filter: none; + opacity: $form-check-input-disabled-opacity; + } + + // Use disabled attribute in addition of :disabled pseudo-class + // See: https://github.com/twbs/bootstrap/issues/28247 + &[disabled], + &:disabled { + ~ .form-check-label { + cursor: default; + opacity: $form-check-label-disabled-opacity; + } + } +} + +.form-check-label { + color: $form-check-label-color; + cursor: $form-check-label-cursor; +} + +// +// Switch +// + +.form-switch { + padding-left: $form-switch-padding-start; + + .form-check-input { + width: $form-switch-width; + margin-left: $form-switch-padding-start * -1; + background-image: escape-svg($form-switch-bg-image); + background-position: left center; + @include border-radius($form-switch-border-radius); + @include transition($form-switch-transition); + + &:focus { + background-image: 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(--#{$prefix}gradient); + } @else { + background-image: 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 { + display: inline-block; + margin-right: $form-check-inline-margin-end; +} + +.btn-check { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; + + &[disabled], + &:disabled { + + .btn { + pointer-events: none; + filter: none; + opacity: $form-check-btn-check-disabled-opacity; + } + } +} diff --git a/scss/forms/_form-control.scss b/scss/forms/_form-control.scss new file mode 100644 index 0000000..e707c57 --- /dev/null +++ b/scss/forms/_form-control.scss @@ -0,0 +1,194 @@ +// +// General form controls (plus a few specific high-level interventions) +// + +.form-control { + display: block; + width: 100%; + padding: $input-padding-y $input-padding-x; + font-family: $input-font-family; + @include font-size($input-font-size); + font-weight: $input-font-weight; + line-height: $input-line-height; + color: $input-color; + 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 `s in CSS. + @include border-radius($input-border-radius, 0); + + @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; + background-color: $input-focus-bg; + border-color: $input-focus-border-color; + outline: 0; + @if $enable-shadows { + @include box-shadow($input-box-shadow, $input-focus-box-shadow); + } @else { + // Avoid using mixin so we can pass custom focus shadow properly + box-shadow: $input-focus-box-shadow; + } + } + + // 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 { + // Multiply line-height by 1em if it has no unit + height: if(unit($input-line-height) == "", $input-line-height * 1em, $input-line-height); + } + + // Placeholder + &::placeholder { + color: $input-placeholder-color; + // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526. + opacity: 1; + } + + // 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 { + 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. + opacity: 1; + } + + // File input buttons theming + &::file-selector-button { + padding: $input-padding-y $input-padding-x; + margin: (-$input-padding-y) (-$input-padding-x); + margin-inline-end: $input-padding-x; + 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])::file-selector-button { + background-color: $form-file-button-hover-bg; + } +} + +// Readonly controls as plain text +// +// Apply class to a readonly input to make it appear like regular plain +// text (without any border, background color, focus indicator) + +.form-control-plaintext { + display: block; + width: 100%; + padding: $input-padding-y 0; + margin-bottom: 0; // match inputs if this class comes on inputs with default margins + line-height: $input-line-height; + color: $input-plaintext-color; + background-color: transparent; + border: solid transparent; + border-width: $input-border-width 0; + + &:focus { + outline: 0; + } + + &.form-control-sm, + &.form-control-lg { + padding-right: 0; + padding-left: 0; + } +} + +// Form control sizing +// +// Build on `.form-control` with modifier classes to decrease or increase the +// height and font-size of form controls. +// +// Repeated in `_input_group.scss` to avoid Sass extend issues. + +.form-control-sm { + min-height: $input-height-sm; + padding: $input-padding-y-sm $input-padding-x-sm; + @include font-size($input-font-size-sm); + @include border-radius($input-border-radius-sm); + + &::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; + } +} + +.form-control-lg { + min-height: $input-height-lg; + padding: $input-padding-y-lg $input-padding-x-lg; + @include font-size($input-font-size-lg); + @include border-radius($input-border-radius-lg); + + &::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; + } +} + +// Make sure textareas don't shrink too much when resized +// https://github.com/twbs/bootstrap/pull/29124 +// stylelint-disable selector-no-qualifying-type +textarea { + &.form-control { + min-height: $input-height; + } + + &.form-control-sm { + min-height: $input-height-sm; + } + + &.form-control-lg { + min-height: $input-height-lg; + } +} +// stylelint-enable selector-no-qualifying-type + +.form-control-color { + width: $form-color-width; + height: $input-height; + padding: $input-padding-y; + + &:not(:disabled):not([readonly]) { + cursor: pointer; + } + + &::-moz-color-swatch { + border: 0 !important; // stylelint-disable-line declaration-no-important + @include border-radius($input-border-radius); + } + + &::-webkit-color-swatch { + @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 new file mode 100644 index 0000000..6de4213 --- /dev/null +++ b/scss/forms/_form-range.scss @@ -0,0 +1,91 @@ +// Range +// +// Style range inputs the same across browsers. Vendor-specific rules for pseudo +// elements cannot be mixed. As such, there are no shared styles for focus or +// active states on prefixed selectors. + +.form-range { + 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; + + &:focus { + outline: 0; + + // Pseudo-elements must be split across multiple rulesets to have an effect. + // No box-shadow() mixin for focus accessibility. + &::-webkit-slider-thumb { box-shadow: $form-range-thumb-focus-box-shadow; } + &::-moz-range-thumb { box-shadow: $form-range-thumb-focus-box-shadow; } + } + + &::-moz-focus-outer { + border: 0; + } + + &::-webkit-slider-thumb { + width: $form-range-thumb-width; + height: $form-range-thumb-height; + margin-top: ($form-range-track-height - $form-range-thumb-height) * .5; // Webkit specific + @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); + } + } + + &::-webkit-slider-runnable-track { + width: $form-range-track-width; + height: $form-range-track-height; + color: transparent; // Why? + cursor: $form-range-track-cursor; + background-color: $form-range-track-bg; + border-color: transparent; + @include border-radius($form-range-track-border-radius); + @include box-shadow($form-range-track-box-shadow); + } + + &::-moz-range-thumb { + width: $form-range-thumb-width; + height: $form-range-thumb-height; + @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); + } + } + + &::-moz-range-track { + width: $form-range-track-width; + height: $form-range-track-height; + color: transparent; + cursor: $form-range-track-cursor; + background-color: $form-range-track-bg; + border-color: transparent; // Firefox specific? + @include border-radius($form-range-track-border-radius); + @include box-shadow($form-range-track-box-shadow); + } + + &:disabled { + pointer-events: none; + + &::-webkit-slider-thumb { + background-color: $form-range-thumb-disabled-bg; + } + + &::-moz-range-thumb { + background-color: $form-range-thumb-disabled-bg; + } + } +} diff --git a/scss/forms/_form-select.scss b/scss/forms/_form-select.scss new file mode 100644 index 0000000..78c34b8 --- /dev/null +++ b/scss/forms/_form-select.scss @@ -0,0 +1,71 @@ +// Select +// +// Replaces the browser default select with a custom one, mostly pulled from +// https://primer.github.io/. + +.form-select { + display: block; + width: 100%; + padding: $form-select-padding-y $form-select-indicator-padding $form-select-padding-y $form-select-padding-x; + -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; + background-color: $form-select-bg; + background-image: escape-svg($form-select-indicator); + background-repeat: no-repeat; + background-position: $form-select-bg-position; + background-size: $form-select-bg-size; + border: $form-select-border-width solid $form-select-border-color; + @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; + outline: 0; + @if $enable-shadows { + @include box-shadow($form-select-box-shadow, $form-select-focus-box-shadow); + } @else { + // Avoid using mixin so we can pass custom focus shadow properly + box-shadow: $form-select-focus-box-shadow; + } + } + + &[multiple], + &[size]:not([size="1"]) { + padding-right: $form-select-padding-x; + background-image: none; + } + + &:disabled { + color: $form-select-disabled-color; + background-color: $form-select-disabled-bg; + border-color: $form-select-disabled-border-color; + } + + // Remove outline from select box in FF + &:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 $form-select-color; + } +} + +.form-select-sm { + padding-top: $form-select-padding-y-sm; + padding-bottom: $form-select-padding-y-sm; + padding-left: $form-select-padding-x-sm; + @include font-size($form-select-font-size-sm); + @include border-radius($form-select-border-radius-sm); +} + +.form-select-lg { + padding-top: $form-select-padding-y-lg; + padding-bottom: $form-select-padding-y-lg; + padding-left: $form-select-padding-x-lg; + @include font-size($form-select-font-size-lg); + @include border-radius($form-select-border-radius-lg); +} diff --git a/scss/forms/_form-text.scss b/scss/forms/_form-text.scss new file mode 100644 index 0000000..f080d1a --- /dev/null +++ b/scss/forms/_form-text.scss @@ -0,0 +1,11 @@ +// +// Form text +// + +.form-text { + margin-top: $form-text-margin-top; + @include font-size($form-text-font-size); + font-style: $form-text-font-style; + font-weight: $form-text-font-weight; + color: $form-text-color; +} diff --git a/scss/forms/_input-group.scss b/scss/forms/_input-group.scss new file mode 100644 index 0000000..247f74a --- /dev/null +++ b/scss/forms/_input-group.scss @@ -0,0 +1,132 @@ +// +// Base styles +// + +.input-group { + position: relative; + display: flex; + flex-wrap: wrap; // For form validation feedback + align-items: stretch; + width: 100%; + + > .form-control, + > .form-select, + > .form-floating { + position: relative; // For focus state's z-index + flex: 1 1 auto; + width: 1%; + min-width: 0; // https://stackoverflow.com/questions/36247140/why-dont-flex-items-shrink-past-content-size + } + + // Bring the "active" form control to the top of surrounding elements + > .form-control:focus, + > .form-select:focus, + > .form-floating:focus-within { + z-index: 5; + } + + // 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. + .btn { + position: relative; + z-index: 2; + + &:focus { + z-index: 5; + } + } +} + + +// Textual addons +// +// Serves as a catch-all element for any text or radio/checkbox input you wish +// to prepend or append to an input. + +.input-group-text { + display: flex; + align-items: center; + padding: $input-group-addon-padding-y $input-group-addon-padding-x; + @include font-size($input-font-size); // Match inputs + font-weight: $input-group-addon-font-weight; + line-height: $input-line-height; + color: $input-group-addon-color; + text-align: center; + white-space: nowrap; + background-color: $input-group-addon-bg; + border: $input-border-width solid $input-group-addon-border-color; + @include border-radius($input-border-radius); +} + + +// Sizing +// +// Remix the default form control sizing classes into new ones for easier +// manipulation. + +.input-group-lg > .form-control, +.input-group-lg > .form-select, +.input-group-lg > .input-group-text, +.input-group-lg > .btn { + padding: $input-padding-y-lg $input-padding-x-lg; + @include font-size($input-font-size-lg); + @include border-radius($input-border-radius-lg); +} + +.input-group-sm > .form-control, +.input-group-sm > .form-select, +.input-group-sm > .input-group-text, +.input-group-sm > .btn { + padding: $input-padding-y-sm $input-padding-x-sm; + @include font-size($input-font-size-sm); + @include border-radius($input-border-radius-sm); +} + +.input-group-lg > .form-select, +.input-group-sm > .form-select { + padding-right: $form-select-padding-x + $form-select-indicator-padding; +} + + +// Rounded corners +// +// These rulesets must come after the sizing ones to properly override sm and lg +// border-radius values when extending. They're more specific than we'd like +// with the `.input-group >` part, but without it, we cannot override the sizing. + +// stylelint-disable-next-line no-duplicate-selectors +.input-group { + &:not(.has-validation) { + > :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):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); + } + } + + $validation-messages: ""; + @each $state in map-keys($form-validation-states) { + $validation-messages: $validation-messages + ":not(." + unquote($state) + "-tooltip)" + ":not(." + unquote($state) + "-feedback)"; + } + + > :not(:first-child):not(.dropdown-menu)#{$validation-messages} { + margin-left: -$input-border-width; + @include border-start-radius(0); + } + + > .form-floating:not(:first-child) > .form-control, + > .form-floating:not(:first-child) > .form-select { + @include border-start-radius(0); + } +} diff --git a/scss/forms/_labels.scss b/scss/forms/_labels.scss new file mode 100644 index 0000000..39ecafc --- /dev/null +++ b/scss/forms/_labels.scss @@ -0,0 +1,36 @@ +// +// Labels +// + +.form-label { + margin-bottom: $form-label-margin-bottom; + @include font-size($form-label-font-size); + font-style: $form-label-font-style; + font-weight: $form-label-font-weight; + color: $form-label-color; +} + +// For use with horizontal and inline forms, when you need the label (or legend) +// text to align with the form controls. +.col-form-label { + padding-top: add($input-padding-y, $input-border-width); + padding-bottom: add($input-padding-y, $input-border-width); + margin-bottom: 0; // Override the `` default + @include font-size(inherit); // Override the `` default + font-style: $form-label-font-style; + font-weight: $form-label-font-weight; + line-height: $input-line-height; + color: $form-label-color; +} + +.col-form-label-lg { + padding-top: add($input-padding-y-lg, $input-border-width); + padding-bottom: add($input-padding-y-lg, $input-border-width); + @include font-size($input-font-size-lg); +} + +.col-form-label-sm { + padding-top: add($input-padding-y-sm, $input-border-width); + padding-bottom: add($input-padding-y-sm, $input-border-width); + @include font-size($input-font-size-sm); +} diff --git a/scss/forms/_validation.scss b/scss/forms/_validation.scss new file mode 100644 index 0000000..c48123a --- /dev/null +++ b/scss/forms/_validation.scss @@ -0,0 +1,12 @@ +// Form validation +// +// Provide feedback to users when form field values are valid or invalid. Works +// primarily for client-side validation via scoped `:invalid` and `:valid` +// pseudo-classes but also includes `.is-invalid` and `.is-valid` classes for +// server-side validation. + +// scss-docs-start form-validation-states-loop +@each $state, $data in $form-validation-states { + @include form-validation-state($state, $data...); +} +// scss-docs-end form-validation-states-loop -- cgit v1.2.3