📘

属人的なデザイントークン管理からの脱却

2025/02/04に公開

※こちら自身の記事のテックブログからの転載になります
https://tech.forstartups.com/entry/2025/01/24/175935

はじめに

こんにちは、STARTUP DB(SDB)の開発をしている杉谷です。

私含めSDBチームでは、デザイナーとエンジニアが密に連携しながらプロダクト開発を進めています。
その中で、「デザイントークンの管理」という課題に直面し、改善に取り組んできました。

フロントエンド開発において「デザインの意図を正確にコードに反映する」ことの重要性を日々の開発で実感しています。特に、デザイントークンの管理は、品質の維持と開発効率の両面で大きな影響を与える要素だと考えています。

今回は、FigmaのLocal Variablesを効率的にSCSSに変換する仕組みを構築した経験についてお話ししたいと思います。

完全な自動化には至っていませんが、従来の手作業と比べて大きな改善を実現することができました。この記事が、同じような課題を抱えているチームの皆さんの参考になれば幸いです。

属人的なデザイントークン管理の問題点

実際にチームで開発を進める中で、以下のような課題を感じていました。

手動管理の限界

// 手動で更新していた従来のSCSS
$color-primary: #1a2b3c;     // Figmaでは 'Primary/Base'
$color-secondary: #2d3e4f;   // Figmaでは 'Secondary/Base'
$spacing-large: 24px;        // Figmaでは 'spacing.large'

この方法には、次のような問題点がありました:

  • デザイントークンの更新が発生するたびに手動でコードを書き換える必要がある
  • 特にcolor・spacingやtypographyの設定は数が多く、更新に時間がかかってしまう
  • 更新漏れや入力ミスのリスクが常にあり、ミスした状態で使用される可能性がある

命名規則の不一致

私たちのチームでは、デザイナーとエンジニアで異なる命名規則を採用していました:

// エンジニア側の命名
$font-size-large: 18px;
$font-weight-bold: 700;
$spacing-x-small: 4px;

// Figma側の命名
// typography.headline.large
// typography.weight.bold
// space.xs

この不一致によって、以下のような問題が発生していました:

  • コードレビュー時に、これがFigmaのどの値なのか確認が必要になる
  • 新しいメンバーが参画した際の学習コストが高くなる
  • 変更が必要な箇所の特定に時間がかかってしまう

解決方法の検討

最初はFigmaのAPIを活用する方法を検討しました。APIを使用することで、Variablesの値を直接参照し、StyleDictionaryで変換するというシンプルな流れを実現できると考えていました。

Figmaのドキュメント(Variables API)を確認すると、変数を参照するためのエンドポイントが用意されていることが分かりました。

しかし、この機能はENTERPRISEプラン以上でないと利用できないという制約があることが判明。私たちのチームのプランでは利用できず、別のアプローチを考える必要がありました(無念、、、)

そこで代替案として、Figmaのプラグインを自作する方法を検討することにしました。

実装

以下の2つのステップで実装を行いました:

  1. Figmaプラグインの作成
  2. StyleDictionaryの設定

Figmaプラグインの作成

実際に作成したPluginはこちらになります:

Plugin URL: Export local variables to Json

下記で実際に書いたコードについて一部解説します。

ソースコード:figma_export_variables_plugin

Pluginの主な機能

デザイントークンをJSON形式に変換し、StyleDictionaryで扱いやすい形式に整形します。

処理の流れ

1.変数コレクションの取得と処理

async function exportToJSON() {
  // ローカルの変数コレクションを取得
  const collections = await figma.variables.getLocalVariableCollectionsAsync();
  // 各コレクションを処理して結果をマージ
  const files = [];
  for (const collection of collections) {
    files.push(...(await processCollection(collection)));
  }
  // 結果をUIに送信
  const mergedBody = Object.assign({}, ...files.map((file) => file.body));
  figma.ui.postMessage({ mergedBody });
}

2.変数の階層構造の作成と値の変換

// 例:'colors/primary/base' → { colors: { primary: { base: { $value: '#1234567' } } } }
name.split("/").forEach((groupName) => {
  obj[groupName] = obj[groupName] || {};
  obj = obj[groupName];
});

3.値の型に応じた変換処理

  • カラー値の変換:RGBAからHEX形式へ

  • 数値の整形:小数点以下の処理

  • エイリアス(参照)の解決:他の変数を参照している場合の処理

StyleDictionaryの設定

StyleDictionaryは、デザイントークンを一元管理し、複数のプラットフォームやフォーマットに変換できるツールです。

以下が実際に、自作Pluginで出力したJSONをSCSSに変換する際に書いたコードになります。

import StyleDictionary from 'style-dictionary'

// プレフィックスの追加 
// 例:typography.headline.large → $typography-headline-large
StyleDictionary.registerTransform({
  name: 'AddPrefixToTheName',
  type: 'name',
  transform: (token) => {
    return `${token.name}`
  },
})

// pxを付与しない項目を定義 
// opacity: 透明度は0-1の小数値 
// font-weight: フォントの太さは100-900の数値 
// line-height: 行の高さは倍率で指定
const EXCLUDED_CATEGORIES = /opacity|font-weight|line-height/


// 数値型のトークンにpxを付与
// 例:spacing.large: 24 → $spacing-large: 24px
StyleDictionary.registerTransform({
  name: 'AddPixelToTheValue',
  type: 'value',
  filter: (token) => {
  // 数値型で、かつ除外カテゴリーに含まれないものだけを変換
    return token.$type === 'number' && !EXCLUDED_CATEGORIES.test(token.name)
  },
  transform: (token) => {
    return `${token.$value}px`
  },
})

