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.
Swatch | Name | Utility class | Hex |
---|
Themes
This example didn’t take different themes into consideration. There are several ways to go about that.
- 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;
}
}
- 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