見出し画像

FigmaプラグインによるFigmaのハックとワークフローの強化

この記事は2022年5月11日に開催されたFigmaのカンファレンス『Config 2022』のセッション内容を記事として再編集した内容ものです


私は医療系テックスタートアップのUbie株式会社でデザインエンジニアをしている谷(@hiloki)です。
この記事では「デザイン業務を少し楽にしたい」そのために自らFigmaプラグインを作ってみたいと考えてもらえるような話をします。

Figmaの特長

FigmaにはAuto LayoutやコンポーネントのVariants、チームでコンポーネントやスタイルを共有するTeam Libraryなどパワフルな機能がたくさんあります。
それら以外で私がFigmaで好きなのは、Figma Communityというコミュニティ機能と、そこに展開されるたくさんのFigma Pluginです。

素晴らしいFigmaプラグインとして、UnsplashやContent Reel等のプラグインの名前を上げている。右側にはそれらのプラグインのキャプチャ

Unsplashから直接Figma上に写真を読み込めるプラグインや、色の組み合わせのコントラスト比をチェックするStark、最近だとDesign Tokensを管理するFigma Tokensも人気です。中にはNicolas Cage Image Replacerのようなコミカルなプラグインがあるのも面白いですね。

プラグインが多すぎる!

プラグインが多すぎることを表した画像。多くのプラグインがリストで並んでいる

本当にたくさんのプラグインがあるので、その中に「自分は欲しいプラグイン」を見つけるのは大変です。それらしいものを見つけても、説明文をみてもよくわからなかったり、インストールしても期待と違うということがよくあります。そんなときはどうすればいいでしょうか?

ないものは作ればいい。
金に困ったら発明すればいい。

円谷 英二

この言葉は『ゴジラ』や『ウルトラマン』といった歴史的な特撮映画に関わった円谷英二さんの言葉です。この言葉がとても好きで、私のモットーであり「ないものを作る」というチャレンジがとても好きなんです。

なので私は自分でプラグインを作り始めました。

figma.com/@hilokiのページのキャプチャ

私が作成したプラグインはFigma Communityに公開しています。
今日はその中から2つほど紹介させてください

作ったプラグインの紹介

Contrast Grid

Figmaプラグイン Contrast Gridのカバー画像

Contrast Gridは、色の組み合わせ(背景色と文字色)のコントラスト比をグリッドで表示するプラグインです。WCAGの基準に従って、4.5:1以上の比率があるか、などが一覧できます。デザインシステムとしてカラーパレットの設計をするときに必要だったので作りました。
Contrast Gridは元々、EightShapes社が作ったWebのツールがあり、こちらを活用していたのですが、WebのツールとFigmaをいったりきたりするのが大変でした。なので、Figmaで完結できるよう考えたのです。またこのプラグインではopacityを考慮したコントラスト比のチェックもできるようにしています。

Typography Styleguide

Figmaプラグイン Typography Styleguideのカバー画像

Typography Styleguideは、ファイルのLocal StyleとしてText Styleをカタログとして生成するプラグインです。Styleのスペックや見た目をガイドラインの資料として用意する必要があったのですが、それを1つずつ手作業でつくるのは大変だったので、自動生成するものを作りました。

プラグインはWebの技術でつくることができる

HTML、CSS、JavaScriptのコードが写っているイメージ画像

これらのプラグインは何か新しい技術や、専用の技術でつくられているわけではありません。HTMLとCSS、JavaScriptといったWebの技術です。
なので私としては、プログラミングに長けたエンジニアでなくとも、少しコーディングをしたことがあるデザイナーであっても挑戦できると考えています。

Figma Plugins API

ではどのようにしてFigmaをWebの技術で操作するのかというと、Plugins APIのことを知る必要があります。Plugins APIを使うことによって、Figmaのレイヤーパネルやプロパティパネルにあるような値の読み込み・操作をすることができます。
コード開発に不慣れだと、APIというものですらよくわからないかもしれません。しかしFigmaのPlugins APIでできることというのは、基本的にはFigmaのUIを手で操作していることをコードによって実行しているだけです。
ここでは小さなサンプルコードを例に説明します。

figma.currentPage.selection[0].name = "Sign up"

このコードはFigma Plugins APIをJavaScriptで操作するサンプルです。これをひとつずつ噛み砕いて説明します。

