4

I want to implement theming in my react application. Therefore I used this tutorial (sass-mixins).

But this doesn't work in combination with css-modules, since the the theming class is outside of the css-module I want to theme.

Does anyone have a workaround for this problem or another approach to theme a react application using sass?

App.js

const theme = require('../../Theming.sass)

<div class={theme['theme-dark'}>
  <SearchBar/>
  ...
</div>

SearchBar.js

const styles = require('./SearchBar.scss)
const theme = require('../../Theming.sass)

<div class={styles.searchBar}>
  ...
</div>

SearchBar.scss

.searchBar {
  @include themify($themes) {
    color: themed('primary');
    background: themed('secondary');
  }

  height: 3em;
  overflow: hidden;

SearchBar.css (compiled)

.searchBar {
  height: 3em;
  overflow: hidden;
}

.theme-light .searchBar {
  color: #fff;
  background: #bfbfbf;
}

.theme-dark .searchBar {
  color: #000;
  background: #1a1a1a;
}

Theming.sass

.theme-dark { background: #000; }

.theme-light { background: #fff; }

$themes: (
  light: (
    primary: #fff,
    secondary: #bfbfbf,
  ),
  dark: (
    primary: #000,
    secondary: #1a1a1a,
  ),
);

@function themed($key) {
  @return map-get($theme-map, $key);
}

@mixin themify($themes: $themes) {
  @each $theme, $map in $themes {

    .theme-#{$theme} & { /* HOW TO USE CSS-MODULES HERE ?*/
      $theme-map: () !global;
      @each $key, $submap in $map {
        $value: map-get(map-get($themes, $theme), '#{$key}');
        $theme-map: map-merge($theme-map, ($key: $value)) !global;
      }

      @content;
      $theme-map: null !global;
    }

  }
}

2 Answers 2

8

I had a similar issue, I am using SASS with CSS modules in a React app and I ended up using the theme class as a global class and not using CSS modules because every time I used the mixin it added the module prefix to the style.

I added :global to the theme class in the mixin:

@mixin themify($themes: $themes) {
  @each $theme, $map in $themes {

    :global(.theme-#{$theme}) & { 
      $theme-map: () !global;
      @each $key, $submap in $map {
        $value: map-get(map-get($themes, $theme), '#{$key}');
        $theme-map: map-merge($theme-map, ($key: $value)) !global;
      }

      @content;
      $theme-map: null !global;
    }

  }
}

And I specified the class directly in my JSX in App.js:

<div class="theme-dark">
  <SearchBar/>
  ...
</div>

I hope this helps someone.

Sign up to request clarification or add additional context in comments.

Comments

1

You also need to import .theme-dark through css-modules.

Should be something like:

<div class={styles.themeDark}>
  <SearchBar/>
  ...
</div>

You should also use sass-resources-loader for it: https://github.com/shakacode/sass-resources-loader

2 Comments

Thats a great hint. But I think I have to use the css-modules inside the mixins functions. I updated the question and marked the line inside the mixins function. Do you know how to use css-modules in this case?
This doesn't work because the mixin adds the raw class .theme-dark. We have to reference the css-module class .theme-dark inside the mixin.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.