【Figma Tokens × Style Dictionary】デザインシステムはじめの一歩
内容
Figma Tokens
で定義したデザイントークンをReact
等のフロント側で使いやすくする
※Figma Tokens は Tokens Studio に名前が変わりました。
簡単!5steps
- 必要packageのinstall
-
install
- Figma Tokensはここからinstall
-
Token Transformer
とStyle Dictionary
のinstall
$ npm install -D token-transformer $ npm install -D style-dictionary
-
- Figma Tokensからjsonファイルを生成
-
Include parent key
のチェックONでExport
-
- jsonファイルをStyle Dictionaryで変換できるようにする
-
token-transformer
$ node token-transformer tokens.json output.json or $ ./node_modules/.bin/token-transformer tokens.json output.json
-
- Style Dictionaryのconfig.jsonを定義
-
config.json
style-dictionary.config.json{ "source": ["output.json"], "platforms": { "scss": { "buildPath": "src/tokens/", "transformGroup": "scss", "files": [{ "destination": "tokens.scss", "format": "scss/map-deep", "mapName":"css-tokens", "options": { "outputReferences": true } }] }, "ts": { "buildPath": "src/tokens/", "transformGroup": "js", "files": [ { "format": "javascript/module", "destination": "tokens.js" }, { "format": "typescript/module-declarations", "destination": "tokens.d.ts" } ] } } }
-
- Style Dictionaryでscssやjsファイルを生成
-
build
configファイルに別名をつけている場合は
--config
を指定$ style-dictionary build --config style-dictionary.config.json
npm-run-allを使用して、jsonの変換とtokenの生成をまとめてやってもいいかもしれません。
package.json"tokne:genJson": "./node_modules/.bin/token-transformer tokens.json output.json", "token:genToken": "style-dictionary build --config style-dictionary.config.json", "token": "run-s tokne:genJson token:genToken"
-
少し詳しく
そもそもデザイントークンとは?
いろんなところで使った方がいいよ!って言われています。
- Material Design 3 - Design tokens
- Goldman Sachs - Color Tokens
- Adobe Blog - デザイナーと開発者の連携を効率化するデザイントークンとは何か?
Figma Tokens
Figma TokensをFigma上で開いた時の画面は以下。
プラスアイコンを押すことでTokenを追加できます。
Color Token追加時の画面。カラーコード指定等ができます。
既存Tokenを指定する際は中括弧で指定します。e.g.{color.palette.red.060}
Tokenを設定したらjsonファイルをエクスポートします。
設定は特に変更せず、Include parent key: on
のままで大丈夫です。
ダウンロード時のファイルはtokens.json
です。
ダウンロードしたファイルは以下のような内容です。
以下のファイルをpackage.json
と同じ階層に配置しましょう。
token.json
{
"global": {
"space": {
"refs": {
"8": {
"value": "8",
"type": "spacing"
}
}
},
"color": {
"palette": {
"red": {
"070": {
"value": "#A1160A",
"type": "color"
},
"060": {
"value": "#D91F11",
"type": "color"
},
"050": {
"value": "#FA5343",
"type": "color"
}
},
"blue": {
"070": {
"value": "#0D4EA6",
"type": "color"
},
"060": {
"value": "#186ADE",
"type": "color"
},
"050": {
"value": "#3D8DF5",
"type": "color"
}
}
},
"button": {
"primary": {
"value": "{color.palette.blue.060}",
"type": "color"
},
"destructive": {
"value": "{color.palette.red.060}",
"type": "color"
}
}
}
}
}
Token Transformer
Figmaからダウンロードしたjsonファイルはエイリアスを含んでいるためtoken-transformer
を用いて変換します。
まずはinstall。
$ npm install -D token-transformer
変換は以下のコマンドを実行するだけです。
output.json
が変換後のファイル名となります。
$ node token-transformer tokens.json output.json
nodeのpathを通していなければ以下で実行できるかと思います。
$ ./node_modules/.bin/token-transformer tokens.json output.json
Style Dictionary
Style Dictionaryにはconfigファイルが必要なので準備します。
package.json
と同じ階層にstyle-dictionary.config.json
を作成します。
output.json
をどのように変換するかを定義します。
今回はscss
とjs
ファイルを生成します。
以下のリンクは参考にした公式のフォーマットページです。
buildPath
のディレクトリにdestination
で指定したファイル名で生成することが出来ます。
{
"source": ["output.json"],
"platforms": {
"scss": {
"buildPath": "src/tokens/",
"transformGroup": "scss",
"files": [{
"destination": "tokens.scss",
"format": "scss/map-deep",
"mapName":"css-tokens",
"options": {
"outputReferences": true
}
}]
},
"ts": {
"buildPath": "src/tokens/",
"transformGroup": "js",
"files": [
{
"format": "javascript/module",
"destination": "tokens.js"
},
{
"format": "typescript/module-declarations",
"destination": "tokens.d.ts"
}
]
}
}
}
次のコマンドを実行することで指定したファイルを生成できます。
$ style-dictionary build --config style-dictionary.config.json
生成されたファイルは以下。
tokens.scss
/**
* Do not edit directly
* Generated on Tue, 05 Apr 2022 10:35:30 GMT
*/
$color-button-destructive: #d91f11 !default;
$color-button-primary: #186ade !default;
$color-palette-blue-050: #3d8df5 !default;
$color-palette-blue-060: #186ade !default;
$color-palette-blue-070: #0d4ea6 !default;
$color-palette-red-050: #fa5343 !default;
$color-palette-red-060: #d91f11 !default;
$color-palette-red-070: #a1160a !default;
$space-refs-8: 8 !default;
$css-tokens: (
'space': (
'refs': (
'8': $space-refs-8
)
),
'color': (
'palette': (
'red': (
'070': $color-palette-red-070,
'060': $color-palette-red-060,
'050': $color-palette-red-050
),
'blue': (
'070': $color-palette-blue-070,
'060': $color-palette-blue-060,
'050': $color-palette-blue-050
)
),
'button': (
'primary': $color-button-primary,
'destructive': $color-button-destructive
)
)
);
tokens.d.ts
/**
* Do not edit directly
* Generated on Tue, 05 Apr 2022 10:35:30 GMT
*/
export default tokens;
declare interface DesignToken {
value: any;
name?: string;
comment?: string;
themeable?: boolean;
attributes?: {
category?: string;
type?: string;
item?: string;
subitem?: string;
state?: string;
[key: string]: any;
};
[key: string]: any;
}
declare const tokens: {
"space": {
"refs": {
"8": DesignToken
}
},
"color": {
"palette": {
"red": {
"070": DesignToken,
"060": DesignToken,
"050": DesignToken
},
"blue": {
"070": DesignToken,
"060": DesignToken,
"050": DesignToken
}
},
"button": {
"primary": DesignToken,
"destructive": DesignToken
}
}
}
tokens.js
/**
* Do not edit directly
* Generated on Tue, 05 Apr 2022 10:35:30 GMT
*/
module.exports = {
"space": {
"refs": {
"8": {
"value": 8,
"type": "spacing",
"filePath": "output.json",
"isSource": true,
"original": {
"value": 8,
"type": "spacing"
},
"name": "SpaceRefs8",
"attributes": {
"category": "space",
"type": "refs",
"item": "8"
},
"path": [
"space",
"refs",
"8"
]
}
}
},
"color": {
"palette": {
"red": {
"070": {
"value": "#a1160a",
"type": "color",
"filePath": "output.json",
"isSource": true,
"original": {
"value": "#A1160A",
"type": "color"
},
"name": "ColorPaletteRed070",
"attributes": {
"category": "color",
"type": "palette",
"item": "red",
"subitem": "070"
},
"path": [
"color",
"palette",
"red",
"070"
]
},
"060": {
"value": "#d91f11",
"type": "color",
"filePath": "output.json",
"isSource": true,
"original": {
"value": "#D91F11",
"type": "color"
},
"name": "ColorPaletteRed060",
"attributes": {
"category": "color",
"type": "palette",
"item": "red",
"subitem": "060"
},
"path": [
"color",
"palette",
"red",
"060"
]
},
"050": {
"value": "#fa5343",
"type": "color",
"filePath": "output.json",
"isSource": true,
"original": {
"value": "#FA5343",
"type": "color"
},
"name": "ColorPaletteRed050",
"attributes": {
"category": "color",
"type": "palette",
"item": "red",
"subitem": "050"
},
"path": [
"color",
"palette",
"red",
"050"
]
}
},
"blue": {
"070": {
"value": "#0d4ea6",
"type": "color",
"filePath": "output.json",
"isSource": true,
"original": {
"value": "#0D4EA6",
"type": "color"
},
"name": "ColorPaletteBlue070",
"attributes": {
"category": "color",
"type": "palette",
"item": "blue",
"subitem": "070"
},
"path": [
"color",
"palette",
"blue",
"070"
]
},
"060": {
"value": "#186ade",
"type": "color",
"filePath": "output.json",
"isSource": true,
"original": {
"value": "#186ADE",
"type": "color"
},
"name": "ColorPaletteBlue060",
"attributes": {
"category": "color",
"type": "palette",
"item": "blue",
"subitem": "060"
},
"path": [
"color",
"palette",
"blue",
"060"
]
},
"050": {
"value": "#3d8df5",
"type": "color",
"filePath": "output.json",
"isSource": true,
"original": {
"value": "#3D8DF5",
"type": "color"
},
"name": "ColorPaletteBlue050",
"attributes": {
"category": "color",
"type": "palette",
"item": "blue",
"subitem": "050"
},
"path": [
"color",
"palette",
"blue",
"050"
]
}
}
},
"button": {
"primary": {
"value": "#186ade",
"type": "color",
"filePath": "output.json",
"isSource": true,
"original": {
"value": "#186ADE",
"type": "color"
},
"name": "ColorButtonPrimary",
"attributes": {
"category": "color",
"type": "button",
"item": "primary"
},
"path": [
"color",
"button",
"primary"
]
},
"destructive": {
"value": "#d91f11",
"type": "color",
"filePath": "output.json",
"isSource": true,
"original": {
"value": "#D91F11",
"type": "color"
},
"name": "ColorButtonDestructive",
"attributes": {
"category": "color",
"type": "button",
"item": "destructive"
},
"path": [
"color",
"button",
"destructive"
]
}
}
}
};
あとは使用したい箇所でimportして使うだけ!
Discussion