tomole
tomole

Reputation: 1006

Theming react app with sass and css modules

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;
    }

  }
}

Upvotes: 4

Views: 4087

Answers (2)

jhadis
jhadis

Reputation: 81

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.

Upvotes: 8

Alexandr Lazarev
Alexandr Lazarev

Reputation: 12882

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

Upvotes: 1

Related Questions