bootstrap icon indicating copy to clipboard operation
bootstrap copied to clipboard

[PROTO]: handle data-bs-theme differently

Open julien-deramond opened this issue 2 years ago • 1 comments


:warning: DRAFT - PROTOTYPE

Description

This PR suggests to change the way we handle data-bs-theme by automatically setting color and background-color values with the following rule:

:root,
[data-bs-theme] {
  color: var(--#{$prefix}body-color);
  background-color: var(--#{$prefix}body-bg);
}

It allows users to set data-bs-theme on any element and have the correct colors applied to it. For example:

<div data-bs-theme="dark">
  <h1>Title</h1>
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>

Based on that statement, it would mean that we could maybe remove some color: var(--bs-{component}-color) and background-color: var(--bs-{component}-bg) rules from our components.

  • [ ] Test this theory more in depth

In order to apply this rule within components, color-mode mixin is rewritten to either apply the @content to :root, [data-bs-theme="light"] or [data-bs-theme="{theme}"].

This PR also shows how to fix an issue in our components; for instance where a light accordion is declared within a dark div, its icons have not the right color because we only had the following rule:

@if $enable-dark-mode {
  @include color-mode(dark) {
    .accordion-button::after {
      --#{$prefix}accordion-btn-icon: #{escape-svg($accordion-button-icon-dark)};
      --#{$prefix}accordion-btn-active-icon: #{escape-svg($accordion-button-active-icon-dark)};
    }
  }
}

This issue can be seen in this CodePen

Because of the CSS cascade order, it seems not possible to specify the CSS var with a class because the priority between nested data themes can mess up everything. The idea is to declare those specific CSS variables at the root level:

@include color-mode(light, true) {
  --#{$prefix}accordion-btn-icon: #{escape-svg($accordion-button-icon)};
  --#{$prefix}accordion-btn-active-icon: #{escape-svg($accordion-button-active-icon)};
}

@if $enable-dark-mode {
  @include color-mode(dark, true) {
    --#{$prefix}accordion-btn-icon: #{escape-svg($accordion-button-icon-dark)};
    --#{$prefix}accordion-btn-active-icon: #{escape-svg($accordion-button-active-icon-dark)};
  }
}

This code could have been written in _root.scss since it's a global rule but if we do that for the accordions, when a custom CSS build will be made, the user will have extra useless CSS variables.

In order to check everything, I've create a temporary (or not?) example page: https://deploy-preview-39295--twbs-bootstrap.netlify.app/docs/5.3/examples/dark-mode/

Type of changes

  • [x] Refactoring (non-breaking change)

Checklist

  • [x] I have read the contributing guidelines
  • [x] My code follows the code style of the project (using npm run lint)
  • [x] My change introduces changes to the documentation
  • (N/A) I have updated the documentation accordingly
  • [x] I have added tests to cover my changes
  • [x] All new and existing tests passed

Live previews

  • https://deploy-preview-39295--twbs-bootstrap.netlify.app/docs/5.3/examples/
  • https://deploy-preview-39295--twbs-bootstrap.netlify.app/docs/5.3/examples/dark-mode/

Related issues

  • Closes #39138

  • #39765 might be closed depending on the final content of this PR

  • Closes #39915 (might be closed depending on the final content of this PR and the associated explanation)

  • #40414 might be closed by this PR

  • [ ] TODO

julien-deramond avatar Oct 13 '23 13:10 julien-deramond

Note to revisit #39977 after I merge it for v5.3.4.

mdo avatar Apr 03 '25 06:04 mdo

Currently when building with $color-mode-type: media-query; the generated output is void of any [data-bs-theme= (as one would expect) ... except the first set of :root. This is because _root.scss has it hard-coded:

:root,
[data-bs-theme] {
//...

This injects the data tag, ignoring both $enable-dark-mode and $color-mode-type ... even though these are then later used in the dark selection.

May I suggest a localised mixin to remediate this? So the top of _root.scss will be:

@mixin root_root() {
  @if not $enable-dark-mode or $color-mode-type == "media-query" {
    :root {
      @content;
    }
  } @else {
    :root,
    [data-bs-theme="light"] {
      @content;
    }
  }
}

@include root_root() {
  color-scheme: light;

  // Note: Custom variable values only support SassScript inside `#{}`.
//...

Output stays the same for normal/default compile but makes for a cleaner CSS with $enable-dark-mode and $color-mode-type variations. (Obviously come up with a better name than root_root :grimacing: )

(Can also be done in #41232 ?)

[EDIT] Ummmm.. seems carousel, close and navbar also have hardcoded data-bs-theme :frowning:

silvinor avatar Jul 27 '25 13:07 silvinor