Skip to content

Instantly share code, notes, and snippets.

@mlaursen
Last active January 25, 2022 22:30
Show Gist options
  • Select an option

  • Save mlaursen/ceeca70cc0000c7cb9803f8a951c8232 to your computer and use it in GitHub Desktop.

Select an option

Save mlaursen/ceeca70cc0000c7cb9803f8a951c8232 to your computer and use it in GitHub Desktop.
The new Sass Module System with react-md

Table of Contents

TODO

How to import react-md files?

Most files can be updated to change @import statements to be @use '...' as *:

-@import '~@react-md/theme/dist/mixins';
+@use '@react-md/theme/dist/mixins' as *;

If you do not add as * to the @use statement, the variables, functions, and mixins within react-md would not be "globally" available. In the example above, you might have to do something like this:

@use '@react-md/theme/dist/mixins';

.example {
  @include react-mdThemeDistMixins.rmd-theme(background, surface);
  
  color: react-mdThemeDistMixins.$rmd-theme-primary;
}

I did not test the example above. I just know that sass will camelCase some parts of the import path if the as part is omitted. You can rename it to something if you'd like manually:

-@use '@react-md/theme/dist/mixins';
+@use '@react-md/theme/dist/mixins' as theme;

 .example {
-  @include react-mdThemeDistMixins.rmd-theme(background, surface);
+  @include theme.rmd-theme(background, surface);
  
-  color: react-mdThemeDistMixins.$rmd-theme-primary;
+  color: theme.$rmd-theme-primary;
 }

How are variables overridden?

Before the new Sass module system, any variable within react-md that was set to !default would be overridden if any imported file defined that variable.

// this would change the primary and secondary theme variables
$rmd-theme-primary: #fd3030;
$rmd-theme-secondary: #000;

@import '~@react-md/theme/dist/mixins';

With the new module system, !default variables can be overridden with the new with syntax:

@use '@react-md/theme/dist/mixins' as * with (
  $rmd-theme-primary: #fd3030,
  $rmd-theme-secondary: #000
);

Overriding react-md variables

TODO

Instead of a src/_variables.scss, create a src/_everything.scss that:

  • defines any scss variables that you need to use in your app that aren't related to react-md
  • @forwards react-md with any overrides required
 $primary-color: #3215fa;
 $secondary-color: #9fa233;

-$rmd-theme-primary: $primary-color;
-$rmd-theme-secondary: $secondary-color;
+@forward 'react-md' with (
+  $rmd-theme-primary: $primary-color,
+  $rmd-theme-secondary: $secondary-color
+);

Switching to the new react-md import

-@import '~@react-md/alert/dist/mixins';
-@import '~@react-md/avatar/dist/mixins';
-@import '~@react-md/button/dist/mixins';
-@import '~@react-md/theme/dist/mixins';
-@import '~@react-md/utils/dist/mixins';
+@use 'react-md' as *;

 @include react-md-utils;

Reusing Variables, Functions, and Mixins throughout your App

// src/_everything.scss
@use '@react-md/theme/dist/color-palette' as colors;
@forward 'react-md' with (
  $rmd-theme-primary: colors.$rmd-blue-500,
  $rmd-theme-secondary: colors.$rmd-orange-a-200,
  $rmd-theme-light: true
  // any other react-md overrides
);
// src/app.scss
@use './everything' as *;

/// generate all the react-md styles with your overrides
@include react-md-utils;
// src/components/Example/Example.module.scss
@use '../../everything' as *;

.container {
  @include rmd-utils-scroll;
  @include rmd-elevation(2);
  @include rmd-theme(background, surface);
  @include rmd-theme(color, on-surface);
}

Why @use '../../everything' as *?

Something that might not have been known is that each .scss file gets compiled separately without any context of other .scss files in your app. Switching to @use the _everything.scss file allows all your variable overrides to persist for each file.

If you don't care about the variable overrides, you could just do:

 // src/components/Example/Example.module.scss
-@use '../../everything' as *;
+@use 'react-md' as *;

 .container {
   @include rmd-utils-scroll;
   @include rmd-elevation(2);
   @include rmd-theme(background, surface);
   @include rmd-theme(color, on-surface);
 }

However, this is not recommended since it could lead to bugs in the future since some variables change internally within react-md based on your overrides.

Using the new react-md import