// StyleDictionaryの出力設定
export default {
  source: ['.style-dictionary/tokens/*.json'],
  platforms: {
    scss: {
      transformGroup: 'scss',
      buildPath: 'src/styles/',
      files: [
        {
          destination: '_variables.scss',
          format: 'scss/variables',
        },
      ],
      transforms: ['AddPrefixToTheName', 'AddPixelToTheValue'],
    },
  },
}

主なカスタマイズ内容

  1. 変数名へのプレフィックス追加(AddPrefixToTheName)
    • 例:color-primary$color-primary
    • バージョン管理や名前空間の分離に役立ちます
      • 今のチームではデザイントークンがV1・V2と混在しているので、ここでそれぞれ判別出来るようにprefixをつけて管理しています
        • 例:color-primary$v2-color-primary
  2. 単位(px)の自動付与(AddPixelToTheValue)
    • 例:spacing-large: 24$spacing-large: 24px
    • 数値型のトークンに自動で「px」を付与します
    • ただし、以下は除外:
      • opacity(不透明度)
      • font-weight(フォントの太さ)
      • line-height(行の高さ)

改善後の状況

自動化による効率化

# コマンド一つで同期が完了
yarn build-style-dictionary

この改善により:

  • デザイントークンの更新が数秒で完了するようになりました
  • 人的ミスのリスクが大幅に低減されました

命名規則の統一

// 自動生成されるSCSS
$typography-headline-large: 24px;
$typography-weight-bold: 700;
$space-xs: 4px;

この改善により:

  • デザイナー・エンジニア間のコミュニケーションがよりスムーズになりました
    • デザイナーとエンジニアで異なる命名規則を使用していたため変数の使い分けに時間を取られていましたが、Figmaの命名規則をベースとした統一により、デザイントークンの運用がスムーズになりました。デザイナーが定義した名前がそのままSCSS変数として使えるため、本来の実装作業に集中できるようになりました
  • コードレビューの効率が向上しました
  • メンバーの学習コストが低下しました

学んだこと

共通言語の重要性

共通言語の重要性について、実際の経験から多くの気づきがありました。

当初、デザイナーとエンジニアで異なる命名を使うことは柔軟性があると考えていました。
しかし、プロジェクトが進むにつれて、それがコミュニケーションコストの増加につながることを実感しました。

特に印象的だったのは、チームメンバーの入れ替わりが発生した際のことです。『なぜこの命名規則を採用したのか』という背景が失われ、コードの意図が理解しづらくなってしまいました。そこで、Figmaの命名規則に合わせることで、プロジェクト全体で一貫性のある共通言語を持つことができ、新メンバーにとっても理解しやすい環境を作ることができました。

この取り組みを通じて、共通言語を設計する際は職種による区分けを避けることの大切さにも気づかされました。エンジニアやデザイナーといった役割で言語を分けるのではなく、プロダクトに関わる全員が自然に受け入れられる/受け入れやすい共通の言語を築くことが、結果としてプロダクトの品質向上につながるのだと実感しています。他所では当たり前のことかもしれませんが、実際に経験することで、その重要性を自分は今回深く理解することができました。

自動化の価値

単純作業の自動化は、工数削減以上の価値があると実感しました。

特にヒューマンエラーのリスクが低減されたことで、品質の維持も容易になりました。
それだけではなく、チームメンバーが本質的な作業に集中できる環境づくりの重要性を学びました。

効率化を超えた学びの機会

この取り組みを通じて、開発における効率化作業の面白さを改めて実感することができました。
また他にも当初は単純な作業の自動化という認識でしたが、実際に取り組んでみると予想以上の発見がありました。

特に印象的だったのは、Figmaのプラグイン開発です。
APIが利用できないという制約は、一見するとマイナスに思えましたが、その制約がむしろより柔軟なアプローチを生み出すきっかけとなりました。
また、当初はチーム内での利用のみを想定していたプラグインが、現在では社外の方々にも活用していただけるようになりました。この予想外の広がりは、効率化への取り組みが単なる業務改善を超えて、より大きな価値を生み出せる可能性を教えてくれました。

振り返ってみると、今回の取り組みは効率化を超えて、技術的な制約との向き合い方や、想定外の価値の見出し方など、エンジニアとしての視座を広げる貴重な機会となったかなと思います。

今後の展望

現在の仕組みをベースに、さらなる自動化と品質向上を目指して、以下のような改善を検討中です

プルリクエスト時にデザイントークンの整合性を自動でチェックし、不整合がある場合は即座に開発者へ通知する仕組みの実装を考えています。これにより、デザインとコードの一貫性をより確実に担保できると良いなと考えています:

  • CIへの組み込み
    • プルリクエスト時に自動でデザイントークンの同期チェック
    • 不整合があった場合の自動通知

デザイントークンの品質管理向上を目的に、以下の機能追加出来ると良いなと考えています:

  • バリデーション機能の強化
    • デザイントークンの命名規則チェック
    • 使用されていない変数の検出

現在50名以上の方々に利用していただいているFigmaの自作Pluginですが、より使いやすいものにするため、以下の改善が出来たら良いなと考えています:

  • Pluginの改善
    • UI・UXの改善
    • Userからのコメントを基に機能追加・修正

おわりに

今回は、FigmaのLocal Variablesを効率的にSCSSに変換する仕組みについて共有させていただきました。当初検討していたFigma APIの利用は叶いませんでしたが、プラグインを自作することで課題を解決することができました。

この仕組みにより、デザイントークンの更新作業が効率化されただけでなく、デザイナーとエンジニア間の共通言語が確立され、コミュニケーションの質も向上しました。

みなさんのプロジェクトでも、似たような課題を抱えているかもしれません。本記事が、その解決のヒントになれば幸いです。

Discussion