diff --git a/.bundlewatch.config.json b/.bundlewatch.config.json index 0177b5f615..7d0f30525e 100644 --- a/.bundlewatch.config.json +++ b/.bundlewatch.config.json @@ -26,11 +26,11 @@ }, { "path": "./dist/css/bootstrap.css", - "maxSize": "35.75 kB" + "maxSize": "36.0 kB" }, { "path": "./dist/css/bootstrap.min.css", - "maxSize": "31.5 kB" + "maxSize": "32.0 kB" }, { "path": "./dist/js/bootstrap.bundle.js", diff --git a/.cspell.json b/.cspell.json index 191c9bc05c..872c34b23c 100644 --- a/.cspell.json +++ b/.cspell.json @@ -21,6 +21,7 @@ "callout", "callouts", "camelCase", + "checkgroup", "clearfix", "Codesniffer", "combinator", diff --git a/scss/_root.scss b/scss/_root.scss index 241147aa65..478114f95a 100644 --- a/scss/_root.scss +++ b/scss/_root.scss @@ -91,6 +91,11 @@ --#{$prefix}root-font-size: #{$font-size-root}; } --#{$prefix}body-font-family: #{meta.inspect($font-family-base)}; + + --#{$prefix}font-size-base: #{$font-size-base}; // 14px + --#{$prefix}font-size-sm: calc(#{$font-size-base} * .9285); + --#{$prefix}font-size-lg: calc(#{$font-size-base} * 1.285); + @include rfs($font-size-base, --#{$prefix}body-font-size); --#{$prefix}body-font-weight: #{$font-weight-base}; --#{$prefix}body-line-height: #{$line-height-base}; @@ -237,7 +242,7 @@ --#{$prefix}link-color-rgb: #{to-rgb($link-color-dark)}; --#{$prefix}link-hover-color-rgb: #{to-rgb($link-hover-color-dark)}; - --#{$prefix}code-color: #{$code-color-dark}; + // --#{$prefix}code-color: #{$code-color-dark}; // removed in v6 --#{$prefix}highlight-color: #{$mark-color-dark}; --#{$prefix}highlight-bg: #{$mark-bg-dark}; diff --git a/scss/_variables.scss b/scss/_variables.scss index a0ed0d40a2..a2a2024159 100644 --- a/scss/_variables.scss +++ b/scss/_variables.scss @@ -10,7 +10,7 @@ // consistent naming. Ex: $nav-link-disabled-color and $modal-content-box-shadow-xs. // scss-docs-start theme-color-variables -$primary: $purple-500 !default; +$primary: $blue-500 !default; $secondary: $gray-600 !default; $success: $green-500 !default; $info: $cyan-500 !default; @@ -167,6 +167,7 @@ $body-emphasis-color: $black !default; $link-color: $primary !default; $link-decoration: underline !default; +$link-underline-offset: .2em !default; $link-shade-percentage: 20% !default; $link-hover-color: shift-color($link-color, $link-shade-percentage) !default; $link-hover-decoration: null !default; @@ -204,7 +205,7 @@ $border-widths: ( 5: 5px ) !default; $border-style: solid !default; -$border-color: $gray-300 !default; +$border-color: color.mix($gray-300, $gray-400) !default; $border-color-translucent: rgba($black, .175) !default; // scss-docs-end border-variables @@ -266,8 +267,8 @@ $font-family-code: var(--#{$prefix}font-monospace) !default; // $font-size-root affects the value of `rem`, which is used for as well font sizes, paddings, and margins // $font-size-base affects the font size of the body text -$font-size-root: null !default; -$font-size-base: 1rem !default; // Assumes the browser default, typically `16px` +$font-size-root: 16px !default; +$font-size-base: 14px !default; // Assumes the browser default, typically `16px` $font-size-sm: $font-size-base * .875 !default; $font-size-lg: $font-size-base * 1.25 !default; @@ -546,8 +547,8 @@ $offcanvas-backdrop-opacity: $modal-backdrop-opacity !default; // Code -$code-font-size: $small-font-size !default; -$code-color: $pink !default; +$code-font-size: 95% !default; +$code-color: var(--#{$prefix}secondary-text) !default; $kbd-padding-y: .1875rem !default; $kbd-padding-x: .375rem !default; @@ -578,7 +579,7 @@ $border-color-translucent-dark: rgba($white, .15) !default; $headings-color-dark: inherit !default; $link-color-dark: tint-color($primary, 40%) !default; $link-hover-color-dark: shift-color($link-color-dark, -$link-shade-percentage) !default; -$code-color-dark: tint-color($code-color, 40%) !default; +// $code-color-dark: tint-color($code-color, 40%) !default; $mark-color-dark: $body-color-dark !default; $mark-bg-dark: $yellow-800 !default; @@ -587,12 +588,6 @@ $mark-bg-dark: $yellow-800 !default; // Forms // -$form-select-indicator-color-dark: $body-color-dark !default; -$form-select-indicator-dark: url("data:image/svg+xml,") !default; - -$form-switch-color-dark: rgba($white, .25) !default; -$form-switch-bg-image-dark: url("data:image/svg+xml,") !default; - // scss-docs-start form-validation-colors-dark $form-valid-color-dark: $green-300 !default; $form-valid-border-color-dark: $green-300 !default; diff --git a/scss/buttons/_button.scss b/scss/buttons/_button.scss index 2bbe49459f..c5f2da5597 100644 --- a/scss/buttons/_button.scss +++ b/scss/buttons/_button.scss @@ -279,4 +279,19 @@ .btn-sm { @include button-size($btn-padding-y-sm, $btn-padding-x-sm, $btn-font-size-sm, $btn-border-radius-sm); } + + .btn-check { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; + + &[disabled], + &:disabled { + + .btn { + pointer-events: none; + filter: none; + opacity: .65; + } + } + } } diff --git a/scss/content/_reboot.scss b/scss/content/_reboot.scss index 47bd8321fe..313837b3d5 100644 --- a/scss/content/_reboot.scss +++ b/scss/content/_reboot.scss @@ -33,7 +33,8 @@ :root { @if $font-size-root != null { - @include font-size(var(--#{$prefix}root-font-size)); + font-size: var(--#{$prefix}root-font-size); + // @include font-size(var(--#{$prefix}root-font-size)); } @if $enable-smooth-scroll { @@ -256,12 +257,13 @@ // Links a { - color: rgba(var(--#{$prefix}link-color-rgb), var(--#{$prefix}link-opacity, 1)); - text-decoration: $link-decoration; + color: var(--#{$prefix}link-color); + text-decoration: var(--#{$prefix}link-decoration); + text-underline-offset: $link-underline-offset; &:hover { - --#{$prefix}link-color-rgb: var(--#{$prefix}link-hover-color-rgb); - text-decoration: $link-hover-decoration; + color: var(--#{$prefix}link-hover-color); + text-decoration: var(--#{$prefix}link-hover-decoration); } } diff --git a/scss/forms/_check.scss b/scss/forms/_check.scss new file mode 100644 index 0000000000..bc88beaf38 --- /dev/null +++ b/scss/forms/_check.scss @@ -0,0 +1,102 @@ +@use "../config" as *; +@use "../colors" as *; +@use "../variables" as *; +@use "../functions" as *; +@use "../vendor/rfs" as *; +@use "../mixins/border-radius" as *; +@use "../mixins/box-shadow" as *; +@use "../mixins/color-mode" as *; +@use "../mixins/focus-ring" as *; +@use "../mixins/transition" as *; +@use "form-variables" as *; + +// scss-docs-start check-variables +$check-border-color: var(--#{$prefix}border-color) !default; +$check-checked-bg: var(--#{$prefix}primary-base) !default; +$check-checked-border-color: $check-checked-bg !default; +$check-indeterminate-bg: var(--#{$prefix}primary-base) !default; +$check-indeterminate-border-color: $check-indeterminate-bg !default; +$check-disabled-bg: var(--#{$prefix}secondary-bg) !default; +$check-disabled-border-color: $check-disabled-bg !default; +$check-disabled-opacity: .65 !default; +// scss-docs-end check-variables + +@layer forms { + b-checkgroup { + display: flex; + gap: var(--#{$prefix}gap, .5rem); + align-items: var(--#{$prefix}align-items, start); + + .description { + color: var(--#{$prefix}secondary-text); + } + } + + .check { + // scss-docs-start check-css-variables + --#{$prefix}check-bg: transparent; + --#{$prefix}check-border-color: #{$check-border-color}; + --#{$prefix}check-checked-bg: #{$check-checked-bg}; + --#{$prefix}check-checked-border-color: #{$check-checked-border-color}; + --#{$prefix}check-indeterminate-bg: #{$check-indeterminate-bg}; + --#{$prefix}check-indeterminate-border-color: #{$check-indeterminate-border-color}; + --#{$prefix}check-disabled-bg: #{$check-disabled-bg}; + --#{$prefix}check-disabled-border-color: #{$check-disabled-border-color}; + --#{$prefix}check-disabled-opacity: #{$check-disabled-opacity}; + // scss-docs-end check-css-variables + + display: grid; + grid-template-columns: repeat(1, minmax(0, 1fr)); + margin-block: .125rem; + + :where(svg, input) { + flex-shrink: 0; + grid-row-start: 1; + grid-column-start: 1; + width: 1rem; + height: 1rem; + } + + :where(input) { + appearance: none; + // later: maybe set a tertiary bg color? + background-color: var(--#{$prefix}check-bg); + border: 1px solid var(--#{$prefix}check-border-color); + // stylelint-disable-next-line property-disallowed-list + border-radius: .25em; + } + + :where(input:checked, input:indeterminate) { + background-color: var(--#{$prefix}check-checked-bg); + border-color: var(--#{$prefix}check-checked-border-color); + } + + &:has(input:checked) .checked, + &:has(input:indeterminate) .indeterminate { + display: block; + color: var(--#{$prefix}primary-contrast); + stroke: currentcolor; + } + + &:has(input:disabled) { + --#{$prefix}check-bg: var(--#{$prefix}check-disabled-bg); + + ~ label { + color: var(--#{$prefix}secondary-text); + cursor: default; + } + } + + &:has(input:disabled:checked) { + opacity: var(--#{$prefix}check-disabled-opacity); + } + + :where(svg) { + pointer-events: none; + } + + :where(svg path) { + display: none; + } + } +} diff --git a/scss/forms/_form-check.scss b/scss/forms/_form-check.scss deleted file mode 100644 index bdb223f1e2..0000000000 --- a/scss/forms/_form-check.scss +++ /dev/null @@ -1,252 +0,0 @@ -@use "../config" as *; -@use "../colors" as *; -@use "../variables" as *; -@use "../functions" as *; -@use "../vendor/rfs" as *; -@use "../mixins/border-radius" as *; -@use "../mixins/box-shadow" as *; -@use "../mixins/color-mode" as *; -@use "../mixins/focus-ring" as *; -@use "../mixins/transition" as *; -@use "form-variables" as *; - -// scss-docs-start form-check-variables -$form-check-input-width: 1em !default; -$form-check-min-height: $font-size-base * $line-height-base !default; -$form-check-padding-start: $form-check-input-width + .5em !default; -$form-check-margin-bottom: .125rem !default; -$form-check-label-color: null !default; -$form-check-label-cursor: null !default; -$form-check-transition: null !default; - -$form-check-input-active-filter: brightness(90%) !default; - -$form-check-input-bg: $input-bg !default; -$form-check-input-border: var(--#{$prefix}border-width) solid var(--#{$prefix}border-color) !default; -$form-check-input-border-radius: .25em !default; -$form-check-radio-border-radius: 50% !default; -$form-check-input-focus-border: $input-focus-border-color !default; -$form-check-input-focus-box-shadow: $focus-ring-box-shadow !default; - -$form-check-input-checked-color: $component-active-color !default; -$form-check-input-checked-bg-color: $component-active-bg !default; -$form-check-input-checked-border-color: $form-check-input-checked-bg-color !default; -$form-check-input-checked-bg-image: url("data:image/svg+xml,") !default; -$form-check-radio-checked-bg-image: url("data:image/svg+xml,") !default; - -$form-check-input-indeterminate-color: $component-active-color !default; -$form-check-input-indeterminate-bg-color: $component-active-bg !default; -$form-check-input-indeterminate-border-color: $form-check-input-indeterminate-bg-color !default; -$form-check-input-indeterminate-bg-image: url("data:image/svg+xml,") !default; - -$form-check-input-disabled-opacity: .5 !default; -$form-check-label-disabled-opacity: $form-check-input-disabled-opacity !default; -$form-check-btn-check-disabled-opacity: $btn-disabled-opacity !default; - -$form-check-inline-margin-end: 1rem !default; -// scss-docs-end form-check-variables - -// scss-docs-start form-switch-variables -$form-switch-color: rgba($black, .25) !default; -$form-switch-width: 1.5em !default; -$form-switch-padding-start: $form-switch-width + .5em !default; -$form-switch-bg-image: url("data:image/svg+xml,") !default; -$form-switch-border-radius: $form-switch-width !default; -$form-switch-transition: background-position .15s ease-in-out !default; - -$form-switch-focus-color: $input-focus-border-color !default; -$form-switch-focus-bg-image: url("data:image/svg+xml,") !default; - -$form-switch-checked-color: $component-active-color !default; -$form-switch-checked-bg-image: url("data:image/svg+xml,") !default; -$form-switch-checked-bg-position: right center !default; -// scss-docs-end form-switch-variables - -@layer forms { - .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 { - --#{$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; - 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; - 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-visible { - border-color: $form-check-input-focus-border; - @include focus-ring(true); - --#{$prefix}focus-ring-offset: 1px; - // 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 { - --#{$prefix}form-check-bg-image: #{escape-svg($form-check-input-checked-bg-image)}, var(--#{$prefix}gradient); - } @else { - --#{$prefix}form-check-bg-image: #{escape-svg($form-check-input-checked-bg-image)}; - } - } - - &[type="radio"] { - @if $enable-gradients { - --#{$prefix}form-check-bg-image: #{escape-svg($form-check-radio-checked-bg-image)}, var(--#{$prefix}gradient); - } @else { - --#{$prefix}form-check-bg-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 { - --#{$prefix}form-check-bg-image: #{escape-svg($form-check-input-indeterminate-bg-image)}, var(--#{$prefix}gradient); - } @else { - --#{$prefix}form-check-bg-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 { - --#{$prefix}form-switch-bg: #{escape-svg($form-switch-bg-image)}; - - width: $form-switch-width; - margin-left: $form-switch-padding-start * -1; - background-image: var(--#{$prefix}form-switch-bg); - background-position: left center; - @include border-radius($form-switch-border-radius, 0); - @include transition($form-switch-transition); - - &:focus { - --#{$prefix}form-switch-bg: #{escape-svg($form-switch-focus-bg-image)}; - } - - &:checked { - background-position: $form-switch-checked-bg-position; - - @if $enable-gradients { - --#{$prefix}form-switch-bg: #{escape-svg($form-switch-checked-bg-image)}, var(--#{$prefix}gradient); - } @else { - --#{$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 { - 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; - } - } - } - - @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 6f617ee0ea..c7ff34f416 100644 --- a/scss/forms/_form-control.scss +++ b/scss/forms/_form-control.scss @@ -1,36 +1,45 @@ @use "sass:math"; @use "../config" as *; @use "../variables" as *; +@use "../functions" as *; @use "../vendor/rfs" as *; @use "../mixins/border-radius" as *; @use "../mixins/box-shadow" as *; +@use "../mixins/color-mode" as *; @use "../mixins/focus-ring" as *; @use "../mixins/gradients" as *; @use "../mixins/transition" as *; @use "form-variables" as *; -// -// General form controls (plus a few specific high-level interventions) -// - @layer forms { .form-control { + --#{$prefix}control-min-height: #{$control-min-height}; + --#{$prefix}control-padding-y: #{$control-padding-y}; + --#{$prefix}control-padding-x: #{$control-padding-x}; + --#{$prefix}control-font-size: #{$control-font-size}; + --#{$prefix}control-line-height: #{$control-line-height}; + --#{$prefix}control-color: #{$control-color}; + --#{$prefix}control-bg: #{$control-bg}; + --#{$prefix}control-border-width: #{$control-border-width}; + --#{$prefix}control-border-color: #{$control-border-color}; + --#{$prefix}control-border-radius: #{$control-border-radius}; + --#{$prefix}control-select-bg-color: #{$control-select-indicator-color}; + --#{$prefix}control-select-bg: #{escape-svg($control-select-indicator)}; + --#{$prefix}control-select-bg-position: #{$control-select-bg-position}; + --#{$prefix}control-select-bg-size: #{$control-select-bg-size}; + 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; - appearance: none; // Fix appearance for date inputs in Safari - background-color: $input-bg; + min-height: var(--#{$prefix}control-min-height); + padding: var(--#{$prefix}control-padding-y) var(--#{$prefix}control-padding-x); + font-size: var(--#{$prefix}control-font-size); + line-height: var(--#{$prefix}control-line-height); + color: var(--#{$prefix}control-color); + appearance: none; + background-color: var(--#{$prefix}control-bg); background-clip: padding-box; - border: $input-border-width solid $input-border-color; - - // Note: This has no effect on `s in CSS. - @include border-radius($input-border-radius, 0); - + border: var(--#{$prefix}control-border-width) solid var(--#{$prefix}control-border-color); + @include border-radius(var(--#{$prefix}control-border-radius), 0); @include box-shadow($input-box-shadow); @include transition($input-transition); @@ -99,16 +108,17 @@ // 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; + min-height: var(--#{$prefix}control-min-height); + padding: var(--#{$prefix}control-padding-y) var(--#{$prefix}control-padding-x); + margin: calc(var(--#{$prefix}control-padding-y) * -1) calc(var(--#{$prefix}control-padding-x) * -1); + margin-inline-end: var(--#{$prefix}control-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-inline-end-width: var(--#{$prefix}control-border-width); border-radius: 0; // stylelint-disable-line property-disallowed-list @include transition($btn-transition); } @@ -145,6 +155,28 @@ } } + // stylelint-disable selector-no-qualifying-type + select.form-control { + padding-right: calc(var(--#{$prefix}control-padding-x) * 3); + background-image: var(--#{$prefix}control-select-bg); + background-repeat: no-repeat; + background-position: var(--#{$prefix}control-select-bg-position); + background-size: var(--#{$prefix}control-select-bg-size); + + &[multiple], + &[size]:not([size="1"]) { + padding-right: var(--#{$prefix}control-padding-x); + background-image: none; + } + + @if $enable-dark-mode { + @include color-mode(dark) { + --#{$prefix}control-select-indicator: #{escape-svg($control-select-indicator-dark)}; + } + } + } + // stylelint-enable selector-no-qualifying-type + // Form control sizing // // Build on `.form-control` with modifier classes to decrease or increase the @@ -153,48 +185,40 @@ // 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; - } + --#{$prefix}control-min-height: #{$control-min-height-sm}; + --#{$prefix}control-padding-y: #{$control-padding-y-sm}; + --#{$prefix}control-padding-x: #{$control-padding-x-sm}; + --#{$prefix}control-font-size: #{$control-font-size-sm}; + --#{$prefix}control-line-height: #{$control-line-height-sm}; + --#{$prefix}control-border-radius: #{$control-border-radius-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; - } + --#{$prefix}control-min-height: #{$control-min-height-lg}; + --#{$prefix}control-padding-y: #{$control-padding-y-lg}; + --#{$prefix}control-padding-x: #{$control-padding-x-lg}; + --#{$prefix}control-font-size: #{$control-font-size-lg}; + --#{$prefix}control-line-height: #{$control-line-height-lg}; + --#{$prefix}control-border-radius: #{$control-border-radius-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; - } + // // 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-sm { + // min-height: $input-height-sm; + // } - &.form-control-lg { - min-height: $input-height-lg; - } - } - // stylelint-enable selector-no-qualifying-type + // &.form-control-lg { + // min-height: $input-height-lg; + // } + // } + // // stylelint-enable selector-no-qualifying-type .form-control-color { width: $form-color-width; diff --git a/scss/forms/_form-select.scss b/scss/forms/_form-select.scss deleted file mode 100644 index 5792edbcbb..0000000000 --- a/scss/forms/_form-select.scss +++ /dev/null @@ -1,127 +0,0 @@ -@use "../config" as *; -@use "../colors" as *; -@use "../variables" as *; -@use "../functions" as *; -@use "../vendor/rfs" as *; -@use "../mixins/border-radius" as *; -@use "../mixins/box-shadow" as *; -@use "../mixins/color-mode" as *; -@use "../mixins/focus-ring" as *; -@use "../mixins/transition" as *; -@use "form-variables" as *; - -// scss-docs-start form-select-variables -$form-select-padding-y: $input-padding-y !default; -$form-select-padding-x: $input-padding-x !default; -$form-select-font-family: $input-font-family !default; -$form-select-font-size: $input-font-size !default; -$form-select-indicator-padding: $form-select-padding-x * 3 !default; // Extra padding for background-image -$form-select-font-weight: $input-font-weight !default; -$form-select-line-height: $input-line-height !default; -$form-select-color: $input-color !default; -$form-select-bg: $input-bg !default; -$form-select-disabled-color: null !default; -$form-select-disabled-bg: $input-disabled-bg !default; -$form-select-disabled-border-color: $input-disabled-border-color !default; -$form-select-bg-position: right $form-select-padding-x center !default; -$form-select-bg-size: 16px 12px !default; // In pixels because image dimensions -$form-select-indicator-color: $gray-800 !default; -$form-select-indicator: url("data:image/svg+xml,") !default; - -$form-select-feedback-icon-padding-end: $form-select-padding-x * 2.5 + $form-select-indicator-padding !default; -$form-select-feedback-icon-position: center right $form-select-indicator-padding !default; -$form-select-feedback-icon-size: $input-height-inner-half $input-height-inner-half !default; - -$form-select-border-width: $input-border-width !default; -$form-select-border-color: $input-border-color !default; -$form-select-border-radius: $input-border-radius !default; -$form-select-box-shadow: var(--#{$prefix}box-shadow-inset) !default; - -$form-select-focus-border-color: $input-focus-border-color !default; -$form-select-focus-width: $input-focus-width !default; -// $form-select-focus-box-shadow: 0 0 0 $form-select-focus-width $input-btn-focus-color !default; - -$form-select-padding-y-sm: $input-padding-y-sm !default; -$form-select-padding-x-sm: $input-padding-x-sm !default; -$form-select-font-size-sm: $input-font-size-sm !default; -$form-select-border-radius-sm: $input-border-radius-sm !default; - -$form-select-padding-y-lg: $input-padding-y-lg !default; -$form-select-padding-x-lg: $input-padding-x-lg !default; -$form-select-font-size-lg: $input-font-size-lg !default; -$form-select-border-radius-lg: $input-border-radius-lg !default; - -$form-select-transition: $input-transition !default; -// scss-docs-end form-select-variables - -@layer forms { - .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; - 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: 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; - 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); - - &:focus-visible { - border-color: $form-select-focus-border-color; - @include focus-ring(true); - } - - &[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); - } - - @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/_form-variables.scss b/scss/forms/_form-variables.scss index bde73334ae..f7a002ddeb 100644 --- a/scss/forms/_form-variables.scss +++ b/scss/forms/_form-variables.scss @@ -1,18 +1,53 @@ @use "../config" as *; +@use "../colors" as *; @use "../variables" as *; +$control-min-height: 2.5rem !default; +$control-min-height-sm: 2rem !default; +$control-min-height-lg: 3rem !default; +$control-padding-y: .375rem !default; +$control-padding-x: .75rem !default; +$control-font-size: $font-size-base !default; +$control-line-height: $line-height-base !default; +$control-color: var(--#{$prefix}body-color) !default; +$control-bg: var(--#{$prefix}body-bg) !default; +$control-border-width: var(--#{$prefix}border-width) !default; +$control-border-color: var(--#{$prefix}border-color) !default; +$control-border-radius: var(--#{$prefix}border-radius) !default; + +$control-padding-y-sm: .25rem !default; +$control-padding-x-sm: .5rem !default; +$control-font-size-sm: $font-size-sm !default; +$control-line-height-sm: $line-height-sm !default; +$control-border-radius-sm: var(--#{$prefix}border-radius-sm) !default; + +$control-padding-y-lg: .5rem !default; +$control-padding-x-lg: 1rem !default; +$control-font-size-lg: $font-size-lg !default; +$control-line-height-lg: $line-height-lg !default; +$control-border-radius-lg: var(--#{$prefix}border-radius-lg) !default; + +$control-select-indicator-color: $gray-600 !default; +$control-select-indicator: url("data:image/svg+xml,") !default; +$control-select-bg-position: right $control-padding-x center !default; +$control-select-bg-size: 16px 12px !default; + +$control-select-indicator-color-dark: $body-color-dark !default; +$control-select-indicator-dark: url("data:image/svg+xml,") !default; + + // scss-docs-start input-btn-variables $input-btn-padding-y: .375rem !default; $input-btn-padding-x: .75rem !default; -$input-btn-font-family: null !default; +// $input-btn-font-family: null !default; $input-btn-font-size: $font-size-base !default; $input-btn-line-height: $line-height-base !default; -$input-btn-focus-width: $focus-ring-width !default; -$input-btn-focus-color-opacity: $focus-ring-opacity !default; -$input-btn-focus-color: $focus-ring-color !default; -$input-btn-focus-blur: $focus-ring-blur !default; -$input-btn-focus-box-shadow: $focus-ring-box-shadow !default; +// $input-btn-focus-width: $focus-ring-width !default; +// $input-btn-focus-color-opacity: $focus-ring-opacity !default; +// $input-btn-focus-color: $focus-ring-color !default; +// $input-btn-focus-blur: $focus-ring-blur !default; +// $input-btn-focus-box-shadow: $focus-ring-box-shadow !default; $input-btn-padding-y-sm: .25rem !default; $input-btn-padding-x-sm: .5rem !default; @@ -22,15 +57,15 @@ $input-btn-padding-y-lg: .5rem !default; $input-btn-padding-x-lg: 1rem !default; $input-btn-font-size-lg: $font-size-lg !default; -$input-btn-border-width: var(--#{$prefix}border-width) !default; +// $input-btn-border-width: var(--#{$prefix}border-width) !default; // scss-docs-end input-btn-variables // scss-docs-start form-input-variables $input-padding-y: $input-btn-padding-y !default; $input-padding-x: $input-btn-padding-x !default; -$input-font-family: $input-btn-font-family !default; +// $input-font-family: $input-btn-font-family !default; $input-font-size: $input-btn-font-size !default; -$input-font-weight: $font-weight-base !default; +// $input-font-weight: $font-weight-base !default; $input-line-height: $input-btn-line-height !default; $input-padding-y-sm: $input-btn-padding-y-sm !default; @@ -48,7 +83,7 @@ $input-disabled-border-color: null !default; $input-color: var(--#{$prefix}body-color) !default; $input-border-color: var(--#{$prefix}border-color) !default; -$input-border-width: $input-btn-border-width !default; +$input-border-width: var(--#{$prefix}border-width) !default; $input-box-shadow: var(--#{$prefix}box-shadow-inset) !default; $input-border-radius: var(--#{$prefix}border-radius) !default; @@ -70,9 +105,12 @@ $input-height-inner: add($input-line-height * 1em, $input-pad $input-height-inner-half: add($input-line-height * .5em, $input-padding-y) !default; $input-height-inner-quarter: add($input-line-height * .25em, $input-padding-y * .5) !default; -$input-height: add($input-line-height * 1em, add($input-padding-y * 2, $input-height-border, false)) !default; -$input-height-sm: add($input-line-height * 1em, add($input-padding-y-sm * 2, $input-height-border, false)) !default; -$input-height-lg: add($input-line-height * 1em, add($input-padding-y-lg * 2, $input-height-border, false)) !default; +// $input-height: add($input-line-height * 1em, add($input-padding-y * 2, $input-height-border, false)) !default; +// $input-height-sm: add($input-line-height * 1em, add($input-padding-y-sm * 2, $input-height-border, false)) !default; +// $input-height-lg: add($input-line-height * 1em, add($input-padding-y-lg * 2, $input-height-border, false)) !default; +$input-height: 2.5rem !default; +$input-height-sm: 2rem !default; +$input-height-lg: 3rem !default; $input-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out !default; diff --git a/scss/forms/_input-group.scss b/scss/forms/_input-group.scss index 8d6de5be18..99db177f5f 100644 --- a/scss/forms/_input-group.scss +++ b/scss/forms/_input-group.scss @@ -10,7 +10,7 @@ // scss-docs-start input-group-variables $input-group-addon-padding-y: $input-padding-y !default; $input-group-addon-padding-x: $input-padding-x !default; -$input-group-addon-font-weight: $input-font-weight !default; +// $input-group-addon-font-weight: $input-font-weight !default; $input-group-addon-color: $input-color !default; $input-group-addon-bg: var(--#{$prefix}tertiary-bg) !default; $input-group-addon-border-color: $input-border-color !default; @@ -64,7 +64,7 @@ $input-group-addon-border-color: $input-border-color !default; 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; + // font-weight: $input-group-addon-font-weight; line-height: $input-line-height; color: $input-group-addon-color; text-align: center; diff --git a/scss/forms/_radio.scss b/scss/forms/_radio.scss new file mode 100644 index 0000000000..af63fb188e --- /dev/null +++ b/scss/forms/_radio.scss @@ -0,0 +1,79 @@ +@use "../config" as *; +@use "../colors" as *; +@use "../variables" as *; +@use "../functions" as *; +@use "../vendor/rfs" as *; +@use "../mixins/border-radius" as *; +@use "../mixins/box-shadow" as *; +@use "../mixins/color-mode" as *; +@use "../mixins/focus-ring" as *; +@use "../mixins/transition" as *; +@use "form-variables" as *; + +// scss-docs-start radio-variables +$radio-border-color: var(--#{$prefix}border-color) !default; +$radio-checked-bg: var(--#{$prefix}primary-base) !default; +$radio-checked-border-color: $radio-checked-bg !default; +$radio-disabled-bg: var(--#{$prefix}secondary-bg) !default; +$radio-disabled-border-color: $radio-disabled-bg !default; +$radio-disabled-opacity: .65 !default; +// scss-docs-end radio-variables + +@layer forms { + b-radiogroup { + display: flex; + gap: var(--#{$prefix}gap, .5rem); + align-items: var(--#{$prefix}align-items, start); + + .description { + color: var(--#{$prefix}secondary-text); + } + } + + .radio { + // scss-docs-start radio-css-variables + --#{$prefix}radio-bg: transparent; + --#{$prefix}radio-border-color: #{$radio-border-color}; + --#{$prefix}radio-checked-bg: #{$radio-checked-bg}; + --#{$prefix}radio-checked-border-color: #{$radio-checked-border-color}; + --#{$prefix}radio-disabled-bg: #{$radio-disabled-bg}; + --#{$prefix}radio-disabled-border-color: #{$radio-disabled-border-color}; + --#{$prefix}radio-disabled-opacity: #{$radio-disabled-opacity}; + // scss-docs-end radio-css-variables + + position: relative; + flex-shrink: 0; + width: 1rem; + height: 1rem; + margin-block: .125rem; + appearance: none; + background-color: var(--#{$prefix}radio-bg); + border: 1px solid var(--#{$prefix}radio-border-color); + // stylelint-disable-next-line property-disallowed-list + border-radius: 50%; + + &:checked { + color: var(--#{$prefix}primary-contrast); + background-color: var(--#{$prefix}radio-checked-bg); + border-color: var(--#{$prefix}radio-checked-border-color); + + &::before { + position: absolute; + inset: .25rem; + content: ""; + background-color: currentcolor; + // stylelint-disable-next-line property-disallowed-list + border-radius: 50%; + } + } + + &:disabled { + --#{$prefix}radio-bg: var(--#{$prefix}radio-disabled-bg); + + ~ label { + color: var(--#{$prefix}secondary-text); + cursor: default; + } + } + } +} diff --git a/scss/forms/_switch.scss b/scss/forms/_switch.scss new file mode 100644 index 0000000000..457d170a4f --- /dev/null +++ b/scss/forms/_switch.scss @@ -0,0 +1,89 @@ +@use "../config" as *; +@use "../colors" as *; +@use "../variables" as *; +@use "../functions" as *; +@use "../vendor/rfs" as *; +@use "../mixins/border-radius" as *; +@use "../mixins/box-shadow" as *; +@use "../mixins/color-mode" as *; +@use "../mixins/focus-ring" as *; +@use "../mixins/transition" as *; +@use "form-variables" as *; + +@layer forms { + .switch { + // scss-docs-start switch-css-variables + --#{$prefix}switch-height: 1.25rem; + --#{$prefix}switch-width: calc(var(--#{$prefix}switch-height) * 1.5); + --#{$prefix}switch-padding: .0625rem; + --#{$prefix}switch-bg: var(--#{$prefix}secondary-bg); + --#{$prefix}switch-border-width: var(--#{$prefix}border-width); + --#{$prefix}switch-border-color: var(--#{$prefix}border-color); + --#{$prefix}switch-indicator-bg: var(--#{$prefix}white); + --#{$prefix}switch-checked-bg: var(--#{$prefix}primary-base); + --#{$prefix}switch-checked-indicator-bg: var(--#{$prefix}white); + --#{$prefix}switch-disabled-bg: var(--#{$prefix}secondary-bg); + --#{$prefix}switch-disabled-indicator-bg: var(--#{$prefix}secondary-text); + // scss-docs-end switch-css-variables + + position: relative; + display: flex; + flex-shrink: 0; + align-items: stretch; + justify-content: flex-start; + width: var(--#{$prefix}switch-width); + height: var(--#{$prefix}switch-height); + padding: var(--#{$prefix}switch-padding); + background-color: var(--#{$prefix}switch-bg); + border: var(--#{$prefix}switch-border-width) solid var(--#{$prefix}switch-border-color); + // stylelint-disable-next-line property-disallowed-list + border-radius: 10rem; + box-shadow: inset 0 1px 2px rgba($black, .05); + // stylelint-disable-next-line property-disallowed-list + transition: .15s ease-in-out; + transition-property: padding-inline-start, background-color; + + &::before { + flex-shrink: 0; + width: calc(var(--#{$prefix}switch-height) - calc(var(--#{$prefix}switch-padding) * 2) - var(--#{$prefix}switch-border-width) * 2); + height: calc(var(--#{$prefix}switch-height) - calc(var(--#{$prefix}switch-padding) * 2) - var(--#{$prefix}switch-border-width) * 2); + // width: calc(var(--#{$prefix}switch-height) - calc(var(--#{$prefix}switch-padding) * 2)); + // height: calc(var(--#{$prefix}switch-height) - calc(var(--#{$prefix}switch-padding) * 2)); + content: ""; + background-color: var(--#{$prefix}switch-indicator-bg); + // stylelint-disable-next-line property-disallowed-list + border-radius: 50%; + box-shadow: 0 1px 2px rgba($black, .1); + } + + input { + position: absolute; + inset: 0; + appearance: none; + background-color: transparent; + } + + &:has(input:checked) { + padding-inline-start: calc(var(--#{$prefix}switch-height) / 2 + var(--#{$prefix}switch-padding)); + background-color: var(--#{$prefix}primary-base); + } + + &:has(input:disabled) { + --#{$prefix}switch-bg: var(--#{$prefix}switch-disabled-bg); + --#{$prefix}switch-indicator-bg: var(--#{$prefix}switch-disabled-indicator-bg); + + &::before { opacity: .4; } + + ~ label { + color: var(--#{$prefix}secondary-text); + cursor: default; + } + } + } + .switch-sm { + --#{$prefix}switch-height: 1em; + } + .switch-lg { + --#{$prefix}switch-height: 2em; + } +} diff --git a/scss/forms/index.scss b/scss/forms/index.scss index 57e6cd25ee..0798f2003b 100644 --- a/scss/forms/index.scss +++ b/scss/forms/index.scss @@ -1,8 +1,9 @@ @forward "labels"; @forward "form-text"; @forward "form-control"; -@forward "form-select"; -@forward "form-check"; +@forward "check"; +@forward "radio"; +@forward "switch"; @forward "form-range"; @forward "floating-labels"; @forward "input-group"; diff --git a/scss/helpers/_stacks.scss b/scss/helpers/_stacks.scss index 36c4ccad70..67c83c3eb6 100644 --- a/scss/helpers/_stacks.scss +++ b/scss/helpers/_stacks.scss @@ -1,13 +1,24 @@ +// stylelint-disable selector-no-qualifying-type + @layer helpers { // scss-docs-start stacks - .hstack { + .hstack, + b-hstack { display: flex; flex-direction: row; align-items: center; align-self: stretch; } + .hstack-start, + b-hstack[align="start"] { + display: flex; + flex-direction: row; + align-items: flex-start; + align-self: stretch; + } - .vstack { + .vstack, + b-vstack { display: flex; flex: 1 1 auto; flex-direction: column; diff --git a/site/data/sidebar.yml b/site/data/sidebar.yml index d8e732f5a4..c6078956db 100644 --- a/site/data/sidebar.yml +++ b/site/data/sidebar.yml @@ -60,8 +60,9 @@ pages: - title: Overview - title: Form control - - title: Select - - title: Checks & radios + - title: Checkbox + - title: Radio + - title: Switch - title: Range - title: Input group - title: Floating labels diff --git a/site/src/content/docs/components/button-group.mdx b/site/src/content/docs/components/button-group.mdx index 5e59feb5b6..34a3055ad5 100644 --- a/site/src/content/docs/components/button-group.mdx +++ b/site/src/content/docs/components/button-group.mdx @@ -44,7 +44,7 @@ These classes can also be added to groups of links, as an alternative to the [`. ## Checkbox and radio button groups -Combine button-like checkbox and radio [toggle buttons]([[docsref:/forms/checks-radios]]) into a seamless looking button group. +Combine button-like checkbox and radio toggle buttons into a seamless looking button group. diff --git a/site/src/content/docs/components/buttons.mdx b/site/src/content/docs/components/buttons.mdx index 4f864f7101..e6bbd3b5ba 100644 --- a/site/src/content/docs/components/buttons.mdx +++ b/site/src/content/docs/components/buttons.mdx @@ -15,7 +15,7 @@ Bootstrap has a base `.btn` class that sets up basic styles such as padding and The `.btn` class is intended to be used in conjunction with our button variants, or to serve as a basis for your own custom styles. -If you are using the `.btn` class on its own, remember to at least define some explicit `:focus` and/or `:focus-visible` styles. +When using `.btn` without a modifier, be sure to add some explicit `:focus-visible` styles. ## Variants @@ -126,12 +126,82 @@ Additional utilities can be used to adjust the alignment of buttons when horizon `} /> +## Toggle buttons + +Create button-like checkboxes and radio buttons by using `.btn` styles rather than `.form-check-label` on the `