@su-record/vibe 2.8.20 → 2.8.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,463 +1,10 @@
1
1
  ---
2
2
  name: vibe-figma-rules
3
- description: Figma to Code 공통 규칙 Model Routing, 스택 감지, 브레이크포인트, 이미지 분류, 컴포넌트 통합
3
+ description: "[Merged] vibe-figma (rules are inlined) 참조"
4
4
  triggers: []
5
5
  tier: standard
6
6
  ---
7
7
 
8
- # Skill: vibe-figma-rules — 공통 규칙 (Single Source of Truth)
8
+ # vibe-figma-rules
9
9
 
10
- 모든 vibe-figma-* 스킬이 참조하는 공통 규칙 정의.
11
- 중복 방지를 위해 **이 파일에만 정의**하고, 다른 스킬에서는 "vibe-figma-rules R-N 참조"로 사용.
12
-
13
- ---
14
-
15
- ## R-0. 설계 철학
16
-
17
- > **비정형 레이어에서도 원본 디자인 수준의 완성도를 달성한다.**
18
-
19
- 실무 Figma 파일의 현실:
20
- ```
21
- "Frame 633372" ← 의미 없는 자동 이름
22
- "Frame 633371" ← 중첩된 의미 없는 프레임
23
- "Frame 633370" ← AI가 구조를 파악할 수 없음
24
- ```
25
-
26
- 레이어명이 "Frame 47", "Group 12"이고, Auto Layout 없이 절대 배치된 프레임이 대부분.
27
- 그러나 `get_design_context`는 레이어가 비정형이어도 **스타일 토큰 값(색상, 폰트, 간격)과
28
- 에셋 URL은 정확하게 반환**한다. 이 값들은 디자이너가 Figma UI에서 보는 것과 동일한 값이다.
29
-
30
- ### 역할 분담
31
-
32
- ```
33
- 스크린샷이 답하는 것 (구조):
34
- — WHAT goes WHERE: 레이아웃 구조, 섹션 경계, 이미지 배치, z-index, 겹침 관계
35
- — 어떤 요소가 배경인지 콘텐츠인지, 어디에 오버레이가 있는지
36
- — 참조 코드의 구조가 스크린샷과 다르면 → 스크린샷이 맞다
37
-
38
- 참조 코드가 답하는 것 (정확한 값):
39
- — EXACT VALUES: hex 색상, font-size(px), font-weight, line-height,
40
- padding, gap, margin, border-radius, shadow, 에셋 URL
41
- — 이 값들은 Figma 디자인 토큰에서 직접 추출된 것이므로 정확하다
42
- — 스크린샷에서 추정할 필요 없이 참조 코드의 값을 그대로 사용한다
43
- — 단, px 값에는 스케일 팩터를 적용해야 한다 (R-3)
44
-
45
- 스크린샷이 검증하는 것 (최종 확인):
46
- — 생성 코드의 렌더링 결과가 원본 스크린샷과 시각적으로 일치하는지
47
- — Match Score 95%+, P1=0이 완료 기준
48
- ```
49
-
50
- ### 핵심 원칙
51
-
52
- ```
53
- 1. 참조 코드의 스타일 값을 반드시 사용한다
54
- — get_design_context가 반환하는 색상/폰트/간격 값은 Figma 토큰에서 온 정확한 값
55
- — 스크린샷에서 색상을 추정하거나 폰트 크기를 눈대중으로 읽지 않는다
56
- — 참조 코드의 값 + 스케일 팩터 적용 = 코드에 쓸 값
57
-
58
- 2. 스크린샷으로 구조를 결정한다
59
- — 레이어 구조("Frame 633372")가 무의미해도 스크린샷에서 섹션 경계를 파악
60
- — 참조 코드의 HTML 구조가 스크린샷과 다르면 → 스크린샷 기준으로 재구성
61
- — 이미지 배치(배경/콘텐츠/오버레이)도 스크린샷에서 판단
62
-
63
- 3. 스크린샷으로 누락을 잡는다
64
- — 참조 코드에 없는 시각 요소가 스크린샷에 보이면 → 추가 구현
65
- — 이미지 인벤토리는 스크린샷에서 작성 (참조 코드에 없는 이미지도 잡기 위해)
66
-
67
- 4. 검증은 항상 시각적 비교로
68
- — 완료 기준: 원본 스크린샷 vs 생성 코드의 Match Score 95%+, P1=0
69
- — 코드의 "정확성"이 아니라 "보이는 결과"가 기준이다
70
- ```
71
-
72
- ### MCP 도구별 역할
73
-
74
- ```
75
- get_design_context → 정확한 스타일 값 + 에셋 URL (코드 작성의 데이터 소스)
76
- get_screenshot → 구조 파악 + 누락 검출 + 최종 시각 검증 (구조의 진실)
77
- get_metadata → 프레임 목록 + nodeId 확보 (탐색 용도)
78
- ```
79
-
80
- ---
81
-
82
- ## R-1. Model Routing
83
-
84
- | Step | Claude | GPT (Codex) | 이유 |
85
- |------|--------|-------------|------|
86
- | Step A (스토리보드 + 구조) | **Haiku → Sonnet** | — | MCP 추출 → 구조 설계 |
87
- | Step B (디자인 추출) | **Haiku** | — | MCP + 이미지 다운로드 |
88
- | Step B (코드 생성) | **Sonnet** | **gpt-5.3-codex-spark** (병렬) | 섹션별 컴포넌트 생성 |
89
- | Step B (검증) | **Sonnet** | — | 이미지 비교 + auto-fix |
90
- | Step C (추가 뷰포트) | **Haiku → Sonnet** | — | 반응형 레이어 추가 |
91
- | Step D (공통화 + 검증) | **Sonnet** | — | 리팩토링 + 최종 검증 |
92
- | Post (코드 리뷰) | — | **gpt-5.3-codex** | 전체 코드 품질 검증 |
93
-
94
- ### GPT 모델 선택 기준
95
-
96
- | 모델 | config key | 용도 |
97
- |------|-----------|------|
98
- | `gpt-5.4` | `models.gpt` | 아키텍처 판단, 복잡한 추론 |
99
- | `gpt-5.3-codex` | `models.gptCodex` | 코드 리뷰, 분석 (정확도 우선) |
100
- | `gpt-5.3-codex-spark` | `models.gptCodexSpark` | 코드 생성 (속도 우선) |
101
-
102
- `~/.vibe/config.json`의 `models`에서 오버라이드 가능.
103
-
104
- ---
105
-
106
- ## R-2. 프로젝트 스택 감지
107
-
108
- ### 2-1. Detect Stack
109
-
110
- 1. Read `.claude/vibe/config.json` → `stacks` 필드
111
- 2. config 없으면 프로젝트 파일에서 감지:
112
-
113
- | 감지 대상 | 파일 패턴 |
114
- |-----------|----------|
115
- | React | `package.json` → `react` in deps |
116
- | Vue | `package.json` → `vue` in deps |
117
- | Next.js | `next.config.*` |
118
- | Nuxt | `nuxt.config.*` |
119
- | Svelte | `svelte.config.*` |
120
- | Tailwind | `tailwind.config.*` |
121
- | CSS Modules | `*.module.css` 패턴 |
122
- | SCSS | `*.scss` 또는 `sass` in deps |
123
- | CSS-in-JS | `styled-components` / `@emotion` in deps |
124
-
125
- ### 2-2. 디렉토리 감지
126
-
127
- | 용도 | Next.js | Nuxt | React | Vue |
128
- |------|---------|------|-------|-----|
129
- | 페이지 | `pages/` or `app/` | `pages/` | `src/pages/` or `src/views/` | `src/views/` |
130
- | 컴포넌트 | `components/` or `src/components/` | `components/` | `src/components/` | `src/components/` |
131
- | 스타일 | SCSS: `assets/scss/` or `src/styles/`, CSS: `src/styles/`, Tailwind: `tailwind.config.*` |
132
-
133
- ### 2-3. Design Context 로드
134
-
135
- 순서대로 읽음 (나중 소스가 우선):
136
-
137
- 1. **`.claude/vibe/design-context.json`** — 브랜드, 접근성, 디바이스 제약
138
- 2. **`.claude/vibe/design-system/{project}/MASTER.md`** — 토큰 정의
139
-
140
- **결정 규칙**: Figma 토큰 ≈ 기존 MASTER.md 토큰 (색상 ΔE < 5 또는 간격 ±2px) → 기존 토큰 사용, 중복 생성 금지.
141
-
142
- ---
143
-
144
- ## R-3. 브레이크포인트 + 스케일 팩터
145
-
146
- ### 소스 우선순위
147
-
148
- | 순위 | 소스 | 방법 |
149
- |------|------|------|
150
- | 1 | **스토리보드** | Step A에서 추출한 `storyboardSpec.breakpoints` |
151
- | 2 | **`~/.vibe/config.json`** | `figma.breakpoints` (CLI로 커스터마이즈) |
152
- | 3 | **프로젝트 CSS/Tailwind** | `tailwind.config.*` → `theme.screens`, 또는 `@media` 패턴 |
153
- | 4 | **기본값** | 아래 테이블 |
154
-
155
- ### 기본 브레이크포인트
156
-
157
- ```
158
- breakpoint: 1024px ← PC↔Mobile 경계 (@media min-width)
159
- pcTarget: 1920px ← PC 메인 타겟
160
- mobilePortrait: 480px ← Mobile portrait max
161
- mobileMinimum: 360px ← Mobile 최소 지원
162
- designPc: 2560px ← Figma PC 아트보드 (디자인 2x 스케일)
163
- designMobile: 720px ← Figma Mobile 아트보드 (디자인 2x 스케일)
164
- ```
165
-
166
- ### 스케일 팩터 계산
167
-
168
- ```
169
- PC: scaleFactor.pc = pcTarget / designPc (기본: 1920/2560 = 0.75)
170
- Mobile: scaleFactor.mobile = mobilePortrait / designMobile (기본: 480/720 = 0.667)
171
-
172
- 적용: 코드 값 = Figma 추출 값 × scaleFactor
173
- - 색상 hex → 스케일 불필요
174
- - 타이포 (font-size, line-height) → 스케일 적용
175
- - 간격 (padding, gap, margin) → 스케일 적용
176
- ```
177
-
178
- ### clamp() 계산 공식
179
-
180
- ```
181
- Step 1: Figma 값 → 타겟 값
182
- targetMobile = figmaMobileValue × scaleFactor.mobile
183
- targetPc = figmaPcValue × scaleFactor.pc
184
-
185
- Step 2: clamp() 생성
186
- minVw = mobileMinimum (360px)
187
- maxVw = pcTarget (1920px)
188
- slope = (targetPc - targetMobile) / (maxVw - minVw)
189
- intercept = targetMobile - slope × minVw
190
- → clamp({targetMobile/16}rem, {intercept/16}rem + {slope×100}vw, {targetPc/16}rem)
191
- ```
192
-
193
- ### CLI 커스터마이즈
194
-
195
- ```bash
196
- vibe figma breakpoints # 현재 값 확인
197
- vibe figma breakpoints --set breakpoint=768 # PC↔Mobile 경계 변경
198
- ```
199
-
200
- ---
201
-
202
- ## R-4. 이미지 분류 + Multi-Layer 패턴
203
-
204
- ### 분류 기준
205
-
206
- | 판별 조건 | 분류 | 코드 패턴 |
207
- |----------|------|----------|
208
- | 프레임 배경이고 위에 텍스트/UI 겹침 | **Background** | `background-image` + `background-size` |
209
- | 독립 레이어, 겹치는 요소 없음 | **Content** | `<img>` 또는 `<picture>` |
210
- | 이름에 `icon`/`logo`/`avatar` | **Inline Asset** | `<img>` (작은 크기) |
211
- | `scaleMode: "TILE"` 반복 패턴 | **Pattern** | `background-repeat` |
212
- | 전체 덮음 + opacity < 1 또는 blendMode | **Overlay** | `background-image` + overlay |
213
-
214
- ### Multi-Layer 패턴 (배경 이미지 섹션 필수 구조)
215
-
216
- ```
217
- .{section}Section ← 레이아웃 (position: relative, overflow: hidden)
218
- .{section}Bg ← 배경 이미지 — z-index: 0
219
- .{section}BgOverlay ← 오버레이 (선택) — z-index: 1
220
- .{section}Character ← 캐릭터/일러스트 (선택) — z-index: 2
221
- .{section}Content ← 텍스트/버튼/UI — z-index: 최상위
222
- ```
223
-
224
- ```css
225
- .{section}Section { position: relative; overflow: hidden; }
226
- .{section}Bg {
227
- position: absolute; inset: 0; z-index: 0;
228
- background-image: url('/images/{feature}/{name}.webp');
229
- background-size: cover; background-position: center;
230
- }
231
- .{section}BgOverlay {
232
- position: absolute; inset: 0; z-index: 1;
233
- background: linear-gradient(to bottom, rgba(0,0,0,0.3), rgba(0,0,0,0.7));
234
- }
235
- .{section}Content { position: relative; z-index: 2; }
236
- ```
237
-
238
- ### 배경 이미지 클래스 분리 원칙
239
-
240
- | 유형 | 클래스 예시 | 분리 이유 |
241
- |------|-----------|----------|
242
- | 섹션 전면 배경 | `.heroBg` | 시즌/이벤트별 이미지 교체 |
243
- | 오버레이 | `.heroBgOverlay` | 투명도/그라데이션 독립 조절 |
244
- | 패턴/텍스처 | `.sectionPattern` | repeat/size 별도 제어 |
245
- | 캐릭터/일러스트 | `.heroCharacter` | 콜라보별 교체, position 조절 |
246
- | 그라데이션 | `.sectionGradient` | 테마별 색상 변경 |
247
-
248
- ### 반응형 배경 이미지
249
-
250
- ```css
251
- .heroBg { background-image: url('/images/hero-mobile.webp'); }
252
- @media (min-width: var(--breakpoint)) {
253
- .heroBg { background-image: url('/images/hero-pc.webp'); }
254
- }
255
- ```
256
-
257
- ### 이미지 공통 규칙
258
-
259
- | 규칙 | 설명 |
260
- |------|------|
261
- | format | `.webp` 우선 (fallback: `.png`/`.jpg`) |
262
- | alt | 레이어 이름에서 파생, 장식은 `alt=""` + `aria-hidden="true"` |
263
- | width/height | 항상 명시 (CLS 방지), 스케일 팩터 적용 |
264
- | loading | 뷰포트 상단 → `eager`, 나머지 → `lazy` |
265
- | object-fit | `cover` (배경), `contain` (로고/아이콘), `fill` 금지 |
266
-
267
- ---
268
-
269
- ## R-5. 컴포넌트 통합 규칙 (80% Rule)
270
-
271
- ### 유사도 판단
272
-
273
- ```
274
- 구조 80%+ 동일 (색상/크기/텍스트만 다름)
275
- → 하나의 컴포넌트 + variant prop으로 통합
276
-
277
- 구조 자체가 다름 (요소 추가/제거, 레이아웃 방향 변경)
278
- → 별도 컴포넌트 유지
279
- ```
280
-
281
- ### 스택별 variant 구현
282
-
283
- | Stack | 방법 |
284
- |-------|------|
285
- | React / Next.js | `variant` prop + 조건부 className |
286
- | Vue / Nuxt | `variant` prop + `<slot>` |
287
- | Svelte | `variant` prop + `<slot>` |
288
- | React Native | `variant` prop + StyleSheet 조건 |
289
-
290
- ### Fragment / 래퍼 제거
291
-
292
- 스타일이나 이벤트가 없는 래핑 요소 → 프레임워크 제공 투명 래퍼 사용:
293
-
294
- | Stack | 투명 래퍼 |
295
- |-------|----------|
296
- | React / Next.js | `<>...</>` |
297
- | Vue / Nuxt | `<template>` (컴포넌트 루트 이외) |
298
- | Svelte | `{#if}`, `{#each}` 블록 |
299
-
300
- ---
301
-
302
- ## R-6. 검증 루프 공통 규칙
303
-
304
- 모든 Step에서 사용하는 스크린샷 기반 검증 프로세스.
305
-
306
- ### 6-1. 원본 스크린샷 확보
307
-
308
- ```
309
- Step A에서 get_screenshot으로 확보한 섹션별 원본 이미지를 기준으로 사용.
310
- 없으면 해당 섹션의 nodeId로 get_screenshot 재호출.
311
-
312
- 원본 = Figma 디자인 스크린샷 (디자이너 의도)
313
- ```
314
-
315
- ### 6-2. 생성 코드 렌더링 확보
316
-
317
- ```
318
- 방법 (우선순위):
319
- 1. /vibe.utils --preview → 브라우저 렌더링 스크린샷 자동 생성
320
- 2. dev 서버 실행 중이면 → 해당 페이지 스크린샷 (Playwright/Puppeteer)
321
- 3. 둘 다 불가능하면 → 생성된 코드를 직접 읽고 시각적 결과를 추론
322
-
323
- ⚠️ 방법 3(코드 읽기 추론)은 최후 수단.
324
- 가능한 한 실제 렌더링 결과를 확보해야 정확한 비교 가능.
325
- ```
326
-
327
- ### 6-3. 섹션별 비교 (전체 페이지가 아닌 섹션 단위)
328
-
329
- ```
330
- 각 섹션 컴포넌트를 개별로 비교:
331
- 원본: Figma 섹션 스크린샷 (get_screenshot per section)
332
- 생성: 렌더링된 섹션 스크린샷 (또는 코드 추론)
333
-
334
- 섹션별로 비교해야 하는 이유:
335
- - 전체 페이지 비교는 스크롤 길이 차이로 오차가 큼
336
- - 섹션 단위가 수정 범위를 좁힐 수 있음
337
- - P1 발견 시 해당 섹션만 수정 → 재비교
338
- ```
339
-
340
- ### 6-4. 비교 항목 + P1/P2 분류
341
-
342
- | 비교 항목 | P1 (필수 수정) | P2 (권장 수정) |
343
- |----------|---------------|---------------|
344
- | **이미지 인벤토리** | 인벤토리에 있는 이미지가 코드에 없음 | — |
345
- | **배경 이미지** | 누락, Multi-Layer 미적용, 경로 깨짐 | 크기/위치 미세 차이 |
346
- | **이미지 다운로드** | 파일 미존재, 0byte, Figma URL 잔존 | — |
347
- | **레이아웃** | 요소 배치 방향 다름, 섹션 순서 다름 | 미세 정렬 차이 |
348
- | **색상** | 배경/텍스트색 완전히 다름 | 미세한 톤 차이 (ΔE < 10) |
349
- | **타이포** | 제목/본문 크기 비율 다름, 굵기 다름 | ±2px 차이 |
350
- | **간격** | 섹션 간 간격 크게 다름, 요소 겹침 | ±4px 차이 |
351
- | **누락 요소** | 스크린샷에 보이는 요소가 코드에 없음 | — |
352
- | **오버레이** | 배경 위 텍스트 가독성 확보 안 됨 | 투명도 미세 차이 |
353
-
354
- ### 6-5. Diff Report 출력
355
-
356
- ```markdown
357
- ## Visual Diff Report — {섹션명}
358
-
359
- 원본: Figma {섹션} 스크린샷
360
- 생성: 렌더링 결과 (또는 코드 추론)
361
-
362
- ### Match Score: {N}%
363
-
364
- | # | 항목 | 원본 | 생성 코드 | 심각도 |
365
- |---|------|------|----------|--------|
366
- | 1 | 배경 이미지 | 눈 테마 + 그라데이션 | 누락 | P1 |
367
- | 2 | 제목 font-size | ~36px (스케일 후) | 24px | P1 |
368
- | 3 | 카드 border-radius | ~12px | 8px | P2 |
369
- ```
370
-
371
- ### 6-6. Auto-Fix Loop
372
-
373
- ```
374
- P1이 있으면:
375
- 1. 해당 섹션의 컴포넌트/스타일 파일 수정
376
- 2. 수정 후 렌더링 재확보 (가능하면)
377
- 3. 원본 스크린샷과 재비교
378
- 4. P1=0 될 때까지 반복 — 횟수 제한 없음
379
-
380
- 같은 P1이 반복될 때:
381
- - 이전과 동일한 수정을 반복하지 않는다
382
- - 접근 방식을 바꿔서 시도한다 (다른 CSS 속성, 다른 레이아웃 전략)
383
- - 접근을 바꿔도 해결 안 되면 → 사용자에게 해당 항목을 보여주고 방향 확인
384
- - 사용자 확인 후에도 루프는 계속된다 — P1=0이 될 때까지 멈추지 않음
385
- ```
386
-
387
- ### 6-7. 완료 조건
388
-
389
- ```
390
- ✅ 모든 섹션 Match Score 95%+
391
- ✅ P1 = 0 (전 섹션)
392
- ✅ 모든 이미지 에셋 표시 + Figma 임시 URL 잔존 0건
393
- ✅ (반응형) 각 뷰포트 독립 검증 통과
394
- ✅ placeholder 0건 — "placeholder", "Key Visual Image", 빈 dashed box,
395
- alt="placeholder", src="" 등이 코드에 남아있으면 미완성
396
- ✅ 단색/gradient 대체 0건 — 원본에 이미지 배경인 곳이 CSS 단색으로 처리되면 미완성
397
- ✅ 텍스트 스타일 전수 적용 — 브라우저 기본 스타일(검은색 16px)로 보이는 텍스트 0건
398
- ✅ 스타일 외부 파일 — 컴포넌트 내 <style> 블록 0건, 인라인 style="" 0건
399
- ```
400
-
401
- ---
402
-
403
- ## R-7. 섹션별 분석 프로세스
404
-
405
- ### Step 1: get_design_context (스타일 값 + 에셋)
406
-
407
- ```
408
- get_design_context(fileKey, 섹션 nodeId)
409
- → 참조 코드 반환 (React+Tailwind 형태)
410
-
411
- 참조 코드에서 추출하는 것 (정확한 값 — Figma 토큰에서 직접 추출됨):
412
- ✅ 색상: hex 값 (text-[#1B3A1D], bg-[#0A1628] 등)
413
- ✅ 폰트: font-size(px), font-weight, line-height, font-family
414
- ✅ 간격: padding, margin, gap (px)
415
- ✅ 장식: border-radius, box-shadow, opacity
416
- ✅ 에셋 URL: const xxxImage = 'https://figma.com/api/mcp/asset/...'
417
-
418
- 이 값들은 디자이너가 Figma UI 우측 패널에서 보는 것과 동일.
419
- 스크린샷에서 추정할 필요 없이 이 값을 그대로 사용한다.
420
- 단, px 값에는 스케일 팩터를 적용한다 (R-3).
421
- ```
422
-
423
- ### Step 2: get_screenshot (구조 + 이미지 인벤토리)
424
-
425
- ```
426
- get_screenshot(fileKey, 섹션 nodeId)
427
- → 원본 디자인 이미지 확보
428
-
429
- 스크린샷에서 판단하는 것 (구조 — 참조 코드가 틀릴 수 있는 영역):
430
- ✅ 레이아웃 구조: 섹션 경계, flex/grid 방향, 요소 배치 순서
431
- ✅ 이미지 배치: 배경/콘텐츠/오버레이 분류, z-index 관계
432
- ✅ 이미지 인벤토리: 보이는 모든 이미지 목록 (참조 코드에 없는 것도 잡음)
433
- ✅ 겹침 구조: 텍스트-배경 관계, 오버레이 유무
434
- ✅ 누락 검출: 참조 코드에 없는 시각 요소 발견
435
- ```
436
-
437
- ### Step 3: 코드 생성
438
-
439
- ```
440
- a. 참조 코드의 스타일 값을 그대로 사용하여 외부 스타일 파일 작성:
441
- - 색상 hex → 토큰 변수로 정의
442
- - font-size × scaleFactor → 토큰 변수로 정의
443
- - 간격 × scaleFactor → 토큰 변수로 정의
444
-
445
- b. 스크린샷의 구조로 HTML/template 결정:
446
- - 레이아웃 방향, 요소 순서
447
- - Multi-Layer 배경 구조 (배경 이미지가 있으면)
448
- - 참조 코드의 구조가 스크린샷과 다르면 → 스크린샷 기준
449
-
450
- c. 에셋 URL → 다운로드 → 로컬 경로로 교체
451
-
452
- d. 스크린샷에 보이지만 참조 코드에 없는 요소 → 추가 구현
453
- ```
454
-
455
- ### 참조 코드의 구조가 틀릴 때
456
-
457
- ```
458
- 레이어가 "Frame 633372"면 참조 코드의 HTML 구조가 부정확할 수 있다.
459
- 이때:
460
- - 스타일 값(색상, 폰트, 간격)은 여전히 정확 → 그대로 사용
461
- - HTML 구조(어떤 요소가 어디에)만 스크린샷 기준으로 재배치
462
- - 에셋 URL도 여전히 유효 → 그대로 다운로드
463
- ```
10
+ 스킬의 규칙은 **vibe-figma**, **vibe-figma-extract**, **vibe-figma-convert** 3개 스킬에 내장되었습니다.
@@ -1,214 +1,10 @@
1
1
  ---
