diff --git a/package-lock.json b/package-lock.json index 33b723d53d..4a3c716ca8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7174,6 +7174,16 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-libc": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.0.tgz", + "integrity": "sha512-vEtk+OcP7VBRtQZ1EJ3bdgzSfBjgnEalLTp5zjJrS+2Z1w2KZly4SBdac/WDU3hhsNAZ9E8SC96ME4Ey8MZ7cg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=8" + } + }, "node_modules/deterministic-object-hash": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/deterministic-object-hash/-/deterministic-object-hash-2.0.2.tgz", @@ -17109,17 +17119,6 @@ "@img/sharp-win32-x64": "0.34.4" } }, - "node_modules/sharp/node_modules/detect-libc": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", - "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "engines": { - "node": ">=8" - } - }, "node_modules/sharp/node_modules/semver": { "version": "7.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", diff --git a/scss/_config.scss b/scss/_config.scss index 34c1abb54c..64f07db28e 100644 --- a/scss/_config.scss +++ b/scss/_config.scss @@ -19,7 +19,6 @@ $enable-rfs: true !default; $enable-validation-icons: true !default; $enable-negative-margins: false !default; $enable-deprecation-messages: true !default; -$enable-important-utilities: false !default; $enable-dark-mode: true !default; $color-mode-type: data !default; // `data` or `media-query` diff --git a/scss/_utilities.scss b/scss/_utilities.scss index 607c1da901..1baeeb77c0 100644 --- a/scss/_utilities.scss +++ b/scss/_utilities.scss @@ -95,6 +95,7 @@ $utilities: map.merge( print: true, property: display, class: d, + important: true, values: inline inline-block block grid inline-grid table table-row table-cell flex inline-flex flow-root none ), // scss-docs-end utils-display @@ -121,6 +122,7 @@ $utilities: map.merge( // scss-docs-start utils-position "position": ( property: position, + important: true, values: static relative absolute fixed sticky ), "top": ( @@ -859,6 +861,7 @@ $utilities: map.merge( "visibility": ( property: visibility, class: null, + important: true, values: ( visible: visible, invisible: hidden, diff --git a/scss/_variables.scss b/scss/_variables.scss index a56412b50d..a0ed0d40a2 100644 --- a/scss/_variables.scss +++ b/scss/_variables.scss @@ -94,7 +94,6 @@ $escaped-characters: ( // $enable-validation-icons: true !default; // $enable-negative-margins: false !default; // $enable-deprecation-messages: true !default; -// $enable-important-utilities: true !default; // $enable-dark-mode: true !default; // $color-mode-type: data !default; // `data` or `media-query` diff --git a/scss/helpers/_color-bg.scss b/scss/helpers/_color-bg.scss index 8d70151ee1..d9b1c56e89 100644 --- a/scss/helpers/_color-bg.scss +++ b/scss/helpers/_color-bg.scss @@ -6,8 +6,8 @@ // All-caps `RGBA()` function used because of this Sass bug: https://github.com/sass/node-sass/issues/2251 @each $color, $value in $theme-colors { .text-bg-#{$color} { - color: color-contrast($value) if($enable-important-utilities, !important, null); - background-color: RGBA(var(--#{$prefix}#{$color}-rgb), var(--#{$prefix}bg-opacity, 1)) if($enable-important-utilities, !important, null); + color: color-contrast($value); + background-color: RGBA(var(--#{$prefix}#{$color}-rgb), var(--#{$prefix}bg-opacity, 1)); } } } diff --git a/scss/mixins/_utilities.scss b/scss/mixins/_utilities.scss index 7202a82312..39d85bc436 100644 --- a/scss/mixins/_utilities.scss +++ b/scss/mixins/_utilities.scss @@ -58,6 +58,7 @@ $is-css-var: map.get($utility, css-var); $is-local-vars: map.get($utility, local-vars); $is-rtl: map.get($utility, rtl); + $is-important: map.get($utility, important); @if $value != null { @if $is-rtl == false { @@ -82,7 +83,7 @@ --#{$prefix}#{$local-var}: #{$variable}; } } - #{$property}: $value if($enable-important-utilities, !important, null); + #{$property}: $value if($is-important, !important, null); } } @@ -94,7 +95,7 @@ --#{$prefix}#{$local-var}: #{$variable}; } } - #{$property}: $value if($enable-important-utilities, !important, null); + #{$property}: $value if($is-important, !important, null); } } } diff --git a/scss/tests/mixins/_utilities.test.scss b/scss/tests/mixins/_utilities.test.scss index 00ce389582..da42501b1d 100644 --- a/scss/tests/mixins/_utilities.test.scss +++ b/scss/tests/mixins/_utilities.test.scss @@ -6,7 +6,6 @@ $true-terminal-output: false; $prefix: bs-; -$enable-important-utilities: false; // Important: Do not import rfs to check that the mixin just calls the appropriate functions from it // @import "../../mixins/utilities"; @@ -41,13 +40,12 @@ $enable-important-utilities: false; } } - @include describe("global $enable-important-utilities: true") { + @include describe("per-utility important: true") { @include it("sets !important") { - $enable-important-utilities: true !global; - @include test-generate-utility( ( property: "padding", + important: true, values: (small: .5rem, large: 2rem) ) ) { @@ -59,8 +57,6 @@ $enable-important-utilities: false; padding: 2rem !important; } } - - $enable-important-utilities: false !global; } } diff --git a/scss/tests/utilities/_api.test.scss b/scss/tests/utilities/_api.test.scss index 304d8d1c94..2b38bb9964 100644 --- a/scss/tests/utilities/_api.test.scss +++ b/scss/tests/utilities/_api.test.scss @@ -1,8 +1,7 @@ -@import "../../functions"; -@import "../../variables"; -@import "../../variables-dark"; -@import "../../maps"; -@import "../../mixins"; +@use "../../functions"; +@use "../../variables"; +@use "../../maps"; +@use "../../mixins"; $utilities: (); @@ -11,16 +10,19 @@ $utilities: (); $utilities: ( margin: ( property: margin, + important: true, values: auto ), padding: ( property: padding, responsive: true, + important: true, values: 1rem ), font-size: ( property: font-size, values: (large: 1.25rem), + important: true, print: true ) ) !global; @@ -33,7 +35,7 @@ $utilities: (); @include assert() { @include output() { - @import "../../utilities/api"; + @use "../../utilities/api"; } @include expect() { @@ -72,4 +74,53 @@ $utilities: (); } } + + @include it("generates utilities without !important when important: false or not set") { + $utilities: ( + opacity: ( + property: opacity, + values: ( + 0: 0, + 50: .5, + 100: 1 + ) + ), + text-align: ( + property: text-align, + important: false, + values: ( + start: left, + center: center + ) + ) + ) !global; + + @include assert() { + @include output() { + @import "../../utilities/api"; + } + + @include expect() { + .opacity-0 { + opacity: 0; + } + + .opacity-50 { + opacity: .5; + } + + .opacity-100 { + opacity: 1; + } + + .text-align-start { + text-align: left; + } + + .text-align-center { + text-align: center; + } + } + } + } } diff --git a/site/src/content/docs/customize/options.mdx b/site/src/content/docs/customize/options.mdx index 926ae03122..16120e3fda 100644 --- a/site/src/content/docs/customize/options.mdx +++ b/site/src/content/docs/customize/options.mdx @@ -26,6 +26,5 @@ You can find and customize these variables for key global options in Bootstrap | `$enable-validation-icons` | `true` (default) or `false` | Enables `background-image` icons within textual inputs and some custom forms for validation states. | | `$enable-negative-margins` | `true` or `false` (default) | Enables the generation of [negative margin utilities]([[docsref:/utilities/spacing#negative-margin]]). | | `$enable-deprecation-messages` | `true` (default) or `false` | Set to `false` to hide warnings when using any of the deprecated mixins and functions that are planned to be removed in `v6`. | -| `$enable-important-utilities` | `true` (default) or `false` | Enables the `!important` suffix in utility classes. | | `$enable-smooth-scroll` | `true` (default) or `false` | Applies `scroll-behavior: smooth` globally, except for users asking for reduced motion through [`prefers-reduced-motion` media query]([[docsref:/getting-started/accessibility#reduced-motion]]) | diff --git a/site/src/content/docs/utilities/api.mdx b/site/src/content/docs/utilities/api.mdx index a3a3631170..daea7d5bc4 100644 --- a/site/src/content/docs/utilities/api.mdx +++ b/site/src/content/docs/utilities/api.mdx @@ -13,13 +13,14 @@ The `$utilities` map contains all our utilities and is later merged with your cu | Option | Type | Default value | Description | | --- | --- | --- | --- | | [`property`](#property) | **Required** | – | Name of the property, this can be a string or an array of strings (e.g., horizontal paddings or margins). | -| [`values`](#values) | **Required** | – | List of values, or a map if you don’t want the class name to be the same as the value. If `null` is used as map key, `class` is not prepended to the class name. | +| [`values`](#values) | **Required** | – | List of values, or a map if you don't want the class name to be the same as the value. If `null` is used as map key, `class` is not prepended to the class name. | | [`class`](#class) | Optional | null | Name of the generated class. If not provided and `property` is an array of strings, `class` will default to the first element of the `property` array. If not provided and `property` is a string, the `values` keys are used for the `class` names. | | [`css-var`](#css-variable-utilities) | Optional | `false` | Boolean to generate CSS variables instead of CSS rules. | | [`css-variable-name`](#css-variable-utilities) | Optional | null | Custom un-prefixed name for the CSS variable inside the ruleset. | | [`local-vars`](#local-css-variables) | Optional | null | Map of local CSS variables to generate in addition to the CSS rules. | | [`state`](#states) | Optional | null | List of pseudo-class variants (e.g., `:hover` or `:focus`) to generate. | | [`responsive`](#responsive) | Optional | `false` | Boolean indicating if responsive classes should be generated. | +| [`important`](#importance) | Optional | `false` | Boolean indicating if `!important` should be added to the utility's CSS rules. | | `rfs` | Optional | `false` | Boolean to enable [fluid rescaling with RFS]([[docsref:/getting-started/rfs]]). | | [`print`](#print) | Optional | `false` | Boolean indicating if print classes need to be generated. | | `rtl` | Optional | `true` | Boolean indicating if utility should be kept in RTL. | @@ -360,12 +361,36 @@ Output: ## Importance -Utilities generated by the API no longer include `!important` by default in v6. This is because we now use CSS layers to ensure utilities override components and modifier classes as intended. You can toggle this setting globally with the `$enable-important-utilities` variable (defaults to `false`). +Utilities generated by the API no longer include `!important` by default in v6. This is because we now use CSS layers to ensure utilities override components and modifier classes as intended. You can enable `!important` on a per-utility basis by setting the `important` option to `true`. ```scss -$enable-important-utilities: true; +$utilities: ( + "opacity": ( + property: opacity, + important: true, + values: ( + 0: 0, + 25: .25, + 50: .5, + 75: .75, + 100: 1, + ) + ) +); ``` +This will generate utilities with `!important`: + +```css +.opacity-0 { opacity: 0 !important; } +.opacity-25 { opacity: .25 !important; } +.opacity-50 { opacity: .5 !important; } +.opacity-75 { opacity: .75 !important; } +.opacity-100 { opacity: 1 !important; } +``` + +Some utilities like `display`, `position`, and `visibility` have `important: true` set by default as they commonly need to override component styles. + ## Using the API Now that you’re familiar with how the utilities API works, learn how to add your own custom classes and modify our default utilities.