@su-record/vibe 2.8.17 → 2.8.18

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.
@@ -8,576 +8,207 @@ tier: standard
8
8
  # Skill: vibe-figma-style — 스타일 아키텍처
9
9
 
10
10
  토큰 포맷, SCSS 규칙, 클래스 네이밍, 반응형 토큰 계산.
11
+ 디렉토리 감지는 **vibe-figma-rules R-2.2** 참조.
11
12
 
12
13
  ---
13
14
 
14
- ## Phase 4: Style Architecture
15
+ ## S-1. 토큰 Resolution Priority
15
16
 
16
- ### 4-1. Global Styles File
17
+ **기본 모드 (프로젝트 통합):**
17
18
 
18
- **Token resolution priority** (default mode):
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 생성** — 마지막 수단
19
23
 
20
- 1. **MASTER.md tokens** if `.claude/vibe/design-system/{project}/MASTER.md` exists, map Figma values to these tokens
21
- 2. **design-context.json tokens** — if `detectedStack.fonts`, `aesthetic.colorMood` exist, align with these
22
- 3. **New figma-tokens** — only for values that have no existing match
24
+ **--new 모드:** 자체 완결 토큰 파일 생성 (MASTER.md 의존 없음).
23
25
 
24
- **--new mode**: Generate self-contained token file (no MASTER.md dependency), in project's standard directories.
25
-
26
- #### Output Structure (both modes — project structure 준수)
27
-
28
- 프로젝트의 기존 디렉토리 구조를 감지하여 올바른 위치에 파일 생성.
29
-
30
- **Step 1: 디렉토리 감지**
31
-
32
- ```
33
- 페이지 디렉토리:
34
- Next.js → pages/ or app/
35
- Nuxt → pages/
36
- React → src/pages/ or src/views/
37
- Vue → src/views/
38
-
39
- 컴포넌트 디렉토리:
40
- Next.js → components/ or src/components/
41
- Nuxt → components/
42
- React → src/components/
43
- Vue → src/components/
44
-
45
- 스타일 디렉토리:
46
- SCSS → assets/scss/ or src/scss/ or src/styles/
47
- CSS → src/styles/ or styles/
48
- Tailwind → tailwind.config.* (extend)
49
- ```
50
-
51
- **Step 2: 스타일 구조 — 모드별 분리**
52
-
53
- Figma 파일명에서 피처명 자동 추출 → kebab-case 변환.
54
-
55
- ### 기본 모드 (기존 프로젝트에 추가)
56
-
57
- ```
58
- ⚠️ 기존 스타일 구조를 먼저 분석하고 그대로 따른다.
59
- 1. Glob/Grep으로 기존 스타일 파일 패턴 탐색:
60
- - 디렉토리 구조 (styles/, scss/, css/)
61
- - 파일 네이밍 (BEM, camelCase, kebab-case)
62
- - import 방식 (@use, @import, CSS Modules)
63
- - 기존 변수/mixin 파일 위치
64
- 2. 기존 토큰/변수/mixin을 최대한 재사용
65
- 3. 새 컴포넌트 스타일만 기존 패턴대로 추가
66
- 4. 기존 스타일 파일을 수정하지 않음 (사이드이펙트 방지)
67
-
68
- 예: 기존 프로젝트가 assets/scss/ 구조를 쓰면:
69
- assets/scss/_variables.scss ← 기존 (수정 안 함)
70
- assets/scss/_mixins.scss ← 기존 (재사용)
71
- assets/scss/pages/
72
- _winter-pcbang.scss ← 새 피처 스타일 (기존 패턴 따름)
73
-
74
- 예: 기존 프로젝트가 CSS Modules를 쓰면:
75
- components/winter-pcbang/
76
- HeroSection.module.scss ← 기존 패턴대로
77
- DailyCheckIn.module.scss
78
- ```
79
-
80
- ### --new 모드 (새 피처, 자체 완결)
81
-
82
- ```
83
- 피처 전용 스타일 폴더를 생성하고, 글로벌 + 컴포넌트별 2-tier 구조:
84
-
85
- styles/{feature-name}/
86
- index.scss ← 진입점
87
-
88
- // ── foundation (토큰, mixin, 기반) ──
89
- _tokens.scss ← 피처 전용 토큰
90
- _mixins.scss ← 피처 전용 mixin
91
- _base.scss ← 피처 공통 reset/폰트
92
-
93
- // ── layout (섹션 배치, 구조) ──
94
- layout/
95
- _page.scss ← 페이지 전체 레이아웃
96
- _hero.scss ← HeroSection 배치/구조
97
- _daily-checkin.scss ← DailyCheckInSection 배치/구조
98
- _play-time-mission.scss ← PlayTimeMissionSection 배치/구조
99
- _token-exchange.scss ← TokenExchangeSection 배치/구조
100
- _token-raffle.scss ← TokenRaffleSection 배치/구조
101
- _caution.scss ← CautionSection 배치/구조
102
-
103
- // ── components (재사용 UI 디자인) ──
104
- components/
105
- _card.scss ← 카드 디자인 (보상, 상품, 아이템)
106
- _button.scss ← 버튼 디자인 (CTA, 출석, 교환)
107
- _badge.scss ← 배지 디자인 (완료, 진행중, 잠금)
108
- _progress.scss ← 프로그레스 바, 게이지
109
- _popups.scss ← 팝업/모달 디자인
110
- _tooltip.scss ← 툴팁, 안내 말풍선
111
- _form.scss ← 입력 폼 (이메일, 검색)
112
-
113
- index.scss 내용:
114
- // foundation
115
- @use 'tokens';
116
- @use 'mixins';
117
- @use 'base';
118
-
119
- // layout
120
- @use 'layout/page';
121
- @use 'layout/hero';
122
- @use 'layout/daily-checkin';
123
- @use 'layout/play-time-mission';
124
- @use 'layout/token-exchange';
125
- @use 'layout/token-raffle';
126
- @use 'layout/caution';
127
-
128
- // components
129
- @use 'components/card';
130
- @use 'components/button';
131
- @use 'components/badge';
132
- @use 'components/progress';
133
- @use 'components/popups';
134
- @use 'components/tooltip';
135
- @use 'components/form';
136
-
137
- layout vs components 구분 기준:
138
- layout/ → 섹션의 위치, 크기, 배치, 간격, 배경
139
- (position, display, flex/grid, padding, margin, background-image)
140
- components/ → UI 요소의 모양, 색상, 타이포, 인터랙션 상태
141
- (color, font, border, border-radius, shadow, hover, focus)
142
-
143
- 각 컴포넌트 스타일 파일 규칙:
144
- - @use '../tokens' as t; 로 토큰 참조
145
- - @use '../mixins' as m; 로 mixin 참조
146
- - 해당 섹션의 클래스만 정의 (다른 섹션 스타일 금지)
147
- - 역할 기반 클래스 네이밍 (Phase 4-4 규칙 적용)
148
- - 배경 이미지는 별도 클래스 (Multi-Layer 패턴)
149
-
150
- _tokens.scss 내용:
151
- $feature-primary: #xxx;
152
- $feature-text: #xxx;
153
- $feature-bp: 1024px;
154
- @function fluid($min, $max) { ... }
155
- // 자체 완결 — 외부 의존 없음
156
-
157
- 이 폴더째 다른 프로젝트에 복사 가능.
158
- ```
26
+ ### Mapping Rules
159
27
 
