Mathias Polligkeit
  • Dev
  • Impro
  • Sheet Music
  • Contact
Nov 25, 2021 (last updated: Dec 2, 2021)

Design Systems, Pt. 6: Variable Export

When creating a design system, a documentation with previews of all the design tokens is very useful. Rather than building a static documentation that has to be updated whenever something is changed, this documentation should be updated automatically from the styles. We’ll concentrate on the first step of exporting the design tokens from the themes we defined.

SASS export

If you use Webpack, you can use Interoperable CSS to export your SASS variables to JavaScript.

On the SASS side, we’ll create a folder called export and add separate SCSS files for the different parts of the theme. We’ll concentrate on the colors in this example.

export/colors.scss looks like this:

@use "../themes/default" as d;

:export {
  @each $key, $value in map.get(d.$theme, colors) {
    #{"" + $key}: $value;
  }
}

Unfortunately, the exported values need to be valid CSS values, which means we cannot export SASS maps directly. Instead, we need to iterate over the map values like illustrated.

Webpack and JavaScript

Add a file called styleguide.js in your JS folder and add this content:

import colors from "../scss/export/_colors.scss";

window.colors = colors;

Here we import the SASS file we just created. For this example, we’ll make the colors object accessible through the window object.

Make sure to add styleguide.js as an entrypoint in your Webpack configuration.

Also, we need to configure css loader to use the icss mode.

{
  loader: "css-loader",
  options: {
    modules: {
      mode: "icss"
    }
  }
}

HTML template

Once all of that is done, you can add something like this to an HTML template:

<table id="styleguide-colors">
  <thead>
    <tr>
      <th>Swatch</th>
      <th>Name</th>
      <th>Utility class</th>
      <th>Hex</th>
    </tr>
  </thead>
  <tbody></tbody>
</table>

<script src="/assets/styleguide.js"></script>

<script>
  const tbody = document.querySelector("#styleguide-colors tbody");

  for (property in colors) {
    let swatch = document.createElement("div");
    swatch.style.width = "64px";
    swatch.style.height = "64px";
    swatch.style.backgroundColor = colors[property];

    let tdSwatch = document.createElement("td");
    tdSwatch.appendChild(swatch);

    let tdName = document.createElement("td");
    tdName.appendChild(document.createTextNode(property));

    let tdUtility = document.createElement("td");
    tdUtility.appendChild(document.createTextNode(".color-" + property));

    let tdValue = document.createElement("td");
    tdValue.appendChild(document.createTextNode(colors[property]));

    let tr = document.createElement("tr");
    tr.appendChild(tdSwatch);
    tr.appendChild(tdName);
    tr.appendChild(tdUtility);
    tr.appendChild(tdValue);

    tbody.appendChild(tr);
  }
</script>

Obviously, this is just the bare minimum to illustrate the solution. In a real application, you would integrate the export into the framework of your choice.

Live demo

The table below is generated with the code above.

SwatchNameUtility classHex

Themes

This example didn’t take different themes into consideration. There are several ways to go about that.

  1. Prefix the keys of the export with the theme name.
@use "../themes/default";
@use "../themes/dark";

:export {
  @each $key, $value in map.get(default.$theme, colors) {
    #{"default-" + $key}: $value;
  }

  @each $key, $value in map.get(dark.$theme, colors) {
    #{"dark-" + $key}: $value;
  }
}
  1. Handle all values for a theme in one separate file.
// export/_default.scss

@use "../themes/default" as t;

:export {
  @each $key, $value in map.get(t.$theme, colors) {
    #{"colors-" + $key}: $value;
  }

  @each $key, $value in map.get(t.$theme, lines) {
    #{"lines-" + $key}: $value;
  }
}

// export/_dark.scss

@use "../themes/dark" as t;

:export {
  @each $key, $value in map.get(t.$theme, colors) {
    #{"colors-" + $key}: $value;
  }

  @each $key, $value in map.get(t.$theme, lines) {
    #{"lines-" + $key}: $value;
  }
}

This would be a good candidate for a mixin.

Alternatives

Instead of exporting the variables from CSS/SASS, you can also directly access the custom properties with JavaScript. Unfortunately, there is no API to retrieve a list of all custom properties, but this article describes a solution around that restriction.

There is also postcss-modules-values, but I don’t know whether it works in combination with SASS variables.

Next part: Design Systems, Pt. 7: Project Structure

  • design-systems
  • sass

See Also

  • Design Systems, Pt. 9: Conclusion
  • Design Systems, Pt. 8: Layout Rules
  • Design Systems, Pt. 7: Project Structure
  • Design Systems, Pt. 5: Themes
  • Design Systems, Pt. 4: Generating Utility Classes
  • privacy policy