左: コードの`figma` の部分、右: FigmaのUIにおける全体

先頭の figma  はAPIとしてはGlobal objectというものですが、ここでの理解としては「Figma全体の中の」くらいのイメージで大丈夫です。

左: コードの`currentPage` の部分、右: FigmaのUIにおける「現在のページ」

`currentPage` は言葉の通り「現在のページ」です。つまり、UIをイメージして「現在のページ」 の中の何かにアクセスすることができます。

左: コードの`selection[0]` の部分、右: FigmaのUIにおける「選択中のレイヤーの1つ」

`selection` もそのまま「選択中のレイヤー」です。つまりここまでのコードを文章にするなら「Figmaの中の、現在のページの中の、選択中のレイヤー」に対して何かができる、ということです。
後ろにある `[0]` はJavaScriptの「配列(Array)」と中身の数字が「インデックス(index)」 というものです。ここでは深く今は考えず、プログラム上で明示的に「一番目」を意味しているコードだと考えてください。
※なぜ「一番目」なのに `0` なのかというのは、コンピュータでの計算における決まりだと考えておいてください!

左: コードの`name` の部分、右: FigmaのUIにおける「レイヤーの名前」

`name` もそのものずばり「名前」です。ここでいう名前とは「レイヤーの名前」です。つまり、ここまでのコードをなぞると「Figmaの中の、現在のページの中の、選択中のレイヤー、名前」ということです。

最後は `= "Sign up"` です。`"Sign up"`は「Sign upという文字列」で、`= ` は数学でいうところの代入で、イコールの前がイコールの後の内容に置き換わります。
すると、一連のコードは「Figmaの中の、現在のページの中の、選択中のレイヤー、名前、を"Sign up"という文字列に置き換える」ということになりますね。

こうみると、Figma Plugins APIとJavaScriptは意味不明な文字列ではなく、UI操作における作業をコードに置き換えたようなものだと分かったのではないでしょうか。

Plugins APIのリファレンスには、初歩的な内容やサンプルコードの解説などもあるので読んでみてください。API Referenceには前述に登場した `figma` というものから、どういう値が参照できるか、何かできるか、といったことを辿ることができます。

プラグインの作成と公開の流れ

プラグイン公開の流れのイメージ図。公式のプラグインテンプレートを使って解説する。次にレビュー申請をしてプラグインを公開する。

APIをどのように扱うのかがわかり、実際にプラグインを公開するまでの流れをみてみましょう。

プラグイン開発をはじめるにはいくつかの方法はありますが、基本的なやり方は公式のテンプレートを利用することです。

FigmaのDesktop Appのメニュー「Plugins > Manage Plugins…」からテンプレートを選ぶことができます。
それらを利用してコードを書けた後は申請が必要です。プラグインが公開される前には審査があり、早ければ3日・長ければ2週間ほどで審査結果が返ってきます。審査結果に問題なければ、晴れてプラグインの公開です。

開発環境を整える必要がある

Node.jsの環境を整える必要についての説明。「環境構築に奮闘する前に、何ができるかを知る」ほうが重要、というメッセージ

プラグイン開発から公開までの簡単に説明してしまいましたが、開発においてはその環境を整える必要があります。少なくともNode.js等の環境は必要となりますし、普段コードを書かない仕事をしている場合はここで躓いてしまうかもしれません。

私としてはこうした開発環境でつまづく前に、APIやScriptで「何ができるのか」を知ってもらいたいと考えました。

今回はFigmaプラグインではなく、DevToolsを使った自動化、そしてScripterプラグインを使ったScriptの管理について紹介します。

なのでこのセッションのテーマとしても、プラグインによるFigmaのハックというよりは、JavaScriptを使ったFigmaのハックについてここからはお話します。

FigmaのDevTools

Figmaでファイルを開いた状態のキャプチャ。中央にDevToolsを開くショートカットの紹介があり、下部にはDevToolsが開いている

DevToolsは「開発者ツール」で、Google Chromeで使えるものと同じです。ここからはDevToolsのConsoleで色々と試してみましょう。

figma.notify('Hello、こんにちわ')

figma.notifyは画面下部に通知メッセージを表示するAPIです。これに文字列を渡すとその内容が表示されます。このコードをConsoleタブの中で実行します。

実行すると通知メッセージが出ましたね。