160
- ### 컴포넌트 스타일 파일 매핑 규칙
28
+ - Figma color 기존 토큰 (ΔE < 5) → 기존 토큰명 사용
29
+ - Figma spacing ≈ 기존 토큰 (±2px) → 기존 토큰명 사용
30
+ - 매칭 없는 값 → `figma-tokens` 보충 토큰으로 추가
161
31
 
162
- ```
163
- 두 종류의 스타일 파일이 필요:
164
-
165
- 1. 섹션 스타일 — 페이지의 각 영역
166
- | 컴포넌트 | --new 모드 | 기본 모드 |
167
- |---------|-----------|---------|
168
- | HeroSection.vue | _hero.scss | 기존 패턴 따름 |
169
- | DailyCheckIn.vue | _daily-checkin.scss | 기존 패턴 따름 |
170
- | CautionSection.vue | _caution.scss | 기존 패턴 따름 |
171
-
172
- 2. 재사용 컴포넌트 스타일 — 여러 섹션에서 공통 사용
173
- | 패턴 | --new 모드 | 용도 |
174
- |------|-----------|------|
175
- | 카드 (보상, 상품, 아이템) | _card.scss | 그리드 아이템, 리스트 아이템 |
176
- | 버튼 (CTA, 출석, 교환) | _button.scss | 액션 트리거 |
177
- | 배지 (상태 표시) | _badge.scss | 완료/진행중/잠금 표시 |
178
- | 프로그레스 | _progress.scss | 게이지, 달성도 |
179
- | 팝업/모달 | _popups.scss | 확인, 상세, 입력 |
180
-
181
- 재사용 컴포넌트 감지 방법:
182
- → 디자인 프레임에서 2회 이상 반복되는 시각 패턴
183
- → 같은 구조 + 다른 데이터 → 하나의 스타일 파일 + variant
184
-
185
- vibe-figma-frame에서 프레임별 추출 시:
186
- → 섹션 스타일 파일에 해당 섹션 스타일 작성
187
- → 반복 패턴 발견 시 재사용 컴포넌트 스타일 파일로 분리
188
- → 토큰에 새 값 추가 (중복 시 기존 토큰 재사용)
189
- ```
32
+ ---
190
33
 
