この記事の概要
Config 2023 で発表された Variables は非常に便利そうでした。
新しいもの好きな方なら、まず試してみたくなるような内容です。
ただ、既存のデータでガッチリと Styles を組んでいると、手動での移行が大変そうだなあ……と思った方もいるのではないでしょうか?
ご安心ください。
公式から Styles -> Variables 変換用のコードが提供されています。
事前知識が無いと若干難しそうだったので、やり方をこの記事で解説します。
やることの概要
- 空の Plugin を作成する
- 公式から出ているコードをコピペする
- Plugin を実行する
説明するを考えた際、まずはコピペが一番分かりやすそうに思えたのでこのやり方を紹介しています。
あまり美しいやり方ではありませんがご了承ください。
また、前提として今回は説明用にこちらのデータを用意しました。
味気ないですが、次のように Color styles を定義しています。
- white
- black
- red
- light
- medium
- dark
空の Plugin を作成する
plugin を通して、既存の styles を variables へと変換します。
そのためまずは新規に作成します。
Toolbar の Resources
をクリックし、 Plugins
タブを開きます。
すぐ下のドロップダウンから Development
を選びます。
+ New
をクリックし、 New plugin...
をクリックします。
Name
には適当な名前(ここでは styles-to-variables
)を入れて、 Figma design
だけの方にチェックを入れて、 Next
をクリックします。
Run once
にチェックを入れ、 Save as
をクリックします。
保存先を聞かれるので、適当なフォルダーを指定します。
ひとまずはこれで完了です。
Done
でウインドウを閉じてしまって構いません。
公式から出ているコードをコピペする
先ほど作成したフォルダーを開くと、次のようなコードの構成になっています。
- .gitignore
- code.js
- code.ts
- manifest.json
- package.json
- README.md
- tsconfig.json
次に、公式の plugin-samples
というリポジトリの中に、 styles-to-variables
があるのでアクセスします。
この code.js
を自分のフォルダーにある code.js
にまるっとコピペします。
Figma Plugin は TypeScript で書いて JavaScript へ変換するのがスタンダードです。ただ、今回は見本のコードが JavaScript でしか提供されていないのと、とにかく簡単に Styles を Variables に変換するのをゴールとしているため、こんな無茶苦茶なやり方をします。くれぐれも日頃の Plugin 開発では真似しないでください。
Plugin を実行する
ここまで来たら終わったも同様です。
Figma に戻り Plugin を開くと、自分が作ったものが Run
可能になっています。
実行した後に Variables
を確認するとこの通り。
white
と black
はトップレベルに、 red
は 1 つ階層を作って、元々の Styles
と同様の構成で登録されました。
余談: TypeScript 化
いくら「細かいことは良いから」なんて記事タイトルにしても、せっかく TypeScript で書けるならそちらで書きたい気持ちはあります。
というわけで、ひとまずエラーが出なくなるようにだけ変えました。
そもそもの処理を変えた方が良い箇所もあるのかもなあ……と思いつつ、私の実力ではそこまで及ばないので今回はここで終わりとします。
console.clear();
+ type TokenData = {
+ color: RGB;
+ hex: string;
+ opacity: number;
+ tokens: string[];
+ };
- const styles = figma.getLocalPaintStyles();
- const tokenDataMap = styles.reduce(styleToTokenDataMap, {});
- const tokenData = Object.values(tokenDataMap);
+ const styles: PaintStyle[] = figma.getLocalPaintStyles();
+ const tokenDataMap: { [key: string]: TokenData } = styles.reduce(styleToTokenDataMap, {});
+ const tokenData: TokenData[] = Object.values(tokenDataMap);
createTokens(tokenData);
- function createTokens(tokenData) {
+ function createTokens(tokenData: TokenData[]): void {
if (tokenData.length <= 0) {
figma.notify("No convertible styles found. :(");
return;
}
- const collection = figma.variables.createVariableCollection(`Style Tokens`);
- let aliasCollection;
+ const collection: VariableCollection = figma.variables.createVariableCollection(`Style Tokens`);
+ let aliasCollection: VariableCollection | undefined;
const modeId = collection.modes[0].modeId;
- function styleToTokenDataMap(into, current) {
- const paints = current.paints.filter(
+ function styleToTokenDataMap(into: { [key: string]: TokenData }, current: PaintStyle): { [key: string]: TokenData } {
+ const paints = (current.paints as SolidPaint[]).filter(
({ visible, type }) => visible && type === "SOLID"
);
- function rgbToHex({ r, g, b }) {
- const toHex = (value) => {
+ function rgbToHex({ r, g, b }: RGB) {
+ const toHex = (value: number) => {
const hex = Math.round(value * 255).toString(16);
return hex.length === 1 ? "0" + hex : hex;
};