A CLI toolkit for aiding design tokens adoption.
$ npm install -g tempera
$ yarn add global tempera
Note: This package is experimental. You may have better success by running the command locally:
USAGE
$ git clone https://github.com/michaelmang/tempera.git
$ yarn install
$ ./bin/run [COMMAND]
Gather metrics around the adoption of a design system.
USAGE
$ tempera scorecard -s https://www.figma.com/developers -t ./tokens.js
OPTIONS
-s, --site=site site url to analyze
-t, --tokens=tokens relative path to tokens file
-j, --json=json (optional) flag to enable printing output as a JSON blob; requires -o, --output to be set
-o, --output=output (optional) relative path for a JSON file to output; requires -j, --json to be enabled
DESCRIPTION
...
Scorecard analyzes a web app or web page,
collecting design system adoption metrics
and insights for adoption.
Design tokens are key-value pairs that represent a specification (aka "spec") of a design system.
If you are new to design tokens, here's a good place to start.
Tempera's scorecard
command expects these tokens to be in the javascript/es6 format which you can generate using Style Dictionary except exported as CommonJS modules.
In other words, flat CommonJS modules in PascalCase are expected.
Example:
module.exports.ColorBackgroundBase = "#ffffff";
module.exports.ColorBackgroundAlt = "#fcfcfcfc";
Support for tokens in ES6 format is on the roadmap.
The scorecard
command expects the tokens to match against one of the following matchers after being transformed to kebab case:
module.exports.BORDER_RADIUS = /border-radius/g;
module.exports.BREAKPOINT = /max-width/g;
module.exports.COLOR = /color/g;
module.exports.DELAY = /delay/g;
module.exports.DURATION = /duration/g;
module.exports.FONT_FAMILY = /font-family/g;
module.exports.FONT_SIZE = /font-size/g;
module.exports.FONT_WEIGHT = /font-weight/g;
module.exports.LINE_HEIGHT = /line-height/g;
module.exports.SPACING = /margin|padding/g;
module.exports.TIMING = /timing/g;
You can learn more about the underlying css-types
package that utilizes these matchers.
Useful for creating custom reporters and tooling.
USAGE
$ tempera scorecard -s https://www.figma.com/developers -t ./tokens.js -j -o report.json
{
"unofficial": [
{
"type": "border-radius",
"attribute": "border-radius",
"unofficialValue": "0.500rem",
"nearestOfficialValue": "0.375rem"
},
// ...
],
"summary": [
{ "category": "Font Family", "correct": 0, "incorrect": 79, "percentage": "0.00" },
{ "category": "Color", "correct": 159, "incorrect": 195, "percentage": "44.92" },
{ "category": "Font Size", "correct": 73, "incorrect": 104, "percentage": "41.24" },
{ "category": "Spacing", "correct": 264, "incorrect": 322, "percentage": "45.05" },
{ "category": "Max Width", "correct": 1, "incorrect": 25, "percentage": "3.85" },
{ "category": "Line Height", "correct": 112, "incorrect": 14, "percentage": "88.89" },
{ "category": "Border Radius", "correct": 16, "incorrect": 13, "percentage": "55.17" },
{ "category": "Font Weight", "correct": 78, "incorrect": 2, "percentage": "97.50" }
],
"total": { "correct": 703, "incorrect": 754, "percentage": "48.25", "grade": "F" }
}
$ tempera --help [COMMAND]
USAGE
$ tempera COMMAND
🤠Howdy, developer! Thanks for being willing to contribute!
- Fork and clone the repo
- Run
yarn install
to install dependencies - Create a branch for your PR with
git checkout -b pr/your-branch-name
- Run
.bin/run/ [COMMAND]
in the root of the repo to run commands locally
Tip: Keep your
master
branch pointing at the original repository and make pull requests from branches on your fork. To do this, run:git remote add upstream https://github.com/michaelmang/tempera.git git fetch upstream git branch --set-upstream-to=upstream/master master
There are currently no tests but please document manual testing on PRs with your changes.
Please checkout the the open issues.
Also, please watch the repo and respond to questions/bug reports/feature requests! Thanks!
In addition to a CLI, Tempera offers other tools to improve design tokens adoption.
A Stylelint plugin that helps avoid the adoption of unofficial design specifications.
yarn add @tempera/stylelint-tokens
Install Stylelint and update your configuration file to utilize the plugin.
// stylelint.config.js
const tokens = require("./fixtures/example-tokens");
module.exports = {
// ...
plugins: ["@tempera/stylelint-tokens"],
rules: {
"@tempera/official-specs": tokens,
},
};
The plugin expects these tokens to be in the javascript/es6 format which you can generate using Style Dictionary except exported as CommonJS modules.
In other words, flat CommonJS modules in PascalCase are expected.
Example:
module.exports.ColorBackgroundBase = "#ffffff";
module.exports.ColorBackgroundAlt = "#fcfcfcfc";
Support for tokens in ES6 format is on the roadmap.
The underlying packages that support Tempera are publicly accessible.
You are welcome and encouraged to use these packages directly should you need a custom solution.
🚀 Contributing to these packages is also welcome.
Utilities to categorize your CSS.
yarn add @tempera/css-types
const {
// Example: matchers.SPACING
// Contains a list of regex matchers to help match common types in CSS
matchers,
// example: getMatcher(postcssProperty)
// Returns a regex matcher fitting for the provided property
getMatcher,
// Example: types.SPACING
// Contains a list of common types in CSS
types,
// Example: getType(postcssProperty)
// Returns a common type fitting for the provided property
getType,
} = require("@tempera/css-types");
A PostCSS plugin that exposes hooks into design token adoption validation.
yarn add @tempera/postcss-scorecard
const pxToRem = require("postcss-pxtorem");
const expandShorthand = require("postcss-shorthand-expand");
await postcss()
.use(pxToRem())
.use(expandShorthand)
.use(
scorecard({
onInvalid: (score) => {
// do something when CSS property is not an official spec
},
onValid: (score) => {
// do something when CSS property is an official spec
},
onFinished: () => {
// do something after validation finishes
},
specs, // the official design tokens
})
)
.process(css, { from: undefined });
The plugin expects these specs/tokens to be in the javascript/es6 format which you can generate using Style Dictionary except exported as CommonJS modules.
In other words, flat CommonJS modules in PascalCase are expected.
Example:
module.exports.ColorBackgroundBase = "#ffffff";
module.exports.ColorBackgroundAlt = "#fcfcfcfc";
Support for tokens in ES6 format is on the roadmap.
An API that generates a Tailwind configuration from a set of design tokens.
yarn add @tempera/tailwind-config
import getTailwindConfig from "@tempera/tailwind-config";
const tailwindConfig = getTailwindConfig(tokens);
// do something with the tailwind config
The plugin expects these specs/tokens to be in the javascript/es6 format which you can generate using Style Dictionary.
In other words, flat modules in PascalCase are expected.
Example:
export const ColorPrimary = blue;
export const ColorSecondary = yellow;
An API that generates a Twind instance from a set of design tokens.
yarn add @tempera/twind
import getTwind from "@tempera/twind";
const { tw } = getTwind(tokens);
function Demo() {
return (
<div className={tw`text-primary`}>
);
}
The plugin expects these specs/tokens to be in the javascript/es6 format which you can generate using Style Dictionary.
In other words, flat modules in PascalCase are expected.
Example:
export const ColorPrimary = blue;
export const ColorSecondary = yellow;
An API that generates twind/style shapes from a set of design tokens.
yarn add @tempera/stitches
import getStitches from '@tempera/stitches';
import getTwind from '@tempera/twind';
import { style } from 'twind/style';
import tokens from './tokens';
const stitches = getStitches(tokens);
const { tw } = getTwind(tokens);
function Demo() {
const button = style(stitches.button);
return (
<div>
<button className={tw(button())}>Base Button</button>
<button className={tw(button({ variant: 'secondary' }))}>
Secondary Button
</button>
</div>
);
}
The plugin expects these specs/tokens to be in the javascript/es6 format which you can generate using Style Dictionary.
In other words, flat modules in PascalCase are expected.
The tokens should follow the following format:
// base format
export const Component[COMPONENT]Base[LONGHAND_CSS_PROPERTY];
// size format
export const Component[COMPONENT][SIZE][LONGHAND_CSS_PROPERTY];
// variant format
export const Component[COMPONENT][VARIANT][UI_STATE][LONGHAND_CSS_PROPERTY];
Examples:
export const ComponentButtonBaseFontSize = '1rem';
export const ComponentButtonBaseColor = 'red';
export const ComponentButtonSmallFontSize = '0.75rem';
export const ComponentButtonSecondaryDefaultBackgroundColor = 'red';
export const ComponentButtonSecondaryDefaultColor = 'white';
export const ComponentButtonSecondaryDefaultFontSize = '0.875rem';
export const ComponentButtonSecondaryHoverFontSize = '0.75rem';
export const ColorPrimary = 'red';
export const ColorWhite = 'white';
export const FontSizeTiny = '0.75rem';
export const FontSizeSmall = '0.875rem';
export const FontSizeMedium = '1rem';
export const LineHeightTiny = '1rem';
export const LineHeightSmall = '1.25rem';
export const LineHeightMedium = '1.5rem';