191
- ### 4-2. Token File Format
34
+ ## S-2. 토큰 파일 포맷
192
35
 
193
- **CSS Custom Properties (default):**
36
+ ### CSS Custom Properties (기본)
194
37
 
195
38
  ```css
196
- /* figma-tokens.css — Auto-generated from Figma. Do not edit manually. */
197
- /* Source: https://www.figma.com/design/{fileKey} */
198
-
199
39
  :root {
200
40
  /* Colors */
201
41
  --figma-primary: #3B82F6;
202
- --figma-primary-hover: #2563EB;
203
42
  --figma-surface: #FFFFFF;
204
- --figma-surface-secondary: #F9FAFB;
205
43
  --figma-text-primary: #111827;
206
- --figma-text-secondary: #6B7280;
207
44
  --figma-border: #E5E7EB;
208
45
 
209
46
  /* Typography */
210
47
  --figma-font-family: 'Inter', system-ui, sans-serif;
211
- --figma-text-xs: 0.75rem; /* 12px */
212
- --figma-text-sm: 0.875rem; /* 14px */
213
- --figma-text-base: 1rem; /* 16px */
214
- --figma-text-lg: 1.125rem; /* 18px */
215
- --figma-text-xl: 1.25rem; /* 20px */
216
- --figma-leading-tight: 1.25;
217
- --figma-leading-normal: 1.5;
48
+ --figma-text-sm: 0.875rem;
49
+ --figma-text-base: 1rem;
50
+ --figma-text-xl: 1.25rem;
218
51
 
219
52
  /* Spacing */
220
- --figma-space-1: 0.25rem; /* 4px */
221
- --figma-space-2: 0.5rem; /* 8px */
222
- --figma-space-3: 0.75rem; /* 12px */
223
- --figma-space-4: 1rem; /* 16px */
224
- --figma-space-6: 1.5rem; /* 24px */
225
- --figma-space-8: 2rem; /* 32px */
226
-
227
- /* Shadows */
228
- --figma-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
229
- --figma-shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
53
+ --figma-space-2: 0.5rem;
54
+ --figma-space-4: 1rem;
55
+ --figma-space-8: 2rem;
230
56
 
231
- /* Border Radius */
232
- --figma-radius-sm: 0.25rem; /* 4px */
233
- --figma-radius-md: 0.5rem; /* 8px */
234
- --figma-radius-lg: 0.75rem; /* 12px */
235
- --figma-radius-full: 9999px;
57
+ /* Shadows, Radius */
58
+ --figma-shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
59
+ --figma-radius-md: 0.5rem;
236
60
  }
237
61
  ```