それでは先程のレイヤー名を変更するScriptも試してみましょう。

figma.currentPage.selection[0].name = "Sign up"

説明した通り「選択中の一番目のレイヤー」の名前を変更するので、レイヤーを選択した状態で、Consoleで実行してください。

レイヤーの名前が「Sign up」に変更されました。

より実用的な例

ここまで紹介したものだけだと実用性にかけるので、もう少し実際のシチュエーションにありそうなケースで紹介します。

命名規則に合わせたレイヤー名の変更

「命名規則に合わせたレイヤー名の変更」のイメージ画像

Frameの名前に命名規則がある場合、その命名規則にあわせて修正する例です。この例では「すべて小文字」「階層の区切りである半角スラッシュの前後にスペースは設けない」といった命名規則があるとします。それに反し、サンプルでは大文字が混ざっていたり、スラッシュの前後のスペースのあり・なしが揺れています。これを修正してみましょう。

サンプルコード

const selection = figma.currentPage.selection;

selection.forEach(node => {
  // Get current name
  const srcName = node.name;

  // Split by slash e.g. Questionnaire, Age
  const splitName = srcName.split('/');

  const newName = splitName.map(name => {
  // Remove start/end space, and to lowercase
    return name.trim().toLowerCase();
  })

  // Assign new name
  node.name = newName.join('/')
})

まずコード上にある`node`というのは「レイヤー」です。FigmaのAPIもとい内部の実装では「node」と呼ぶことを覚えておくと良いでしょう。
これまでの例では `selection[0]` のように記述していましたが、この例では「選択中のすべてのレイヤー」に対する処理をおこないます。
「選択中のすべてのレイヤー」を意味する`figma.currentPage.selection`に対し、JavaScriptの `forEach()` という繰り返し処理によって、選択したひとつずつのレイヤーに対して名前を整形する処理を書いています。

Frameの中にあるMain componentを見つける

「Frameの中にあるMain componentを見つける」のイメージ画像

ページのデザインをしているときに、そのFrameの中にMain componentが混じってしまうことがあります。本来であればMain componentは別のところで管理され、ページのデザインの中にはそのInstanceがあるべきですが、作業をしているとうっかり残してしまうことが僕の経験としてよくあります。
このMain componentを選択したFrameから見つけるScriptです。

サンプルコード

// Select any nodes
const selection = figma.currentPage.selection;

const components = selection.map(node => {
  if("children" in node) {
    // Find “COMPONENT” type node 
    const nodes = node.findAllWithCriteria({
      types: ['COMPONENT']
    })
		
    return nodes;
  }
})

// Reselect Main Components
figma.currentPage.selection = components.flat();

// Show result at the notification
figma.notify(`Find ${components.flat().length} components 🕵️‍♂️`)

先ほどのFrame名を変更した例と同じように「選択中のすべてのレイヤー」に対して繰り返し処理をおこないます。今回は `forEach()` ではなく `map()`を使い、繰り返し処理した結果を `components` という定数に入れるようにし、後半のコードで使います。

繰り返し処理の中身では、FigmaのAPIにある `findAllWithCriteria` を使って「Main componentのタイプのレイヤー」を探しています。`COMPONENT`というtypeのものがMain componentなので、それを見つけて、先程の `components` という定数に入れています。

`figma.currentPage.selection` が再び登場するのですが、これはコードの処理でいうと「選択中のすべてのレイヤーに、見つけたMain componentのレイヤーを入れる」となり、日本語で言い換えれば「見つけたMain componentのレイヤーを選択状態にする」ということをしています。この処理によって、UI上では1つ以上のMain componentがが選択された状態になるので、どこにMain componentがあるのかがわかります。

最後はおまけで、`figma.notify` を使って、発見したMain componentの数を通知メッセージで表示するようにしています。

ページのバックアップを作成する

3つ目は現在のPage(FigmaにおけるPage)をScriptで複製しつつ、複製したPage名の後ろに「現在の日時」を加えるというものです。
シチュエーションとしては、既存のページに対して何か新しいデザイン変更を加えるときに、念の為ページを複製して作業をすることをイメージしてください。このときに複製したものをバックアップとしてしばらく残す場合に、それがいつの時点のPageなのかをわかりやすくするために、複製した日時を残したい、というアイデアです。

サンプルコード

const clonePage = figma.currentPage.clone();

