jgthms / bulma

Modern CSS framework based on Flexbox
https://bulma.io
MIT License
48.88k stars 3.93k forks source link

How do I override the colors in the dark theme? #3804

Open alycklama opened 2 months ago

alycklama commented 2 months ago

Is it possible to override the colors in the dark theme? I've tried so many things, and I have yet to find a working or maintainable solution.

Naively, I tried to use the following, but it didn't work:

@include cv.system-theme($name: "dark") {
  $primary: hsl(11, 100%, 41%);

  @include cv.register-hsl("shadow", white);
}

Then I tried the code below, which seems to work fine, however, it doesn't seem to work well with contrasting colours. The has-text-primary-invert has the exact same color in the dark theme if the primary color of the light theme is set to #fff. I'm not entirely sure how the dark theme isn't independent of the light theme. I guess because I'm changing a single color and I'm not using generate-on-scheme-colors?

image
@include cv.system-theme($name: "dark") {
  --bulma-primary: hsl(130, 50, 45);
  --bulma-primary-h: 130deg;
  --bulma-primary-s: 50%;
  --bulma-primary-l: 45%;
}

I had a look in the code base to see how the dark theme is constructed. There I noticed the same color palette is used as for the light theme. I copied all the code below and just changed the primary value. However, this doesn't seem to work at all.

$dark-colors: fn.mergeColorMaps(
  (
    "primary": #ff0000,
  ),
  dv.$custom-colors
) !default;

@include cv.system-theme($name: "dark") {
  @each $name, $color in $dark-colors {
    $base: $color;

    @if type-of($color == "list") {
      $base: list.nth($color, 1);
    }

    @include cv.generate-on-scheme-colors($name, $base, $scheme-main);
  }

  @include cv.register-vars(
    (
      "scheme-brightness": "dark",
    )
  );

  @include cv.register-hsl("shadow", white);
}

Any idea how this is supposed to work idiomatically? Any help is greatly appreciated!

maerteijn commented 1 month ago

@alycklama I've been stumbling on this too. The new recommended way how to customize variables is with @use / @forward combined with a with:

@forward "bulma/sass/utilities/" with (
  $primary: #ff0000  // red
);

But you can only @use / @forward a module with sass once. So defining a different $primary color for the dark theme can't be done without multiple stylesheets. You would need to regenerate the $primary color maps anyway as the dark theme by default only includes the lighting changes / inversions.

So as far as I can tell the only way to do this properly is to override the $primary color using css variables. At least, is how I understand how you should do it according to the documentation, but the docs are not very explicit in most regards and might need more examples.

When we only want to generate a new primary color you can do this like so:

@use "bulma/sass/utilities/css-variables" as cv;

$primary-dark: #00008B; // dark blue

[data-theme=dark], .theme-dark {
  @include cv.register-hsl("primary", $primary-dark);
}

This generates a new primary-h / s / l color for the dark theme. But as there are so many variables with colors generated based on several colors setting adding them all by hand would defeat the purpose of having sass generating this for us in the first place.

We can however regenerate the colors just like themes/light.scss and themes/dark.scss are doing. We only need to call cv.generate-color-palette and cv.generate-on-scheme-colors to (re)generate all the colors based on our new $primary-dark variable.

An example on how this can be solved:

main.scss

// Just include / customize what we need
@forward "bulma/sass/utilities/";
@forward "bulma/sass/base/";
@forward "bulma/sass/elements/content";
@forward "bulma/sass/elements/image";
@forward "bulma/sass/elements/button";
@forward "bulma/sass/helpers/color";

@use "themes";

And a themes.scss like so:

@use "bulma/sass/utilities/css-variables" as cv;

@use "bulma/sass/themes/setup";
@use "bulma/sass/themes/light";
@use "bulma/sass/themes/dark";

$primary-dark: #00008B; // dark blue, <-- the new $primary color for the dark theme

@mixin light-theme-config {
  @include light.light-theme;
}

@mixin dark-theme-config {
  @include dark.dark-theme;

  // Here we register the  `$primary-dark` color as `$primary` for the dark theme only
  @include cv.register-hsl("primary", $primary-dark);
  @include cv.generate-color-palette("primary", $primary-dark);
  @include cv.generate-on-scheme-colors("primary", $primary-dark, dark.$scheme-main);
}

// Setup the light theme as the default theme
:root {
  @include light-theme-config;
  @include setup.setup-theme;
}

// Setup the dark theme and include the prefers-color-scheme: dark and [data-theme=dark], .theme-dark sections
@include cv.system-theme($name: "dark") {
  @include dark-theme-config;
}

@include cv.bulma-theme($name: "dark") {
  @include dark-theme-config;
  @include setup.setup-theme;
}

This will look like the following, with a is-primary and has-text-primary-invert class on the button element and with the blue inverted text color, regenerated withgenerate-color-palette : image image

In case you'd like to see this in action, I've created an example repository which you can find here: https://github.com/maerteijn/bulma-dark-theme-primary/tree/main