mcpField
D
design-to-component-translator

design-to-component-translator

github.com/patricio0312revデザイン・UI63263 回インストール41 週間前に更新
リポジトリ

design-to-component-translator について

ビジュアルデザインの仕様を React コンポーネントに変換するスキルです。デザイントークン、操作状態、レスポンシブ対応、アクセシビリティを扱います。

主な機能

  1. 01デザインの寸法とスタイルを抽出
  2. 02値をデザイントークンに対応付け
  3. 03セマンティックな React コンポーネントを生成
  4. 04操作状態とレスポンシブ状態を実装
  5. 05アクセシビリティとバリエーションを文書化

活用シーン

  1. 01Figmaのボタン仕様をReactに変換
  2. 02デザインレイアウトからレスポンシブなコンポーネントを作成
  3. 03コンポーネントのバリエーションと表示状態を記録

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/patricio0312rev/skills --skill design-to-component-translator

インストール後、Claude Code で/design-to-component-translatorを入力して読み込まれたか確認します。

詳細

デザインからコンポーネントへの変換

デザイン仕様を、ピクセル単位で正確な本番環境向け React コンポーネントに変換します。

基本的なワークフロー

  1. デザイン仕様を分析する:余白、色、タイポグラフィ、寸法を抽出します
  2. トークンに対応付ける:デザイン値をデザインシステムのトークンに変換します
  3. 構造を生成する:セマンティックな HTML 構造を作成します
  4. スタイルを適用する:正確な寸法で Tailwind/CSS を実装します
  5. 状態を追加する:ホバー、フォーカス、アクティブ、無効の各状態を含めます
  6. レスポンシブに対応する:ブレークポイントごとのルールを実装します
  7. アクセシビリティを確保する:ARIA ラベルとキーボードナビゲーションを追加します
  8. バリエーションを記述する:すべての表示状態と props を列挙します

デザイン仕様の分析

Figma/デザインから抽出する内容

余白とレイアウト:

  • パディング:p-4(16px)、px-6(水平方向に24px)
  • マージン:m-2(8px)、mt-4(上方向に16px)
  • ギャップ:gap-3(flex アイテム間に12px)
  • 幅/高さ:w-64(256px)、h-10(40px)

タイポグラフィ:

  • フォントファミリー:font-sans、font-mono
  • フォントサイズ:text-sm(14px)、text-base(16px)、text-lg(18px)
  • フォントウェイト:font-normal(400)、font-medium(500)、font-semibold(600)
  • 行の高さ:leading-tight、leading-normal、leading-relaxed
  • 文字間隔:tracking-tight、tracking-normal、tracking-wide

色:

  • 背景:bg-blue-500、bg-gray-100
  • テキスト:text-gray-900、text-white
  • 枠線:border-gray-300、border-blue-600
  • 不透明度:bg-opacity-50、text-opacity-75

枠線と角丸:

  • 枠線の幅:border、border-2、border-t-4
  • 枠線の角丸:rounded(4px)、rounded-md(6px)、rounded-lg(8px)、rounded-full

シャドウ:

  • shadow-sm、shadow、shadow-md、shadow-lg、shadow-xl

デザイントークンへのマッピング

トークンシステムの作成
// tokens.ts
export const tokens = {
  colors: {
    primary: {
      50: "#eff6ff",
      100: "#dbeafe",
      500: "#3b82f6",
      600: "#2563eb",
      700: "#1d4ed8",
    },
    gray: {
      100: "#f3f4f6",
      300: "#d1d5db",
      500: "#6b7280",
      700: "#374151",
      900: "#111827",
    },
  },
  spacing: {
    xs: "0.25rem", // 4px
    sm: "0.5rem", // 8px
    md: "1rem", // 16px
    lg: "1.5rem", // 24px
    xl: "2rem", // 32px
  },
  fontSize: {
    xs: ["0.75rem", { lineHeight: "1rem" }],
    sm: ["0.875rem", { lineHeight: "1.25rem" }],
    base: ["1rem", { lineHeight: "1.5rem" }],
    lg: ["1.125rem", { lineHeight: "1.75rem" }],
    xl: ["1.25rem", { lineHeight: "1.75rem" }],
  },
  borderRadius: {
    sm: "0.25rem", // 4px
    md: "0.375rem", // 6px
    lg: "0.5rem", // 8px
    full: "9999px",
  },
  shadows: {
    sm: "0 1px 2px 0 rgb(0 0 0 / 0.05)",
    md: "0 4px 6px -1px rgb(0 0 0 / 0.1)",
    lg: "0 10px 15px -3px rgb(0 0 0 / 0.1)",
  },
};
Tailwind の設定
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        primary: {
          50: "#eff6ff",
          100: "#dbeafe",
          500: "#3b82f6",
          600: "#2563eb",
          700: "#1d4ed8",
        },
      },
      spacing: {
        18: "4.5rem",
        88: "22rem",
      },
      fontSize: {
        "2xs": "0.625rem",
      },
    },
  },
};