// Get current date
const currentDate = new Date();

// Concat page name with current date
clonePage.name = `${clonePage.name} [${getCurrentTime(currentDate)}]`;

function getCurrentTime(currentDate) {
  const year = currentDate.getFullYear();
  const month = (currentDate.getMonth() + 1).toString().padStart(2, '0');
  const date = currentDate.getDate().toString().padStart(2, '0');
  const hours = currentDate.getHours().toString().padStart(2, '0');
  const minutes = currentDate.getMinutes().toString().padStart(2, '0');

  return `${year}/${month}/${date} ${hours}:${minutes}`;
}

ScriptによるPageの複製は、Pageに対して `clone()` を実行するだけです。このコードでは「現在のページ」である `figma.currentPage`に対して`clone()` をしています。その複製されたページを `clonePage`に入れておきます。
後半のコードはFigmaのAPIに関係ないJavaScriptのコードです。色々と複雑そうに見えることをしていますが、現在の日時を取得するコードで今回は詳細は省きます。このサンプルとしては、取得した現在の日時を文字列にし、 `clonePage`の名前、つまり `clonePage.name`に入れるということをしています。

JavaScriptのコードを管理するScripterプラグイン

ここまでDevToolsのConsoleを利用してJavaScriptのコードを実行してきましたが、毎回コピー&ペーストしてやるのは大変です。そこでScripterというプラグインを紹介します。

Scripter

Figma APIを実行できるFigmaプラグイン、Scripterのキャプチャ

ScripterはFigmaのプラグインで、そのプラグイン上でJavaScriptおよびFigmaのAPIを実行できるという特殊なプラグインです。エディタはVS Codeが基盤にあり、コードのハイライトやコード補完も効きます。

Scripterは任意のコードを名前をつけて保存ができます。つまりここまで紹介したようなコードを再利用したい場合には、Scripterに保存しておけば便利です。

そしてもうひとつの便利な機能は、そのコードを他のFigmaユーザーと共有できることです。プラグインのUIからエクスポートするボタンを実行すると、Figmaのファイル上にScripterによってボタンのようなものが作られます。他のScripterプラグインをインストールしたユーザーが、その生成されたボタンを選択し、Figmaの右下部にある「Open Script」を実行するとコードがそのユーザーのScripterプラグインの中に取り込まれます。

実際にScripterに保存する様子、共有のための操作はデモ動画をご覧ください。デモ動画では紹介した「Frameの中にあるMain componentを見つける」コードを登録しています。

色のカタログを生成する

最後にもうひとつ大きな例を紹介します。前半に紹介したTypograpphy Styleguideのように、ファイルに登録された色のスタイル(Color Styles)をカタログ上に生成するコードです。カラートップと名前、HEXの値と、CSSで扱うときの名前を揃えたものを生成します。

このコードはこれまでよりやや多く複雑です。分量も多いのでこの記事には転載しませんが、サンプルコードを別途見てみてください。ポイントとしては、一見複雑に見えても、やっていることは基本的にFigmaのUIで手作業でやることをコードで自動化しているだけです。Scripterプラグインにサンプルコードを登録し、中身の値を変更してみたり、新しい機能を追加したりと試してみてください。

次はぜひプラグイン開発に挑戦を!

今回のセッションはここまでですが、今回の紹介したようなコードを使ったFigmaのhackに自信がついたら、ぜひプラグイン開発にもチャレンジしてください。紹介したContrast GridのようにプラグインのUIが必要だったり、Quick Actionsによる実行をさせたい場合はプラグイン化が必要です。そして自分の開発したプラグインを世界中の皆さんに公開しましょう!

デザイナーはコードを書くべきか?

最後は多く議論される「デザイナーはコードを書くべきか?」についての個人的な経験を述べて終わりたいと思います。

書くべきかはわかりませんが、少なくともコードを学ぶことによって、UIデザインのスキルが上がっているという実感はあります。

少なくとも今回のようにコードを使ってFigmaをJavaScriptで操作し、プラグインを開発する経験は、Figmaでより構造的で整備されたデザインができるようになる力になります。

プラグイン開発はワークフローを強化するだけではなく、あなたのデザインの力を押し上げてくれるでしょう。

このセッションの内容が多くのデザイナーにとって刺激になれば幸いです。ありがとうございました 👋

動画とスライド


明日の元気の素になります。