2
2
  name: vibe-figma-style
3
- description: Style architecture tokens, SCSS, class naming, responsive tokens
3
+ description: "[Merged] vibe-figma-convert 참조"
4
4
  triggers: []
5
5
  tier: standard
6
6
  ---
7
7
 
8
- # Skill: vibe-figma-style — 스타일 아키텍처
8
+ # vibe-figma-style
9
9
 
10
- 토큰 포맷, SCSS 규칙, 클래스 네이밍, 반응형 토큰 계산.
11
- 디렉토리 감지는 **vibe-figma-rules R-2.2** 참조.
12
-
13
- ---
14
-
15
- ## S-1. 토큰 Resolution Priority
16
-
17
- **기본 모드 (프로젝트 통합):**
18
-
19
- 1. **MASTER.md** (`.claude/vibe/design-system/{project}/MASTER.md`) — 최우선
20
- 2. **design-context.json** (`.claude/vibe/design-context.json`) — 보조
21
- 3. **프로젝트 테마 파일** (tailwind.config, CSS variables 등) — 폴백
22
- 4. **새 figma-tokens 생성** — 마지막 수단
23
-
24
- **--new 모드:** 자체 완결 토큰 파일 생성 (MASTER.md 의존 없음).
25
-
26
- ### Mapping Rules
27
-
28
- - Figma color ≈ 기존 토큰 (ΔE < 5) → 기존 토큰명 사용
29
- - Figma spacing ≈ 기존 토큰 (±2px) → 기존 토큰명 사용
30
- - 매칭 없는 값 → `figma-tokens` 보충 토큰으로 추가
31
-
32
- ---
33
-
34
- ## S-2. 토큰 파일 포맷
35
-
36
- ### CSS Custom Properties (기본)
37
-
38
- ```css
39
- :root {
40
- /* Colors */
41
- --figma-primary: #3B82F6;
42
- --figma-surface: #FFFFFF;
43
- --figma-text-primary: #111827;
44
- --figma-border: #E5E7EB;
45
-
46
- /* Typography */
47
- --figma-font-family: 'Inter', system-ui, sans-serif;
48
- --figma-text-sm: 0.875rem;
49
- --figma-text-base: 1rem;
50
- --figma-text-xl: 1.25rem;
51
-
52
- /* Spacing */
53
- --figma-space-2: 0.5rem;
54
- --figma-space-4: 1rem;
55
- --figma-space-8: 2rem;
56
-
57
- /* Shadows, Radius */
58
- --figma-shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
59
- --figma-radius-md: 0.5rem;
60
- }
61
- ```
62
-
63
- ### SCSS (SCSS 감지 시)
64
-
65
- ```scss
66
- // _figma-tokens.scss
67
- @use 'sass:math';
68
-
69
- $figma-primary: #3B82F6;
70
- $figma-text-primary: #111827;
71
- $figma-font-family: 'Inter', system-ui, sans-serif;
72
- $figma-text-base: 1rem;
73
- $figma-space-4: 1rem;
74
- $figma-radius-md: 0.5rem;
75
-
76
- // Breakpoints
77
- $figma-bp: 1024px;
78
- $figma-bp-mobile-min: 360px;
79
- $figma-bp-pc-target: 1920px;
80
-
81
- // Mixins
82
- @mixin figma-pc { @media (min-width: $figma-bp) { @content; } }
83
- @mixin figma-mobile-only { @media (max-width: $figma-bp - 1px) { @content; } }
84
-
85
- // Fluid function (clamp 자동화)
86
- @function figma-fluid($mobile, $desktop, $min-vw: $figma-bp-mobile-min, $max-vw: $figma-bp-pc-target) {
87
- $slope: math.div($desktop - $mobile, $max-vw - $min-vw);
88
- $intercept: $mobile - $slope * $min-vw;
89
- @return clamp(#{$mobile}, #{$intercept} + #{$slope * 100}vw, #{$desktop});
90
- }
91
- ```
92
-
93
- **SCSS 사용 시 필수 규칙:**
94
- - `@use 'figma-tokens' as figma;` 네임스페이스 import
95
- - `@include figma.figma-pc { }` — `@media` 직접 사용 금지
96
- - `figma-fluid($mobile, $desktop)` — 수동 clamp() 금지
97
-
98
- ### Tailwind (Tailwind 감지 시)
99
-
100
- ```js
101
- export const figmaTokens = {
102
- colors: { figma: { primary: '#3B82F6' } },
103
- spacing: { /* ... */ },
104
- borderRadius: { /* ... */ },
105
- };
106
- ```
107
-
108
- ---
109
-
110
- ## S-3. 반응형 토큰 (responsive mode)
111
-
112
- 뷰포트 간 값이 다른 토큰은 `clamp()`로 fluid 스케일링.
113
- 동일한 값은 static 유지. 계산 공식은 **vibe-figma-rules R-3** 참조.
114
-
115
- ```css
116
- :root {
117
- /* Shared (뷰포트 간 동일) */
118
- --figma-primary: #3B82F6;
119
- --figma-radius-md: 0.5rem;
120
-
121
- /* Fluid (뷰포트 간 다름) */
122
- --figma-text-h1: clamp(2rem, 1.423rem + 2.564vw, 4.5rem);
123
- --figma-space-section: clamp(1rem, 0.248rem + 3.286vw, 3rem);
124
- }
125
- ```
126
-
127
- ```scss
128
- // SCSS — figma-fluid() 사용
129
- $figma-text-h1: figma-fluid(2rem, 4.5rem);
130
- $figma-space-section: figma-fluid(1rem, 3rem);
131
- ```
132
-
133
- ---
134
-
135
- ## S-4. 스타일 파일 구조
136
-
137
- ### --new 모드 (자체 완결)
138
-
139
- ```
140
- styles/{feature-name}/
141
- index.scss ← 진입점
142
- _tokens.scss ← 피처 전용 토큰
143
- _mixins.scss ← 피처 전용 mixin
144
- _base.scss ← 피처 공통 reset/폰트
145
- layout/ ← 섹션 배치/구조 (position, flex/grid, padding, background)
146
- _page.scss
147
- _hero.scss
148
- _feature-a.scss
149
- components/ ← UI 요소 모양 (color, font, border, shadow, hover)
150
- _card.scss
151
- _button.scss
152
- _popups.scss
153
- ```
154
-
155
- **layout vs components 구분:**
156
- - `layout/` → 섹션의 위치, 크기, 배치, 간격, 배경
157
- - `components/` → UI 요소의 모양, 색상, 타이포, 인터랙션 상태
158
-
159
- ### 기본 모드 (기존 프로젝트 추가)
160
-
161
- ```
162
- 기존 스타일 구조를 분석하고 그대로 따른다:
163
- 1. Glob/Grep으로 기존 패턴 탐색 (디렉토리, 네이밍, import 방식)
164
- 2. 기존 토큰/변수/mixin 재사용
165
- 3. 새 컴포넌트 스타일만 기존 패턴대로 추가
166
- 4. 기존 스타일 파일은 수정하지 않음
167
- ```
168
-
169
- ---
170
-
171
- ## S-5. 클래스 네이밍 규칙
172
-
173
- 클래스 이름은 **역할(role)**을 드러내야 하며, 구조나 스타일 속성을 이름에 넣지 않는다.
174
-
175
- | 원칙 | 좋은 예 | 나쁜 예 |
176
- |------|--------|--------|
177
- | 역할 기반 | `.heroSection`, `.productCard` | `.section1`, `.card` |
178
- | 용도 명시 | `.heroBg`, `.cardThumbnail` | `.bg`, `.img` |
179
- | 관계 표현 | `.heroTitle`, `.heroDescription` | `.title`, `.text` |
180
- | 축약 금지 | `.navigationMenu` | `.navMnu` |
181
-
182
- ### 구체적 규칙
183
-
184
- ```
185
- 1. 컴포넌트 루트: 섹션/컴포넌트 이름 → .loginForm, .heroSection
186
- 2. 자식 요소: 부모이름 + 역할 → .heroTitle, .heroCta
187
- 3. 이미지 클래스: 용도 명시 → .heroBg, .productPhoto, .brandLogo
188
- 4. 상태 변형: variant/state 접미사 → .buttonPrimary, .cardHighlight
189
- ```
190
-
191
- ### Anti-Patterns
192
-
193
- ```css
194
- /* WRONG */
195
- .wrapper { } .inner { } .box { } .item { } .text1 { }
196
-
197
- /* CORRECT */
198
- .eventSection { } .eventContent { } .rewardCard { } .eventDescription { }
199
- ```
200
-
201
- ---
202
-
203
- ## S-6. 토큰 매핑 코멘트 (기본 모드)
204
-
205
- 토큰 파일 상단에 매핑 결과를 코멘트로 출력:
206
-
207
- ```
208
- /* Figma Token Mapping:
209
- * Figma "Primary" → var(--figma-primary) = #3B82F6
210
- * ✅ Matched: var(--color-blue-500) from MASTER.md
211
- * Figma "Accent" → var(--figma-accent) = #7C3AED
212
- * New token: no existing match
213
- */
214
- ```
10
+ 스킬은 **vibe-figma-convert**으로 병합되었습니다.