Search code examples
ruby-on-rails-7dart-sass

Sharing variables between shared files using @use


Currently migrating from sass to dart-sass. Using @use and @forward is not a problem for any *.scss file outside shared folder.

Problem: When to stylesheets/shared/_variables.scss add @use "functions" as *; as it uses function example-ui-color, getting:

Question:
Is there some different approach to achieve this?

Error: Module loop: this module is already being loaded.
  ┌──> app/assets/stylesheets/shared/_functions.scss
1 │ @use "variables" as *;
  │ ^^^^^^^^^^^^^^^^^^^^^ new load
  ╵
  ┌──> app/assets/stylesheets/example/example.scss
1 │ @use "shared/variables" as *;
 |   │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ original load
 |   ╵
 |   shared/_functions.scss 1:1                        @use
 |   shared/_variables.scss 3:1                        @use
 |   app/assets/stylesheets/example/example.scss 1:1  @use
 |   app/assets/stylesheets/application.scss 2:1       root stylesheet

File structure:

stylesheets/shared/
  _functions.scss
  _mixins.scss
  _variables.scss
stylesheets/example/
  example.scss
stylesheets/application.scss
// stylesheets/shared/_functions.scss

@use "variables" as *;
@use "sass:map";

@function example-ui-color($color, $variant: 'normal') {
  @return map.get(map.get($example-ui, $color), $variant);
}
// stylesheets/shared/_mixins.scss

@use "variables" as *;
@use "sass:list";
@use "sass:map";

@mixin break($size) {
  @media (min-width: map.get($breakpoints, $size)) {
    @content;
  }
}
// stylesheets/shared/_variables.scss
@use "functions" as *; // when add this, error happens

$example-ui: (
  'grey':   ('lightest': #eeeeee, 'light': #d2d2d2, 'normal': #c1c1c1, 'dark': #999, 'darkest': #3a3a3a),
  'green':  ('lightest': #d7e8c4, 'light': #bde093, 'normal': #6cc04a, 'dark': #28a834, 'darkest': #00833e),
  'blue':   ('lightest': #cce5f4, 'light': #b6c2e9, 'normal': #62b3e5, 'dark': #0b3486, 'darkest': #071d49),
  'red':    ('lightest': #f7eae4, 'light': #f0b3ca, 'normal': #e45385, 'dark': #dd3a76, 'darkest': #f9423a),
  'orange': ('lightest': #ffe1c6, 'light': #ffbe85, 'normal': #f78d2d, 'dark': #e57a18, 'darkest': #d75f00),
);

$breakpoints: (
  xs: 360px,
  sm: 768px,
  md: 992px,
  lg: 1024px
);

$footer_border_top: example-ui-color('blue', 'darkest');

$gap: 16px;
// stylesheets/example/example.scss

@use "shared/variables" as *;
@use "shared/mixins" as *;
@use "shared/functions" as *;

li.responsible-contact a {
  border: 1px solid example-ui-color('grey', 'normal');
}

Solution

  • You are using advanced Sass concepts that I don't use myself but something is quite obvious here :

    • _functions.scss partial uses variables
    • _variables.scss partial uses functions

    It is recursive and you end up in a loop. Basically you have to shape your partials in a way they don't rely on each other.

    for example I have a folder abstracts which contains the following partials :

    • _colors.scss
    • _mixins.scss
    • _responsive.scss
    • _values.scss

    And none of them uses any other partial. Because each of these partials do their own job. For example Colors have only color variables ... They are basically atomic.

    Maybe you can rethink the way you design your SCSS framewok to have it work without any recursion

    One idea is to create a higher level partial that would uses many partials from your shared folder and use this partial instead of the children partials independently.