238
62
 
239
- **Tailwind extend (if Tailwind detected):**
240
-
241
- ```js
242
- // figma.config.ts — merge into tailwind.config.ts theme.extend
243
- export const figmaTokens = {
244
- colors: {
245
- figma: {
246
- primary: '#3B82F6',
247
- 'primary-hover': '#2563EB',
248
- // ...
249
- },
250
- },
251
- spacing: { /* ... */ },
252
- borderRadius: { /* ... */ },
253
- };
254
- ```
255
-
256
- **SCSS (if `*.scss` or `sass` detected):**
63
+ ### SCSS (SCSS 감지 )
257
64
 
258
65
  ```scss
259
- // _figma-tokens.scss — Auto-generated from Figma. Do not edit manually.
66
+ // _figma-tokens.scss
67
+ @use 'sass:math';
260
68
 
261
- // ── Variables ──
262
69
  $figma-primary: #3B82F6;
263
- $figma-primary-hover: #2563EB;
264
- $figma-surface: #FFFFFF;
265
70
  $figma-text-primary: #111827;
266
- $figma-text-secondary: #6B7280;
267
- $figma-border: #E5E7EB;
268
-
269
71
  $figma-font-family: 'Inter', system-ui, sans-serif;
270
- $figma-text-xs: 0.75rem;
271
- $figma-text-sm: 0.875rem;
272
72
  $figma-text-base: 1rem;
273
- $figma-text-lg: 1.125rem;
274
- $figma-text-xl: 1.25rem;
275
-
276
- $figma-space-1: 0.25rem;
277
- $figma-space-2: 0.5rem;
278
73
  $figma-space-4: 1rem;
279
- $figma-space-6: 1.5rem;
280
- $figma-space-8: 2rem;
281
-
282
- $figma-radius-sm: 0.25rem;
283
74
  $figma-radius-md: 0.5rem;
284
- $figma-radius-lg: 0.75rem;
285
-
286
- $figma-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
287
- $figma-shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
288
75
 
289
- // ── Breakpoints ──
76
+ // Breakpoints
290
77
  $figma-bp: 1024px;
291
78
  $figma-bp-mobile-min: 360px;
292
79
  $figma-bp-pc-target: 1920px;
293
80
 
294
- // ── Mixins ──
295
- @mixin figma-pc {
296
- @media (min-width: $figma-bp) { @content; }
297
- }
298
-
299
- @mixin figma-mobile-only {
300
- @media (max-width: $figma-bp - 1px) { @content; }
301
- }
81
+ // Mixins
82
+ @mixin figma-pc { @media (min-width: $figma-bp) { @content; } }
83
+ @mixin figma-mobile-only { @media (max-width: $figma-bp - 1px) { @content; } }
302
84
 
303
- // ── Functions ──
85
+ // Fluid function (clamp 자동화)
304
86
  @function figma-fluid($mobile, $desktop, $min-vw: $figma-bp-mobile-min, $max-vw: $figma-bp-pc-target) {
305
- $slope: ($desktop - $mobile) / ($max-vw - $min-vw);
87
+ $slope: math.div($desktop - $mobile, $max-vw - $min-vw);
306
88
  $intercept: $mobile - $slope * $min-vw;
307
89
  @return clamp(#{$mobile}, #{$intercept} + #{$slope * 100}vw, #{$desktop});
308
90
  }
309
-
310
- // Usage: font-size: figma-fluid(1rem, 2rem);
311
91
  ```