コンポーネント変換の例

Figma 仕様からボタンを作成する

Figma の仕様:

  • 高さ:40px
  • パディング:12px 24px
  • 枠線の角丸:6px
  • フォント:Inter Medium 14px
  • 背景:#3B82F6
  • テキスト:#FFFFFF
  • ホバー:#2563EB
  • シャドウ:0 1px 3px rgba(0,0,0,0.1)

変換後のコンポーネント:

import { cn } from "@/lib/utils";

interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
  variant?: "primary" | "secondary";
  size?: "sm" | "md" | "lg";
}

export const Button = ({
  variant = "primary",
  size = "md",
  className,
  children,
  ...props
}: ButtonProps) => {
  return (
    <button
      className={cn(
        // Base styles
        "inline-flex items-center justify-center rounded-md font-medium",
        "transition-colors duration-200",
        "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2",
        "disabled:pointer-events-none disabled:opacity-50",
        // Variant: Primary (matches Figma)
        variant === "primary" && [
          "bg-primary-500 text-white shadow-sm",
          "hover:bg-primary-600",
          "active:bg-primary-700",
        ],
        // Size: Medium (40px height, 12px 24px padding)
        size === "md" && "h-10 px-6 text-sm",
        className
      )}
      {...props}
    >
      {children}
    </button>
  );
};
デザイン仕様からカードを作成する

Figma の仕様:

  • パディング:24px
  • 枠線の角丸:12px
  • 背景:#FFFFFF
  • 枠線:1px solid #E5E7EB
  • シャドウ:0 1px 3px rgba(0,0,0,0.1)
  • 最大幅:400px

変換後のコンポーネント:

interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
  elevated?: boolean;
}

export const Card = ({
  elevated = false,
  className,
  children,
  ...props
}: CardProps) => {
  return (
    <div
      className={cn(
        // Base from Figma
        "max-w-sm rounded-xl bg-white p-6",
        "border border-gray-200",
        // Conditional shadow
        elevated ? "shadow-lg" : "shadow-sm",
        // Hover state (not in Figma, but good UX)
        "transition-shadow duration-200 hover:shadow-md",
        className
      )}
      {...props}
    >
      {children}
    </div>
  );
};

インタラクションの状態

ホバー状態
// Figma: Background changes from #3B82F6 to #2563EB on hover
className={cn(
  'bg-primary-500',
  'hover:bg-primary-600',
  'transition-colors duration-200'
)}
フォーカス状態
// Accessible focus ring
className={cn(
  'focus:outline-none',
  'focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2'
)}
アクティブ/押下状態
// Figma: Slightly darker on click
className={cn(
  'active:bg-primary-700',
  'active:scale-[0.98]', // Slight scale down
  'transition-all duration-100'
)}
無効状態
// Figma: 50% opacity, no interactions
className={cn(
  'disabled:opacity-50',
  'disabled:cursor-not-allowed',
  'disabled:pointer-events-none'
)}

レスポンシブデザインへの変換

ブレークポイントのマッピング
// Figma artboards → Tailwind breakpoints
// Mobile (375px): default (no prefix)
// Tablet (768px): md:
// Desktop (1024px): lg:
// Wide (1280px): xl:

<div
  className={cn(
    // Mobile: Stack vertically, full width
    "flex flex-col gap-4 w-full",
    // Tablet: Side by side, 50% each
    "md:flex-row md:gap-6",
    // Desktop: Max width container
    "lg:max-w-6xl lg:mx-auto"
  )}
/>
レスポンシブタイポグラフィ
// Figma mobile: 14px, desktop: 16px
<h1 className="text-sm md:text-base lg:text-lg font-semibold">
  Responsive Heading
</h1>
レスポンシブな余白
// Figma mobile: 16px padding, desktop: 24px
<div className="p-4 md:p-6 lg:p-8">Content</div>

デザインシステムとの統合

shadcn/ui のパターンを使用する
// Leveraging shadcn's composable approach
import { cn } from "@/lib/utils";

const buttonVariants = cva(
  "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background",
  {
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground hover:bg-primary/90",
        destructive:
          "bg-destructive text-destructive-foreground hover:bg-destructive/90",
        outline:
          "border border-input hover:bg-accent hover:text-accent-foreground",
        secondary:
          "bg-secondary text-secondary-foreground hover:bg-secondary/80",
        ghost: "hover:bg-accent hover:text-accent-foreground",
        link: "underline-offset-4 hover:underline text-primary",
      },
      size: {
        default: "h-10 py-2 px-4",
        sm: "h-9 px-3 rounded-md",
        lg: "h-11 px-8 rounded-md",
        icon: "h-10 w-10",
      },
    },
    defaultVariants: {
      variant: "default",
      size: "default",
    },
  }
);

