2

Scenario :

  • I have an app which in Id like to use 3 different graphical themes.
  • To propagate my themes, I'm using 3 different classes that I apply to my root component,
    let call those classes .themeA, .themeB, .themeC.
    For every themes,
    I have a Sass variable which encapsulate all the colors I need.

For example:

$themeAColors: (
    my-background-color: 'blue';
    my-color: 'green';
);

$themeBColors: (
    my-background-color: 'red';
    my-color: 'yellow';
);

$themeCColors: (
    my-background-color: 'white';
    my-color: 'black';
)

Then in every sub components in which I wish to apply my theme I'm using the following pattern:

@mixin subComponentStyle($theme) {
    .title {
       background-color: map-get($theme, my-background-color);
       color: map-get($theme, my-color);
    }
}

:host-context(.themeA) {
    @include subComponentStyle($themeAColors);
}

:host-context(.themeB) {
    @include subComponentStyle($themeBColors);
}

:host-context(.themeC) {
    @include subComponentStyle($themeCColors);
}



Problem :

  • Is there a way to avoid or factorize the use of :host-context() selector in every sub components AND respecting component style encapsulation ?

Update: Thank you, that is helping simplify things a bit. Now we would like to find a way to avoid copying this block in every sub-components:

@each $param in ($themeAColors, $themeBColors, $themeCColors) {
   $name: map-get($param, name);
   :host-context(#{ $name }) {
       @include subComponentStyle($param);
    }
}

Ideally, we would like to replace this by a function call that would take any mixin in parameter and apply it. So in every components we would just have to call this function with the right mixin to handle theming.

Persijn
  • 14,624
  • 3
  • 43
  • 72
flemgs
  • 55
  • 7
  • On the update: I don't fully understand what your use case is and how your css will be generated to each subcomponent? I'm more used to static pages, and generating a single css file. There are some functions available in sass [function](http://sass-lang.com/documentation/file.SASS_REFERENCE.html#function_directives) but i would advice against using logic to much logic in a stylesheet. – Persijn Nov 30 '18 at 21:09
  • Yes I agree that too much logic in CSS is overkill. But I am not a great fan of copy/paste everywhere the same block of code neither... Ideally I would like to have this block defined in one single place and call it through a function in each components. – flemgs Dec 03 '18 at 14:34

1 Answers1

0

Sass mixin with multiple themes and :host-context

Be careful with the use of :host-context is does not have a lot of support.

After playing around for a while with the sass could i got it to iterate over a list of themes. The themes are then passed down to the mixing.
Used a name variable in the loop so it can get used in the css rule definition.

@mixin subComponentStyle($theme) {
  background-color: map-get($theme, my-background-color);
  color: map-get($theme, my-color);
}

$themeAColors: (
  name: ".themeA",
  my-color: 'blue',
  my-background-color: 'red',
);

$themeBColors: (
  name: ".themeB",
  my-color: 'white',
  my-background-color: 'black',
);

$themeCColors: (
  name: ".themeC",
  my-color: 'Orange',
  my-background-color: '#2a4',
);

@each $param in ($themeAColors, $themeBColors, $themeCColors) {
  $name: map-get($param, name);
  :host-context(#{ $name }) {
    @include subComponentStyle($param);
  }
}

And this compiles to this css:

:host-context(.themeA) {
  background-color: "red";
  color: "blue";
}

:host-context(.themeB) {
  background-color: "black";
  color: "white";
}

:host-context(.themeC) {
  background-color: "#2a4";
  color: "Orange";
}
Persijn
  • 14,624
  • 3
  • 43
  • 72