312
92
 
313
- **SCSS 사용 시 추가 규칙:**
314
- - CSS custom properties 대신 `$변수` 사용 (프로젝트 컨벤션에 따라 둘 다 가능)
315
- - `@mixin figma-pc` breakpoint 일관성 유지 — `@media` 직접 사용 금지
316
- - `figma-fluid()` 함수로 clamp() 계산 자동화 — 수동 계산 금지
317
- - 파일명: `_figma-tokens.scss` (partial, `_` prefix)
318
- - `@use 'figma-tokens' as figma;` 로 네임스페이스 import
319
-
320
- ### 4-3. Responsive Token Format (responsive mode only)
93
+ **SCSS 사용 시 필수 규칙:**
94
+ - `@use 'figma-tokens' as figma;` 네임스페이스 import
95
+ - `@include figma.figma-pc { }` — `@media` 직접 사용 금지
96
+ - `figma-fluid($mobile, $desktop)` 수동 clamp() 금지
321
97
 
322
- When `responsive.json` exists, tokens that **differ across viewports** use `clamp()` for fluid scaling.
323
- Tokens that are **identical** across viewports remain static.
324
-
325
- **clamp() range uses breakpoints from Phase 3-3:**
98
+ ### Tailwind (Tailwind 감지 )
326
99
 
100
+ ```js
101
+ export const figmaTokens = {
102
+ colors: { figma: { primary: '#3B82F6' } },
103
+ spacing: { /* ... */ },
104
+ borderRadius: { /* ... */ },
105
+ };
327
106
  ```
328
- minVw = mobileMinimum (default: 360px)
329
- maxVw = pcTarget (default: 1920px)
330
- breakpoint = breakpoint (default: 1024px) ← used for @media
331
107
 
332
- Design values must be scaled before clamp:
333
- PC Figma value × (pcTarget / designPc) = target PC value
334
- Mobile Figma value × (mobilePortrait / designMobile) = target mobile value
335
- ```
108
+ ---
336
109
 
337
- **CSS Custom Properties (responsive):**
110
+ ## S-3. 반응형 토큰 (responsive mode)
338
111
 
339
- ```css
340
- /* figma-tokens.css Responsive tokens from Figma */
341
- /* clamp range: {mobileMinimum}px → {pcTarget}px */
342
- /* Breakpoint: {breakpoint}px (PC↔Mobile) */
343
- /* Design scale: PC {designPc}→{pcTarget}, Mobile {designMobile}→{mobilePortrait} */
112
+ 뷰포트 간 값이 다른 토큰은 `clamp()`로 fluid 스케일링.
113
+ 동일한 값은 static 유지. 계산 공식은 **vibe-figma-rules R-3** 참조.
344
114
 
115
+ ```css
345
116
  :root {
346
- /* === Shared (same across all viewports) === */
117
+ /* Shared (뷰포트 동일) */
347
118
  --figma-primary: #3B82F6;
348
- --figma-font-family: 'Inter', system-ui, sans-serif;
349
119
  --figma-radius-md: 0.5rem;
350
- --figma-shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
351
-
352
- /* === Fluid Typography (scales with viewport) === */
353
- /* Figma PC 96px → target 36px, Figma Mobile 48px → target 32px */
354
- --figma-text-h1: clamp(2rem, {intercept}rem + {slope}vw, 2.25rem);
355
- --figma-text-body: clamp(0.875rem, {intercept}rem + {slope}vw, 1rem);
356
120
 
357
- /* === Fluid Spacing (scales with viewport) === */
358
- --figma-space-section: clamp(1rem, {intercept}rem + {slope}vw, 3rem);
359
- --figma-space-content: clamp(0.75rem, {intercept}rem + {slope}vw, 1.5rem);
360
-
361
- /* === Breakpoint (from config, user-customizable) === */
362
- --figma-bp: 1024px;
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);
363
124
  }
364
125
  ```
365
126
 
366
- **clamp() calculation formula:**
367
-
368
- ```
369
- Step 1: Scale Figma values to target viewport
370
- targetMobile = figmaMobileValue × (mobilePortrait / designMobile)
371
- targetPc = figmaPcValue × (pcTarget / designPc)
372
-
373
- Example (defaults): Figma PC h1=96px, Figma Mobile h1=48px
374
- targetPc = 96 × (1920 / 2560) = 72px
375
- targetMobile = 48 × (480 / 720) = 32px
376
-
377
- Step 2: Calculate clamp()
378
- minVw = mobileMinimum (360)
379
- maxVw = pcTarget (1920)
380
- min = targetMobile, max = targetPc
381
-
382
- slope = (max - min) / (maxVw - minVw)
383
- intercept = min - slope * minVw
384
- → clamp({min/16}rem, {intercept/16}rem + {slope*100}vw, {max/16}rem)
385
-
386
- Example:
387
- slope = (72 - 32) / (1920 - 360) = 0.02564
388
- intercept = 32 - 0.02564 × 360 = 22.77
389
- → clamp(2rem, 1.423rem + 2.564vw, 4.5rem)
390
- ```
391
-
392
- **Tailwind (responsive — if Tailwind detected):**
393
-
394
- Use Tailwind's responsive prefixes instead of clamp() for layout, clamp() for typography/spacing:
395
-
396
- ```js
397
- export const figmaTokens = {
398
- fontSize: {
399
- 'figma-h1': ['clamp(1.5rem, 1.076rem + 1.878vw, 3rem)', { lineHeight: '1.2' }],
400
- 'figma-body': ['clamp(0.875rem, 0.828rem + 0.188vw, 1rem)', { lineHeight: '1.5' }],
401
- },
402
- spacing: {
403
- 'figma-section': 'clamp(1rem, 0.248rem + 3.286vw, 3rem)',
404
- },
405
- };
406
- ```
407
-
408
- **SCSS (responsive):**
409
-
410
127
  ```scss
411
- // _figma-tokens.scss — figma-fluid() 함수로 자동 계산
412
- @use 'sass:math';
413
-
414
- $figma-bp: 1024px;
415
- $figma-bp-mobile-min: 360px;
416
- $figma-bp-pc-target: 1920px;
417
-
418
- @function figma-fluid($mobile, $desktop, $min-vw: $figma-bp-mobile-min, $max-vw: $figma-bp-pc-target) {
419
- $slope: math.div($desktop - $mobile, $max-vw - $min-vw);
420
- $intercept: $mobile - $slope * $min-vw;
421
- @return clamp(#{$mobile}, #{$intercept} + #{$slope * 100}vw, #{$desktop});
422
- }
423
-
424
- @mixin figma-pc { @media (min-width: $figma-bp) { @content; } }
425
-
426
- // Token 사용
128
+ // SCSS — figma-fluid() 사용
427
129
  $figma-text-h1: figma-fluid(2rem, 4.5rem);
428
- $figma-text-body: figma-fluid(0.875rem, 1rem);
429
130
  $figma-space-section: figma-fluid(1rem, 3rem);
430
131
  ```
431
132
 
432
- ```scss
433
- // Component.module.scss — 사용 예시
434
- @use 'figma-tokens' as figma;
435
-
436
- .heroSection {
437
- padding: figma.$figma-space-section;
438
- }
133
+ ---
439
134
 
440
- .heroTitle {
441
- font-size: figma.$figma-text-h1;
442
- }
135
+ ## S-4. 스타일 파일 구조
443
136
 
444
- .cardGrid {
445
- display: grid;
446
- grid-template-columns: 1fr;
137
+ ### --new 모드 (자체 완결)
447
138
 
448
- @include figma.figma-pc {
449
- grid-template-columns: repeat(3, 1fr);
450
- }
451
- }
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. 기존 스타일 파일은 수정하지 않음
452
167
  ```
453
168
 
454
- ### 4-4. Class Naming Rules
169
+ ---
455
170
 
456
- 클래스 이름은 **역할(role)**을 드러내야 하며, 구조나 스타일 속성을 이름에 넣지 않는다.
171
+ ## S-5. 클래스 네이밍 규칙
457
172
 
458
- #### 네이밍 원칙
173
+ 클래스 이름은 **역할(role)**을 드러내야 하며, 구조나 스타일 속성을 이름에 넣지 않는다.
459
174
 
460
175
  | 원칙 | 좋은 예 | 나쁜 예 |
461
176
  |------|--------|--------|
462
- | **역할 기반** | `.heroSection`, `.productCard`, `.navPrimary` | `.section1`, `.card`, `.nav` |
463
- | **용도 명시** | `.heroBg`, `.cardThumbnail`, `.avatarImg` | `.bg`, `.img`, `.image1` |
464
- | **상태 포함** | `.buttonPrimary`, `.inputError` | `.blueButton`, `.redBorder` |
465
- | **관계 표현** | `.heroTitle`, `.heroDescription` | `.title`, `.text` |
466
- | **축약 금지** | `.navigationMenu`, `.backgroundImage` | `.navMnu`, `.bgImg` |
177
+ | 역할 기반 | `.heroSection`, `.productCard` | `.section1`, `.card` |
178
+ | 용도 명시 | `.heroBg`, `.cardThumbnail` | `.bg`, `.img` |
179
+ | 관계 표현 | `.heroTitle`, `.heroDescription` | `.title`, `.text` |
180
+ | 축약 금지 | `.navigationMenu` | `.navMnu` |
467
181
 
468
- #### 구체적 규칙
182
+ ### 구체적 규칙
469
183
 
470
184
  ```
471
- 1. 컴포넌트 루트: 섹션/컴포넌트 이름 그대로
472
- .loginForm, .heroSection, .productGrid
473
-
474
- 2. 자식 요소: 부모이름 + 역할
475
- .heroTitle, .heroDescription, .heroCta
476
- .loginFormInput, .loginFormSubmit
477
-
478
- 3. 이미지 클래스: 반드시 용도를 명시
479
- .heroBg ← 히어로 배경 이미지
480
- .heroBgOverlay ← 배경 위 오버레이
481
- .productPhoto ← 상품 사진
482
- .brandLogo ← 브랜드 로고
483
-
484
- 4. 상태 변형: variant/state 접미사
485
- .buttonPrimary, .buttonDisabled
486
- .cardHighlight, .cardCompact
185
+ 1. 컴포넌트 루트: 섹션/컴포넌트 이름 → .loginForm, .heroSection
186
+ 2. 자식 요소: 부모이름 + 역할 → .heroTitle, .heroCta
187
+ 3. 이미지 클래스: 용도 명시 → .heroBg, .productPhoto, .brandLogo
188
+ 4. 상태 변형: variant/state 접미사 → .buttonPrimary, .cardHighlight
487
189
  ```
488
190
 
489
- #### Anti-Patterns
191
+ ### Anti-Patterns
490
192
 