Part of the v3.0.0 release was to create a new Sass import that merges all the .scss files into one for two reasons:

  1. This simplifies importing things from react-md into a single @use statement instead of multiple lines
  2. Drastically improves build performance in large projects because only one .scss file needs to be resolved.

As mentioned above, sass-loader with webpack does not maintain context of other .scss files in your app. Each time you import './path/to/my.scss'; or import styles from './path/to/my.module.scss';, sass-loader will need to resolve every @import or @use statement found in that file recursively. The IO required for this is the whole reason build times can get slow in larger projects since there are about 200 .scss files within react-md that would need to be resolved. Combining all the files as a build step within react-md removes this issue and drastically increases build performance.

If you want to use these new changes, either:

  • follow the steps above with the _everything.scss file and update all your files to just @use './path/to/everything' as *; instead of @use '@react-md/{{PACKAGE}}/dist/mixins' as *;

    -@import '~@react-md/alert/dist/mixins';
    -@import '~@react-md/app-bar/dist/mixins';
    -@import '~@react-md/avatar/dist/mixins';
    -@import '~@react-md/badge/dist/mixins';
    -@import '~@react-md/button/dist/mixins';
    -@import '~@react-md/card/dist/mixins';
    -@import '~@react-md/chip/dist/mixins';
    -@import '~@react-md/dialog/dist/mixins';
    -@import '~@react-md/divider/dist/mixins';
    -@import '~@react-md/elevation/dist/mixins';
    -@import '~@react-md/expansion-panel/dist/mixins';
    -@import '~@react-md/form/dist/mixins';
    -@import '~@react-md/icon/dist/mixins';
    -@import '~@react-md/layout/dist/mixins';
    -@import '~@react-md/link/dist/mixins';
    -@import '~@react-md/list/dist/mixins';
    -@import '~@react-md/media/dist/mixins';
    -@import '~@react-md/menu/dist/mixins';
    -@import '~@react-md/overlay/dist/mixins';
    -@import '~@react-md/progress/dist/mixins';
    -@import '~@react-md/sheet/dist/mixins';
    -@import '~@react-md/states/dist/mixins';
    -@import '~@react-md/table/dist/mixins';
    -@import '~@react-md/tabs/dist/mixins';
    -@import '~@react-md/theme/dist/mixins';
    -@import '~@react-md/tooltip/dist/mixins';
    -@import '~@react-md/transition/dist/mixins';
    -@import '~@react-md/tree/dist/mixins';
    -@import '~@react-md/typography/dist/mixins';
    -@import '~@react-md/utils/dist/mixins';
    +@use './path/to/everything' as *;
  • remove all @import and @use statements in a file and replace with `@use 'react-md' as *';

    -@import '~@react-md/alert/dist/mixins';
    -@import '~@react-md/app-bar/dist/mixins';
    -@import '~@react-md/avatar/dist/mixins';
    -@import '~@react-md/badge/dist/mixins';
    -@import '~@react-md/button/dist/mixins';
    -@import '~@react-md/card/dist/mixins';
    -@import '~@react-md/chip/dist/mixins';
    -@import '~@react-md/dialog/dist/mixins';
    -@import '~@react-md/divider/dist/mixins';
    -@import '~@react-md/elevation/dist/mixins';
    -@import '~@react-md/expansion-panel/dist/mixins';
    -@import '~@react-md/form/dist/mixins';
    -@import '~@react-md/icon/dist/mixins';
    -@import '~@react-md/layout/dist/mixins';
    -@import '~@react-md/link/dist/mixins';
    -@import '~@react-md/list/dist/mixins';
    -@import '~@react-md/media/dist/mixins';
    -@import '~@react-md/menu/dist/mixins';
    -@import '~@react-md/overlay/dist/mixins';
    -@import '~@react-md/progress/dist/mixins';
    -@import '~@react-md/sheet/dist/mixins';
    -@import '~@react-md/states/dist/mixins';
    -@import '~@react-md/table/dist/mixins';
    -@import '~@react-md/tabs/dist/mixins';
    -@import '~@react-md/theme/dist/mixins';
    -@import '~@react-md/tooltip/dist/mixins';
    -@import '~@react-md/transition/dist/mixins';
    -@import '~@react-md/tree/dist/mixins';
    -@import '~@react-md/typography/dist/mixins';
    -@import '~@react-md/utils/dist/mixins';
    +@use 'react-md' as *;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment