---
name: figma-to-code
description: |
  트리거: "figma를 코드로", "디자인 구현해줘", "피그마 코드 변환", "figma to code", "디자인 스펙 구현"
  수행: Figma 디자인 명세(JSON 또는 텍스트 설명) → React 또는 Vue 코드로 변환. Tailwind CSS 우선 사용
  출력: 컴포넌트 파일, Tailwind 클래스 적용 마크업, 반응형 처리
---

# Figma to Code Converter

## 목적

Figma 디자인 명세(JSON export, 텍스트 설명, 스크린샷 설명)를 실제 동작하는 React 또는 Vue 컴포넌트 코드로 변환한다.
Tailwind CSS를 우선 사용하며, 디자인 토큰(색상, 폰트, 간격)을 코드에 정확히 반영한다.

## 실행 절차

1. **입력 분석**: Figma JSON / 텍스트 명세 / 이미지 설명에서 컴포넌트 구조, 색상, 폰트, 간격 값 추출
2. **컴포넌트 계층 파악**: 최상위 프레임 → 섹션 → 개별 요소로 분해
3. **디자인 토큰 매핑**: Figma 색상값 → Tailwind 색상 클래스 또는 CSS 변수로 변환
4. **마크업 생성**: 시맨틱 HTML 태그 사용, flexbox/grid 레이아웃 구현
5. **반응형 처리**: Figma의 Auto Layout 및 Constraints → Tailwind 반응형 접두사 적용
6. **인터랙션 추가**: hover, focus, active 상태 스타일링

## 출력 형식

### Figma 명세 입력 예시

```
Frame: ProductCard
- 너비: 320px, 배경: #FFFFFF, 모서리: 12px, 그림자: 0 4px 16px rgba(0,0,0,0.1)
- 이미지 영역: 320x200, 배경: #F3F4F6
- 뱃지: 좌상단, 배경: #EFF6FF, 텍스트: #2563EB, 폰트: 12px/500
- 제목: Pretendard 18px/600, 색상: #111827, 2줄 제한
- 가격: Pretendard 20px/700, 색상: #2563EB
- 원가(취소선): Pretendard 14px/400, 색상: #9CA3AF
- 버튼: 전체너비, 높이 44px, 배경: #2563EB, 텍스트: #FFFFFF, 모서리: 8px
```

### 변환된 코드 예시

```tsx
// ProductCard.tsx
import React from 'react';

interface ProductCardProps {
  imageUrl: string;
  imageAlt: string;
  badge?: string;
  title: string;
  price: number;
  originalPrice?: number;
  onAddToCart: () => void;
}

export function ProductCard({
  imageUrl,
  imageAlt,
  badge,
  title,
  price,
  originalPrice,
  onAddToCart,
}: ProductCardProps) {
  const discountRate = originalPrice
    ? Math.round((1 - price / originalPrice) * 100)
    : null;

  return (
    <article className="w-80 rounded-xl bg-white shadow-[0_4px_16px_rgba(0,0,0,0.1)] overflow-hidden">
      {/* 상품 이미지 */}
      <div className="relative h-[200px] bg-gray-100">
        <img
          src={imageUrl}
          alt={imageAlt}
          className="h-full w-full object-cover"
          loading="lazy"
        />
        {badge && (
          <span className="absolute left-3 top-3 rounded-full bg-blue-50 px-2.5 py-1 text-xs font-medium text-blue-600">
            {badge}
          </span>
        )}
      </div>

      {/* 상품 정보 */}
      <div className="p-4 flex flex-col gap-3">
        <h3 className="text-lg font-semibold text-gray-900 line-clamp-2 leading-snug">
          {title}
        </h3>

        <div className="flex items-center gap-2">
          <span className="text-xl font-bold text-blue-600">
            {price.toLocaleString('ko-KR')}원
          </span>
          {originalPrice && (
            <span className="text-sm text-gray-400 line-through">
              {originalPrice.toLocaleString('ko-KR')}원
            </span>
          )}
          {discountRate && (
            <span className="text-sm font-semibold text-red-500">
              {discountRate}%
            </span>
          )}
        </div>

        <button
          type="button"
          onClick={onAddToCart}
          className="w-full h-11 rounded-lg bg-blue-600 text-white font-medium
                     hover:bg-blue-700 active:bg-blue-800
                     focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2
                     transition-colors duration-150"
        >
          장바구니 담기
        </button>
      </div>
    </article>
  );
}
```

### Figma JSON 입력 처리 예시

```
입력 (Figma JSON 일부):
{
  "name": "LoginForm",
  "type": "FRAME",
  "fills": [{"color": {"r":1,"g":1,"b":1}}],
  "children": [
    {"name": "email-input", "type": "INSTANCE", "componentProperties": {...}},
    {"name": "password-input", "type": "INSTANCE"},
    {"name": "login-button", "fills": [{"color":{"r":0.149,"g":0.384,"b":0.949}}]}
  ]
}
```

```tsx
// LoginForm.tsx (변환 결과)
export function LoginForm({ onSubmit }: { onSubmit: (data: LoginData) => void }) {
  const { register, handleSubmit, formState: { errors } } = useForm<LoginData>();

  return (
    <form
      onSubmit={handleSubmit(onSubmit)}
      className="flex flex-col gap-4 bg-white p-8 rounded-xl"
      noValidate
    >
      <div className="flex flex-col gap-1.5">
        <label htmlFor="email" className="text-sm font-medium text-gray-700">
          이메일
        </label>
        <input
          id="email"
          type="email"
          autoComplete="email"
          aria-invalid={!!errors.email}
          aria-describedby={errors.email ? 'email-error' : undefined}
          className="rounded-lg border border-gray-300 px-3 py-2.5 text-sm
                     focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500
                     aria-invalid:border-red-400 aria-invalid:ring-red-400"
          {...register('email', { required: '이메일을 입력해주세요' })}
        />
        {errors.email && (
          <p id="email-error" className="text-xs text-red-500" role="alert">
            {errors.email.message}
          </p>
        )}
      </div>

      <button
        type="submit"
        className="h-11 rounded-lg bg-[#2563F2] font-medium text-white
                   hover:bg-blue-700 transition-colors"
      >
        로그인
      </button>
    </form>
  );
}
```

## 사용 예시

**입력:**
> "이 Figma 명세를 코드로 바꿔줘: 네비게이션 바, 높이 64px, 배경 흰색, 좌측에 로고 이미지 + 텍스트, 중앙에 메뉴 링크 4개, 우측에 로그인 버튼. 모바일에서는 햄버거 메뉴로 전환."

**출력:**
- `Navbar.tsx` - 데스크톱 + 모바일 반응형, 햄버거 메뉴 토글 포함
- Tailwind 반응형 클래스 (`md:flex`, `md:hidden`) 적용
- ARIA 속성 완비 (aria-expanded, aria-controls)

## 주의사항

- Figma의 rgba 색상값 → Tailwind 팔레트 매핑 우선, 없으면 `[]` 임의값 사용
- Auto Layout `gap` → `gap-*`, `padding` → `p-*`/`px-*`/`py-*` 클래스로 변환
- `line-clamp`는 `@tailwindcss/line-clamp` 플러그인 필요 시 명시
- 이미지는 항상 `alt` 텍스트 포함, 장식용 이미지는 `aria-hidden="true"`
- 프레임워크를 지정하지 않으면 React + TypeScript 기본 출력
- 인터랙션(호버, 클릭) 명세가 없으면 합리적인 기본값 적용 후 주석으로 표시