491
193
  ```css
492
- /* WRONG: 의미 없는 이름 */
493
- .wrapper { }
494
- .inner { }
495
- .box { }
496
- .item { }
497
- .text1 { }
498
-
499
- /* CORRECT: 역할이 드러나는 이름 */
500
- .eventSection { }
501
- .eventContent { }
502
- .rewardCard { }
503
- .rewardItem { }
504
- .eventDescription { }
505
- ```
506
-
507
- **Component style file MUST reference global tokens:**
508
-
509
- ```css
510
- /* LoginForm.module.css */
511
- .loginForm {
512
- padding: var(--figma-space-6);
513
- background: var(--figma-surface);
514
- border-radius: var(--figma-radius-lg);
515
- box-shadow: var(--figma-shadow-md);
516
- }
517
-
518
- .loginFormTitle {
519
- font-size: var(--figma-text-xl);
520
- font-weight: 600;
521
- color: var(--figma-text-primary);
522
- line-height: var(--figma-leading-tight);
523
- }
524
-
525
- .loginFormSubmit {
526
- background: var(--figma-primary);
527
- color: var(--figma-surface);
528
- border-radius: var(--figma-radius-md);
529
- padding: var(--figma-space-2) var(--figma-space-4);
530
- transition: background 150ms ease;
531
- }
194
+ /* WRONG */
195
+ .wrapper { } .inner { } .box { } .item { } .text1 { }
532
196
 
533
- .loginFormSubmit:hover {
534
- background: var(--figma-primary-hover);
535
- }
197
+ /* CORRECT */
198
+ .eventSection { } .eventContent { } .rewardCard { } .eventDescription { }
536
199
  ```
537
200
 
538
201
  ---
539
202
 
540
- ## Phase 7: Token Mapping (default mode)
541
-
542
- **Only in default (project integration) mode.** Map extracted Figma tokens to the project's existing token system.
543
-
544
- ### Token Source Priority
545
-
546
- ```
547
- 1. MASTER.md (.claude/vibe/design-system/{project}/MASTER.md) ← 최우선
548
- 2. design-context.json (.claude/vibe/design-context.json) ← 보조
549
- 3. Project theme files (tailwind.config, CSS variables, etc.) ← 폴백
550
- 4. Generate new figma-tokens ← 마지막 수단
551
- ```
552
-
553
- ### Mapping Rules
554
-
555
- 1. **MASTER.md exists** → authoritative token source
556
- - Figma color ≈ MASTER.md color (ΔE < 5) → use MASTER.md token name
557
- - Figma spacing ≈ MASTER.md spacing (±2px) → use MASTER.md token name
558
- - Figma font ≈ MASTER.md font → use MASTER.md token name
559
- - Unmatched Figma values → add to `figma-tokens.css` as supplementary tokens
560
-
561
- 2. **No MASTER.md, but design-context.json exists** →
562
- - Use `detectedStack` info for naming convention
563
- - Use `aesthetic.colorMood` to validate token naming (e.g., warm palette → warm- prefix)
564
- - Generate `figma-tokens.css` grouped by category
565
-
566
- 3. **No design system at all** →
567
- - Generate `figma-tokens.css` (or Tailwind extend)
568
- - Group tokens by category (color, typography, spacing, shadow)
569
-
570
- ### Output Mapping Comment
203
+ ## S-6. 토큰 매핑 코멘트 (기본 모드)
571
204
 
572
- Always output token mapping as a comment block at the top of the token file:
205
+ 토큰 파일 상단에 매핑 결과를 코멘트로 출력:
573
206
 
574
207
  ```
575
208
  /* Figma Token Mapping:
576
- * Figma "Primary/Default" → var(--figma-primary) = #3B82F6
209
+ * Figma "Primary" → var(--figma-primary) = #3B82F6
577
210
  * ✅ Matched: var(--color-blue-500) from MASTER.md
578
- * Figma "Text/Body" → var(--figma-text-base) = 1rem / 1.5
579
- * Matched: var(--text-base) from MASTER.md
580
- * Figma "Accent/Glow" → var(--figma-accent-glow) = #7C3AED
581
- * ⚠️ New token: no existing match
211
+ * Figma "Accent" → var(--figma-accent) = #7C3AED
212
+ * New token: no existing match
582
213
  */
583
214
  ```