カラーシステムへの変換

Figma から CSS 変数へ
/* Figma colors → CSS variables */
:root {
  /* Primary from Figma #3B82F6 */
  --primary: 221 83% 60%;
  --primary-foreground: 0 0% 100%;

  /* Secondary from Figma #6B7280 */
  --secondary: 220 9% 46%;
  --secondary-foreground: 0 0% 100%;

  /* Backgrounds */
  --background: 0 0% 100%;
  --foreground: 222 47% 11%;

  /* Borders */
  --border: 220 13% 91%;
  --input: 220 13% 91%;
  --ring: 221 83% 60%;

  /* Radius from Figma */
  --radius: 0.5rem;
}
コンポーネントでの使用
<div className="bg-background text-foreground border-border">
  <button className="bg-primary text-primary-foreground">Button</button>
</div>

アニメーションとトランジション

Figma のマイクロインタラクション
// Figma: Button scales slightly on hover
<button className={cn(
  'transition-all duration-200',
  'hover:scale-105',
  'active:scale-95'
)}>
  Hover me
</button>

// Figma: Card lifts on hover
<div className={cn(
  'transition-all duration-300',
  'hover:-translate-y-1 hover:shadow-lg'
)}>
  Card content
</div>

// Figma: Fade in on mount
<div className="animate-in fade-in duration-500">
  Fading content
</div>

寸法の変換

Figma のピクセル → Tailwind クラス
FigmaTailwind値
2px0.50.125rem
4px10.25rem
8px20.5rem
12px30.75rem
16px41rem
20px51.25rem
24px61.5rem
32px82rem
40px102.5rem
48px123rem
カスタム値
// Figma: 18px (not in default Tailwind)
<div className="w-[18px] h-[18px]">{/* or add to config */}</div>

アクセシビリティへのマッピング

ビジュアルデザインからアクセシビリティへ
// Figma shows disabled state
<button
  disabled={isDisabled}
  aria-disabled={isDisabled}
  className={cn(
    isDisabled && 'opacity-50 cursor-not-allowed'
  )}
>
  Submit
</button>

// Figma shows error state
<input
  aria-invalid={hasError}
  aria-describedby={hasError ? 'error-message' : undefined}
  className={cn(
    hasError && 'border-red-500 focus:ring-red-500'
  )}
/>

よく使われるパターン

フォーム入力の変換

Figma の仕様:

  • 高さ:44px
  • パディング:12px 16px
  • 枠線:1px #D1D5DB
  • 枠線の角丸:8px
  • フォーカス時の枠線:2px #3B82F6
<input
  className={cn(
    "h-11 w-full rounded-lg border border-gray-300 px-4",
    "text-base text-gray-900 placeholder:text-gray-500",
    "focus:border-primary-500 focus:ring-2 focus:ring-primary-500 focus:ring-offset-0",
    "disabled:cursor-not-allowed disabled:opacity-50"
  )}
/>
アイコンボタンの変換

Figma の仕様:

  • サイズ:40x40px
  • アイコン:20x20px、中央揃え
  • 枠線の角丸:8px
  • ホバー時の背景:#F3F4F6
<button
  className={cn(
    "flex h-10 w-10 items-center justify-center rounded-lg",
    "text-gray-700 transition-colors",
    "hover:bg-gray-100",
    "focus-visible:ring-2 focus-visible:ring-primary-500"
  )}
>
  <Icon className="h-5 w-5" />
</button>

ベストプラクティス

  1. 二度測る:すべての寸法がFigmaと完全に一致していることを確認します
  2. デザイントークンを使用する:ハードコードされた値ではなく、トークンにマッピングします
  3. すべての状態に対応する:ホバー、フォーカス、アクティブ、無効、エラーを含めます
  4. レスポンシブにする:デザインにあるすべてのブレークポイントを実装します
  5. アクセシビリティ:Figmaに状態が示されている場合はARIAを追加します
  6. アニメーション:トランジションのタイミングをデザインに合わせます
  7. ダークモード:デザインがある場合は、クラスバリアントを使用して実装します
  8. コンポーネントバリアント:再利用可能なバリアント用のpropsを作成します
  9. ドキュメント:デザインからの逸脱があれば記録します
  10. レビュー:実装についてデザイナーの承認を得ます

出力チェックリスト

デザインからコンポーネントへの変換には、次の項目をすべて含めてください。

  • Figmaの寸法に正確に一致する間隔
  • タイポグラフィのスケールとウェイト
  • デザインシステムのすべての色の値
  • 角丸とシャドウ
  • ホバー状態のスタイル
  • フォーカス状態のスタイル(アクセシブル)
  • アクティブ/押下状態のスタイル
  • 無効状態のスタイル
  • レスポンシブブレークポイントのルール
  • デザイントークンのマッピングに関するドキュメント
  • アクセシビリティ属性
  • 状態に応じたコンポーネントバリアント

コメント