Dark mode's derived variables should reference the variables they are based on, not the defaults
Created by: yugabe
https://github.com/orgs/twbs/discussions/37911
Discussed inOriginally posted by Nysosis January 18, 2023
I'm just looking through the https://github.com/twbs/bootstrap/blob/main/scss/_variables.scss and wondering why the variables at https://github.com/twbs/bootstrap/blob/main/scss/_variables.scss#L325 aren't based off the actual, and primarily I'm concerned on $primary
variable, instead they use the appropriate shade of what the default colour is.
If I change the $primary, I would have thought it would feed through into all derived colours, instead of also needing to override those (and potentially others down the line)
This seems to be mainly true for colors defined in _variables-dark.scss and _variables.scss. It became mostly impossible to migrate to 5.3.0 from 5.2.x, because overriding the base colors don't work at all.
For reference, I think the correct way to define the dark mode variables would be similar to as follows:
_variables-dark.scss:
/* ... */
// scss-docs-start sass-dark-mode-vars
$primary-text-dark: tint-color($primary, 40%) !default; // was $blue-300 !default;
$secondary-text-dark: $gray-300 !default; // Kept as is. As secondary is used as "disabled" colors, it doesn't really make sense to override them at all anyways. Grays are defined manually, so tinting isn't straighforward either.
$success-text-dark: tint-color($success, 40%) !default; // was $green-300 !default;
$info-text-dark: tint-color($info, 40%) !default; // was $cyan-300 !default;
$warning-text-dark: tint-color($warning, 40%) !default; // was $yellow-300 !default;
$danger-text-dark: tint-color($danger, 40%) !default; // was $red-300 !default;
$light-text-dark: $gray-100 !default;
$dark-text-dark: $gray-300 !default;
$primary-bg-subtle-dark: shade-color($primary, 80%) !default; // was $blue-900 !default;
$secondary-bg-subtle-dark: $gray-900 !default;
$success-bg-subtle-dark: shade-color($success, 80%) !default; // was $green-900 !default;
$info-bg-subtle-dark: shade-color($info, 80%) !default; // was $cyan-900 !default;
$warning-bg-subtle-dark: shade-color($warning, 80%) !default; // was $yellow-900 !default;
$danger-bg-subtle-dark: shade-color($danger, 80%) !default; // was $red-900 !default;
$light-bg-subtle-dark: $gray-800 !default;
$dark-bg-subtle-dark: mix($gray-800, $black) !default;
$primary-border-subtle-dark: shade-color($primary, 40%) !default; // was $blue-700 !default;
$secondary-border-subtle-dark: $gray-700 !default;
$success-border-subtle-dark: shade-color($success, 40%) !default; // was $green-700 !default;
$info-border-subtle-dark: shade-color($info, 60%) !default; // was $cyan-800 !default;
$warning-border-subtle-dark: shade-color($warning, 60%) !default; // was $yellow-800 !default;
$danger-border-subtle-dark: shade-color($red, 40%) !default; // was $red-700 !default;
$light-border-subtle-dark: $gray-700 !default;
$dark-border-subtle-dark: $gray-800 !default;
$body-color-dark: $gray-500 !default;
$body-bg-dark: $gray-900 !default;
$body-emphasis-color-dark: $gray-100 !default;
$body-secondary-color-dark: rgba($body-color-dark, .75) !default; // Wierd to see how this correctly references its base color...
$body-secondary-bg-dark: $gray-800 !default;
$body-tertiary-color-dark: rgba($body-color-dark, .5) !default; // This too.
$body-tertiary-bg-dark: mix($gray-800, $gray-900, 50%) !default;
$emphasis-color-dark: $white !default;
$border-color-dark: $gray-700 !default;
$border-color-translucent-dark: rgba($white, .15) !default;
$headings-color-dark: #fff !default; // This is just plain bad, I would certainly do a blame on this. Why use $white one line above, and #fff here?
$link-color-dark: tint-color($primary, 40%) !default; // was $blue-300 !default;
$link-hover-color-dark: shift-color($link-color-dark, -$link-shade-percentage) !default; // was $blue-200 !default; - I'm taking a guess shading with a negative value will work correctly.
$code-color-dark: tint-color($code-color, 40%) !default; // was $pink-300 !default;
/* ... */
_variables.scss
/* ... */
$primary-text: shade-color($primary, 20%) !default; // was $blue-600 !default;
$secondary-text: $gray-600 !default;
$success-text: shade-color($green, 20%) !default; // was $green-600 !default;
$info-text: shade-color($info, 40%) !default; // was $cyan-700 !default;
$warning-text: shade-color($warning, 40%) !default; // was $yellow-700 !default;
$danger-text: shade-color($danger, 20%) !default; // was $red-600 !default;
$light-text: $gray-600 !default;
$dark-text: $gray-700 !default;
$primary-bg-subtle: tint-color($primary, 80%) !default; // was $blue-100 !default;
$secondary-bg-subtle: $gray-100 !default;
$success-bg-subtle: tint-color($success, 80%) !default; // was $green-100 !default;
$info-bg-subtle: tint-color($info, 80%) !default; // was $cyan-100 !default;
$warning-bg-subtle: tint-color($warning, 80%) !default; // was $yellow-100 !default;
$danger-bg-subtle: tint-color($danger, 80%) !default; // was $red-100 !default;
$light-bg-subtle: mix($gray-100, $white) !default;
$dark-bg-subtle: $gray-400 !default;
$primary-border-subtle: tint-color($primary, 60%) !default; // was $blue-200 !default;
$secondary-border-subtle: $gray-200 !default;
$success-border-subtle: tint-color($success, 60%) !default; // $green-200 !default;
$info-border-subtle: tint-color($info, 60%) !default; // $cyan-200 !default;
$warning-border-subtle: tint-color($warning, 60%) !default; // $yellow-200 !default;
$danger-border-subtle: tint-color($danger, 60%) !default; // $red-200 !default;
$light-border-subtle: $gray-200 !default;
$dark-border-subtle: $gray-500 !default;
/* ... */
It would be even better if the default was calculated based on the default light value, so that it would be lightened/darkened sufficiently enough that the target contrast ratio could be achieved. This is mostly because like $primary-border-subtle-dark
uses $blue-700
, but $info-border-subtle-dark
uses $cyan-800
, so they cannot use the same percentage for shading (unless we accept 50% as a correct middle ground).
A problem is with light, dark and "secondary", which are whites, blacks and shades of gray. See comments in the code above. Secondary shouldn't have been repurposed as the color that you use for "disabled" states and whatnot - or I might have missed it previously, but overriding it makes a bit less sense in this case.
It's very obvious no reference should be made to discrete colors (like $red
) in the body of the "_variables*.scss" files instead where they are defined and assigned to the default theme - so, usually once.
Making multiple different variables in 5.3.0 doesn't help at all if someone wants do define more theme colors then the ones currently built in. The docs don't reflect how adding one more color to the theme map might affect all related aspects either.