くらにゃんLINEミニアプリをFigmaのVariablesとMCPを使ってダークモードに対応してみた

くらにゃんLINEミニアプリをFigmaのVariablesとMCPを使ってダークモードに対応してみた

2025.09.25

こんばんは、リテールアプリ共創部マッハチームの西田です

先日、弊社のマスコットキャラクターである、くらにゃんの公式ショップのLINEミニアプリがリリースされました

LINE ミニアプリ

公式ショップ

今回はくらにゃんLINEミニアプリを、AIを活用し高速でダークモードに対応したので、その過程をご紹介させていただきます

全体の仕組み

利用している技術

  • Next.js ⇒ LINEミニアプリ
  • Tailwind 4 ⇒ CSS
  • Claude Code ⇒ コーディング補助
  • AI Starter ⇒ 雑務、壁打ち

全体像

Dark Mode を反映したデザイントークンをFigmaで定義し、

clanyan-line-mini-app-dark-mode-01.png

それをMCPとClaude Codeを使って Next.js で作成されたLINEミニアプリに反映しました

clanyan-line-mini-app-dark-mode-02.png

デザイントークンをFigmaのVariablesで定義

FigmaのVariablesを使い、デザイントークンを定義します。Variablesを使うことにより、Figmaで作成するデザイン内で再利用可能で、一貫性のあるデザインの作成を楽にします。

Variablesはデザインシステムの構築にも利用でき、今回のダークモード対応ではデザインシステムのデザイントークンを定義します。

デザイントークンは2種類登録します

  1. プリミティブトークン
  2. セマンティックトークン

プリミティブトークンはデザインシステム内で使われる設定値を定義します。今回はダークモード対応のために色のトークンを定義します

  • primitive/color/grey/300#DDDDDD
  • primitive/color/grey/700#444444

clanyan-line-mini-app-dark-mode-03.png

プリミティブトークンをFigmaのデザイン上で使い回すことで、色味の一貫性を保ちやすくします

セマンティックトークンは意味を持った名前で、デザイン上でどこに使用するのかのコンテキストを含む名前にします。Figma上のデザインからはこのセマンティックを参照し、プリミティブトークンは、セマンティックトークンからエイリアス先として設定します

  • semantic/color/textprimitive/color/grey/950
  • semantic/color/heading/secondaryprimitive/color/grey/900

FigmaのデザインにVariablesを適用

FigmaのデザインにVariablesを適用していきます。色を選択するところで、 Libraries から選択することができます

clanyan-line-mini-app-dark-mode-04.png

Variablesをエクスポートし、AIに渡してダークモードの色を指定

Figma の Plugin を使って、Variablesの定義をエクスポートします

https://www.figma.com/community/plugin/1256972111705530093/export-import-variables

今回は上記の Plugin を使って、エクスポートしました。JSON形式のファイルがエクスポートされるので、そのファイルをAIに渡し、ダークモードの定義を出力してもらいました

VariablesのMode機能でDarkモードを表現する

Variables の Mode 機能を使って、Figma上でDarkモードを表現できるようにします。モードを追加し「Dark」と名前をつけます。セマンティックトークのDarkモード時に参照するプリミティブトークンを設定します

clanyan-line-mini-app-dark-mode-05.png

デザインに戻り、Appearance からModeを切り替えることで、LightモードとDarkモードを切り替え、見た目を確認することができます

clanyan-line-mini-app-dark-mode-06.jpg

Variablesをエクスポートし、リポジトリに含める

先ほどエクスポートしたJSONをリポジトリに含め、 AIから参照できるようにします

デザイントークンを Tailwind で使えるようにする

デザイントークン定義をエクスポートしたJSONを Tailwind で使えるようにします。今回は Tailwind v4 を使ってるので、通常のCSS変数として取り込みます。最初 AI (Claude Code) に読み込ますだけでいい感じに css ファイルに追記してくれると想定していましたが、JSONファイルが大きすぎるためか、なかなかうまくいかず、最終的には、出力されたJSONから CSS ファイルに変換するスクリプトをAIに出力させ、それを実行しCSSファイルに変換しました。

出力されたCSSは以下のようなCSSです

:root {
  /* Colors from Figma */
  --color-grey-50: #f5f5f5;
  --color-grey-950: #0a0a0a;

  --color-text-primary: var(--color-grey-950);
  --color-background-page: var(--color-grey-50);  
  /* ...省略... */  
}

.dark {
  /* Dark mode color overrides */
  --color-text-primary: var(--color-grey-50);
  --color-background-page: var(--color-grey-950);
  /* ...省略... */  
}

CSSの変数として、プリミティブカラー、セマンティックカラーの定義が出力され、ダークモード対応用の .dark CSSクラスの配下であればセマンティックカラーの変数を上書きするようになっています。

スクリプト自体は汎用性がないもののため、ここには記載しませんが、出力結果を見ながらAIに指示を出し調整しました

Next.js上でOSの設定に合わせてダークモードを切り替えれるようにする

OSの設定からダークモードの設定を取得し、その内容に応じて、html要素にcssクラス lightdark を設定しています。また、LINEミニアプリが実行されるLIFFブラウザでは、ダークモードに直接対応していないので、手動でもダークモードを切り替えられるようにしました。手動で切り替えた設定は localStorage に保存するようにしてます

"use client";

import { createContext, useContext, useEffect, useState } from "react";

type Theme = "light" | "dark" | "system";

type ThemeContextType = {
  theme: Theme;
  setTheme: (theme: Theme) => void;
};

const ThemeContext = createContext<ThemeContextType | undefined>(undefined);

export function useTheme() {
  const context = useContext(ThemeContext);
  if (!context) {
    throw new Error("useTheme must be used within a ThemeProvider");
  }
  return context;
}

export function ThemeProvider({ children }: { children: React.ReactNode }) {
  const [theme, setTheme] = useState<Theme>("system");

  useEffect(() => {
    const storedTheme = localStorage.getItem("theme") as Theme | null;
    if (storedTheme) {
      setTheme(storedTheme);
    }
  }, []);

  useEffect(() => {
    const root = window.document.documentElement;
    root.classList.remove("light", "dark");

    const applyTheme = () => {
      if (theme === "system") {
        const isDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
        root.classList.add(isDark ? "dark" : "light");
      } else {
        root.classList.add(theme);
      }
    };

    applyTheme();

    if (theme === "system") {
      const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
      const handleChange = () => applyTheme();
      mediaQuery.addEventListener("change", handleChange);
      return () => mediaQuery.removeEventListener("change", handleChange);
    }
  }, [theme]);

  const handleThemeChange = (newTheme: Theme) => {
    setTheme(newTheme);
    localStorage.setItem("theme", newTheme);
  };

  return (
    <ThemeContext.Provider value={{ theme, setTheme: handleThemeChange }}>
      {children}
    </ThemeContext.Provider>
  );
}

Figma MCPを使いコンポーネントにTailwindのクラスを当てる

Figma MCPを設定

Dev Mode MCPサーバー利用ガイド

Figma MCPはFigma のディスクトップアプリの Local Server を使用します。ディスクトップアプリを起動し、メニューから Preferences → Enable local MCP Server でMCPサーバーを起動します

clanyan-line-mini-app-dark-mode-07.png

その後、MCPサーバーを Claude Code に登録します

claude mcp add --transport sse figma-dev-mode-mcp-server http://127.0.0.1:3845/sse 

以下のコマンドを実行し

claude mcp list

以下の出力が確認できればOKです

figma-dev-mode-mcp-server: http://127.0.0.1:3845/sse (SSE) - ✓ Connected

MCPを使ってコンポーネントにクラスを適用

Figma MCPを使うとディスクトップアプリ上で選択した Node をClaude Codeから参照できるようになります

clanyan-line-mini-app-dark-mode-08.png

Claude Code に指示を出すときに、明示的に「Figma MCPを使用して」と付け加えると、Figma MCPを利用する確率が高まります。

Figma MCPは選択したノードの配下のノードの情報まで一度に取得できます。最初、一番上位のフレームを選択して一度に全てのCSSクラスを適用する想定でしたが以下の問題が発生しできませんでした

  1. Tailwind v4 のテーマに設定したクラス名をAIが使用しない
  2. AIがFigma上のデザインとReactコンポーネントとの対応がわからず、よくわからない修正を繰り返してしまう

そのため、まず、 Tailwind v4 のテーマに設定したクラス名に手動で修正し、修正内容をプロンプトで伝えました。

その後、同じセッションでコンテキストを保ったまま、React コンポーネントに対応する Figma 上のNodeを選択し、Claude Code 上で @ で対応するコンポーネントのファイルを指定し、一つ一つ指示を出すことで、思った通りの修正を行うことができました

最後に

今回はAIを使って、LINEミニアプリをダークモードに対応してみました。基本的には Plan Mode ⇒ Auto Edit Mode の順で開発を進めていますが、Plan Mode の情報量では確認しきれない部分も多く、出力し、動きを確認し、修正を繰り返すというステップで開発を進めました。

今回のダークモード実装には大体半日程度かかり、そのほとんどを慣れないFigmaの作業が占めています。AIを使って10倍の生産性まで、まだ遠い感じがしますが、案件作業中の合間で、こういった作業も行えるのは、AIなしでは考えられなかったと思います。

この記事が誰かの役に立てれば幸いです

この記事をシェアする

facebookのロゴhatenaのロゴtwitterのロゴ

© Classmethod, Inc. All rights reserved.