Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
ad19585
refactor: Bottom Nav 활성 탭을 화면 state 대신 라우트에서 파생
xeoxxn Sep 9, 2026
6647381
refactor: ScreenLayout을 라우터 레벨로 이동, useScreenHeader 훅 도입
xeoxxn Sep 9, 2026
8730156
feat: 재사용 가능한 ScreenHeader 컴포넌트 분리
xeoxxn Sep 9, 2026
5655e51
refactor: 대여/반납 토글을 헤더에서 화면 요소로 분리, 필터 고정+목록만 스크롤
xeoxxn Sep 9, 2026
983e481
docs: 용어 사전 컨벤션 추가
xeoxxn Sep 9, 2026
bf4693b
refactor: rental → bililge 네이밍 통일
xeoxxn Sep 9, 2026
f5c3691
chore: main에서 컴포넌트 관련 스킬·컨벤션 문서 가져오기
xeoxxn Sep 9, 2026
0047473
feat: 대여 신청 바텀시트 추가(휠 피커로 대여 시작 시간 선택)
xeoxxn Sep 9, 2026
94b12de
fix: 휠 피커·스테퍼 숫자 폭 고정해서 자릿수 바뀌어도 안 밀리게 수정
xeoxxn Sep 9, 2026
b50014c
fix: 휠 피커 선택 줄 뒤 회색 글자가 비쳐서 두꺼워 보이던 문제 수정
xeoxxn Sep 9, 2026
cf90bc0
fix: figma-check 결과 반영 — 시트 상단 여백, 안내 문구 굵기 Figma에 맞춤
xeoxxn Sep 9, 2026
2e6144e
fix: 바텀시트 하단 세이프에어리어에 누락된 홈 인디케이터 바 추가
xeoxxn Sep 9, 2026
da0758b
revert: 홈 인디케이터 바 제거, 세이프에어리어 여백만 유지
xeoxxn Sep 9, 2026
e7887bf
fix: 바텀시트 하단 여백을 34px로 과다 계산했던 것 14px로 수정
xeoxxn Sep 9, 2026
fc643d4
fix: Bottom Nav 하단 검은색 홈 인디케이터 바 제거, 여백만 유지
xeoxxn Sep 9, 2026
d6d9f2b
fix: 바텀시트 슬라이드 애니메이션을 iOS 스타일 감속 곡선으로 자연스럽게 조정
xeoxxn Sep 9, 2026
4142283
perf: 바텀시트 첫 오픈 때 휠 피커 마운트가 슬라이드 첫 프레임을 막던 문제 수정
xeoxxn Sep 10, 2026
acae08d
refactor: 텍스트 스타일을 WDS Typography 컴포넌트로 전환, 타이포그래피 컨벤션 추가
xeoxxn Sep 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions .claude/skills/component/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
name: component
description: Figma Stream 파일의 노드를 코드 컴포넌트로 옮긴다. WDS(원티드 디자인 시스템) 컴포넌트로 확인되면 @wanteddev/wds를 import해서 재사용하고, Stream 고유 UI만 새로 만든다. /component <figma URL 또는 node-id>로 호출한다.
---

# /component — Figma → 코드 컴포넌트 변환 워크플로우

Stream Figma 파일의 노드를 받아서, WDS로 확인된 부분은 `@wanteddev/wds`를 import해 재사용하고 Stream 고유 UI만 새로 컴포넌트로 만드는 방식으로 코드를 생성한다. 모든 컴포넌트가 같은 구조를 따르게 하는 게 목적이다.

> **발동 조건**: `/component`로 호출했을 때. 뒤에 Figma URL(node-id 포함) 또는 node-id가 없으면 임의로 노드를 고르지 말고 사용자에게 요청한다.
> **`figma:figma-design-to-code` 스킬과의 관계**: 이 스킬을 대체하지 않는다. 그 스킬의 "기존 컴포넌트·토큰 재사용" 단계를 WDS 우선 규칙으로 구체화한 래퍼다. `get_design_context`를 호출하기 전 `figma-design-to-code` 스킬(또는 `skill://figma/figma-design-to-code/SKILL.md`)도 함께 로드한다.

## 상수

```
Stream fileKey: 3QkxTuGLZkB17pZILTog9L
WDS libraryKey: lk-01f447137a741b37c25896e9a4e109dcb719fa4e54177be9a39d24b8da507c109279c2d1d0533b9943595d7d6a5ea398977f43b5d84e163797965d810ba79b69
```

Figma URL이 주어지면 거기서 fileKey/nodeId를 추출한다. node-id만 주어지고 fileKey가 없으면 위 Stream fileKey를 기본값으로 쓴다(이 스킬은 Stream 파일 전용).

## Step 1 — 대상 노드 확인

`get_metadata(fileKey, nodeId)` 또는 `get_screenshot`으로 무엇을 컴포넌트화할지 확인한다. 노드가 화면 전체처럼 너무 크면, 실제로 컴포넌트화할 하위 노드를 좁혀달라고 사용자에게 요청한다 — 임의로 쪼개지 않는다.

## Step 2 — WDS 대조

1. `docs/conventions/wds-component-usage.md`를 먼저 읽는다. 이미 확정된 매핑이 있으면 재조사 없이 바로 쓴다 — **단, 대상 노드의 실제 스크린샷/스타일이 문서에 기록된 것과 눈에 띄게 다르면(색상·활성 상태 표현 등) 같은 이름이라도 재확인한다.** 파일 전체에서 한 번 확정된 컴포넌트라도 다른 화면에서는 Stream이 로컬로 새로 만든 동명의 요소일 수 있다(사례: `docs/conventions/wds-component-usage.md`의 "빌릴게 필터 Chip은 WDS Chip/Chip이 아니었다" 참고).
2. 대상 노드 안의 인스턴스 중 문서에 없는 이름이 있으면:
1. `search_design_system`을 WDS libraryKey로 스코프 제한해서 정확한 이름으로 검색한다.
2. 결과가 애매하면(이름만 비슷하거나 여러 개 매칭) `get_design_context`로 실제 인스턴스 노드를 열어, 응답의 "Component descriptions" 섹션에 나오는 메인 컴포넌트 Node ID·공식 문서 링크(`montage.wanted.co.kr`)로 확정한다.
3. 새로 확정된 매핑은 `docs/conventions/wds-component-usage.md`의 표에 바로 추가한다 — 이 스킬을 쓸수록 문서가 쌓여서 다음 실행이 더 빨라진다.
3. 매칭도 안 되고 이름도 비슷한 게 없으면 Stream 고유 UI로 취급한다(Step 3-3).

## Step 3 — 코드 생성

1. `get_design_context(fileKey, nodeId)`로 레퍼런스 코드를 받는다.
2. Step 2에서 WDS로 확정된 서브트리는 raw JSX 대신 실제 WDS export로 치환한다.
- export 이름은 반드시 `node_modules/@wanteddev/wds/dist/components/`에서 실존 여부를 확인한 후 쓴다 — 이름을 추측하지 않는다.
- 아이콘은 `@wanteddev/wds-icon`에서 가져온다.
- WDS 컴포넌트 내부를 오버라이드하지 않는다. 레이아웃 조정은 감싸는 wrapper에서 한다.
3. WDS로 확정되지 않은 나머지(Stream 고유 UI)는 `docs/conventions/component-convention.md`를 따라 새 컴포넌트로 작성한다 (파일 구조, variant→Props 유니온 타입 매핑, Figma 노드 추적 주석 등).
4. 이미지·아이콘 asset은 `download_assets`로 받아 `src/assets/`에 커밋한다 — Figma asset URL은 7일 후 만료되므로 그대로 참조하지 않는다.

## Step 4 — 배치 & 검증

1. `docs/conventions/coding-style.md`·`component-convention.md`의 파일 위치 규칙(feature 전용 vs `components/ui/` 공용)에 따라 저장 위치를 정한다. 재사용 범위가 애매하면 사용자에게 확인한다.
2. `pnpm check`(Biome)로 lint/format을 통과시킨다.
3. `component-convention.md`의 "완료 기준 체크리스트"로 스스로 검증한다.

## Step 5 — 결과 안내

- 생성·수정한 파일 경로
- WDS로 대체한 컴포넌트 목록 / 새로 만든 Stream 고유 컴포넌트 목록
- `wds-component-usage.md`에 새로 추가한 매핑이 있으면 그 사실을 짚어준다
76 changes: 76 additions & 0 deletions .claude/skills/figma-check/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
name: figma-check
description: 이미 구현된 코드가 Figma 디자인과 1:1로 일치하는지 교차검증한다. 색상 토큰, WDS 컴포넌트 사용 판단, 레이아웃/패딩, 실제 렌더링 스크린샷까지 대조해서 불일치를 번호 매겨 리포트한다. /figma-check <figma URL 또는 node-id> [코드 파일 경로]로 호출한다.
---

# /figma-check — Figma ↔ 구현 교차검증 워크플로우

`/component`로 만든 코드가 시간이 지나거나 다른 세션에서 수정되면서 Figma 원본과 어긋나지 않았는지 확인한다. **이 스킬은 검증만 한다 — 발견한 불일치를 자동으로 고치지 않는다.** 수정은 사용자가 결과를 보고 별도로 요청할 때 진행한다.

> **발동 조건**: `/figma-check`로 호출했을 때. 뒤에 Figma URL(node-id 포함) 또는 node-id가 없으면 임의로 노드를 고르지 말고 사용자에게 요청한다.
> **`/component`와의 관계**: `/component`가 "Figma → 코드"를 만드는 스킬이라면, 이 스킬은 그 결과물이 여전히 Figma와 맞는지 "코드 ↔ Figma"를 되짚어 확인하는 스킬이다. 둘 다 같은 컨벤션 문서(`docs/conventions/component-convention.md`, `wds-component-usage.md`)를 기준으로 삼는다.

## 상수

```
Stream fileKey: 3QkxTuGLZkB17pZILTog9L
WDS libraryKey: lk-01f447137a741b37c25896e9a4e109dcb719fa4e54177be9a39d24b8da507c109279c2d1d0533b9943595d7d6a5ea398977f43b5d84e163797965d810ba79b69
```

Figma URL이 주어지면 거기서 fileKey/nodeId를 추출한다. node-id만 주어지고 fileKey가 없으면 위 Stream fileKey를 기본값으로 쓴다.

## Step 1 — 대상 코드 파일 확정

- 사용자가 코드 경로를 같이 줬으면 그걸 쓴다.
- 안 줬으면 `component-convention.md`가 요구하는 `// Figma: ... (nodeId <id>)` 파일 최상단 주석을 근거로 찾는다:

```bash
grep -rln "nodeId <해당 id>\|nodeId \`<해당 id>\`" src/ --include="*.tsx"
```

- 매칭이 여러 개거나 하나도 없으면 임의로 고르지 말고 사용자에게 확인한다. 검증 대상이 화면 전체(여러 컴포넌트로 조립됨)면, `get_metadata`로 하위 노드 구조를 먼저 파악해 관련 컴포넌트 파일들을 전부 나열한다.

## Step 2 — Figma 레퍼런스 수집

대상 노드에 대해 아래 세 가지를 받는다 (`figma:figma-design-to-code` 스킬도 함께 로드).

1. `get_design_context(fileKey, nodeId)` — 레퍼런스 JSX/스타일과 "Component descriptions" 섹션(WDS 메인 컴포넌트 Node ID·문서 링크 확정용)
2. `get_screenshot(fileKey, nodeId)` — 비교용 스크린샷. 로컬에 저장해둔다
3. `get_variable_defs(fileKey, nodeId)` — 이 노드에서 실제 쓰이는 Figma 변수명과 값(색상·타이포)

## Step 3 — 실제 렌더링 캡처

1. dev 서버가 안 떠 있으면 `pnpm dev`로 띄운다(포트 충돌 시 기존 프로세스 정리 후 재시작).
2. `run` 스킬(또는 `chromium-cli`, 없으면 `npx playwright`)로 대상 화면/컴포넌트를 렌더링해서 스크린샷을 찍는다. 특정 variant(예: 선택 상태, 스테퍼 모드)를 봐야 하면 클릭 등으로 상태를 재현한 뒤 캡처한다.
3. 확인이 끝나면 띄운 dev 서버는 정리한다(사용자가 계속 쓰라고 하지 않는 한).

## Step 4 — 교차검증 체크리스트

아래 다섯 가지를 순서대로 확인한다. 항목마다 통과/불일치를 기록해둔다.

1. **비주얼 비교**: Step 2의 Figma 스크린샷과 Step 3의 실제 렌더링을 나란히 놓고 본다. 레이아웃, 정렬, 간격, 색감, 잘림 여부를 확인한다.
2. **색상 토큰**: 대상 코드에 `text-[#...]`, `bg-[#...]`, `border-[#...]` 같은 하드코딩 hex가 남아있으면 전부 지적한다. `docs/conventions/component-convention.md`의 "색상 토큰" 규칙대로 `src/index.css`의 `@theme` 토큰을 써야 한다. 이미 토큰이 있는데 못 찾고 hex를 새로 박은 경우도 있을 수 있으니, hex 값을 Step 2의 `get_variable_defs` 결과와 대조해서 맞는 토큰이 있는지 확인한다. 이름이 비슷해도 값이 다른 토큰들(예: `Line/Normal/Neutral` 반투명 vs `Line/Solid/Neutral` 불투명)을 혼동하지 않았는지 특히 주의한다.
3. **WDS 판단 재검증**: 코드가 `@wanteddev/wds`/`@wanteddev/wds-icon`을 import하는 자리마다 `docs/conventions/wds-component-usage.md`에 그 판단 근거가 있는지 확인한다. 없으면 Step 2의 Component descriptions로 확정하고 문서에 추가한다. 반대 방향도 확인한다 — Stream 로컬로 새로 만든 부분이 사실 WDS 컴포넌트인 경우, 또는 이름은 같지만 실제로는 다른 스타일(활성 상태 표현 등)이라 Stream 로컬이 맞는 경우.
4. **박스모델 실측**: 브라우저에서 대표 요소 하나를 골라 `getComputedStyle`로 padding/border-width/margin이 의도한 값과 맞는지 찍어본다. 특히 `0px`으로 죽어있으면 CSS 우선순위 문제(예: 레이어 밖 전역 reset이 Tailwind 유틸리티를 이기는 문제 — `docs/plans/rental-list-screen.md` 참고)를 의심한다.
5. **컴포넌트 기본값 재확인**: WDS 컴포넌트를 쓸 때 명시하지 않은 prop의 기본값이 Figma 디자인과 다른 걸 렌더링하고 있지 않은지 확인한다(예: `TopNavigation`의 기본 `variant="normal"`이 타이틀을 가운데 정렬시켜서 Figma의 좌측 정렬과 어긋났던 사례, `background` 기본값이 iOS 반투명 스타일이라 배경색이 미묘하게 달라 보였던 사례). 의심되면 해당 컴포넌트의 `node_modules/@wanteddev/wds/dist/components/<name>/style.js`를 직접 열어 실제 동작을 확인한다.

## Step 5 — 결과 안내

`pr-check` 스킬과 같은 형식으로, 발견한 불일치를 중요도 순으로 번호 매겨 나열한다.

```
## Figma 교차검증 결과 — {대상} (nodeId {id})

1. 🔴 [파일:라인] 무엇이 다른지
- Figma: {기대값}
- 코드: {실제값}
- 수정 방안: {한두 문장}

2. 🟡 [파일:라인] ...
```

- 🔴 High: 화면에 실제로 다르게 보이는 것(레이아웃 깨짐, 색 틀림, WDS 컴포넌트 오판으로 동작이 다름)
- 🟡 Medium: 지금 당장 안 보이지만 잠재적으로 문제(하드코딩 hex가 토큰과 값은 같지만 토큰을 안 써서 나중에 디자인 바뀌면 안 따라가는 경우 등)
- 🟢 Low: 사소한 스타일 차이, 주석/문서 누락
- 전부 통과했으면 "N개 항목 모두 Figma와 일치" 로 짧게 알린다.
- 새로 확정된 WDS 매핑이나 색상 토큰이 있으면 `docs/conventions/wds-component-usage.md` / `component-convention.md`에 반영했는지 짚어준다.
1 change: 1 addition & 0 deletions docs/conventions/coding-style.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
- 훅: `useXxx`. 일반 함수/변수: camelCase. 상수: `UPPER_SNAKE_CASE`.
- 불리언: `is` / `has` / `should` 접두사.
- 폴더: 도메인명 소문자 또는 kebab-case.
- **도메인 이름은 임의로 번역/축약하지 않는다.** `features/<기능>/` 폴더명, 라우트 경로, 도메인 접두사가 붙는 컴포넌트/타입명은 `docs/conventions/terminology.md`(용어 사전)의 코드 용어를 그대로 쓴다 — 백엔드 API 엔드포인트 네이밍과 맞추기 위함이다. 사전에 없는 새 도메인이면 먼저 그 문서에 추가한 뒤 코드에 반영한다.

## 폴더 구조

Expand Down
88 changes: 88 additions & 0 deletions docs/conventions/component-convention.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Component Convention

> Figma 디자인을 코드 컴포넌트로 옮길 때 따르는 구조 규칙.
> `docs/conventions/coding-style.md`(네이밍·폴더·TS 규칙)를 보완하는 문서이며, `/component` 스킬이 만드는 모든 컴포넌트는 이 규칙을 따른다.

## 0. 원칙

Figma에 있는 요소라고 전부 새로 코드를 짜지 않는다.

- **WDS(원티드 디자인 시스템) 컴포넌트로 확인된 건 반드시 `@wanteddev/wds`/`@wanteddev/wds-icon`을 import해서 쓴다.** 직접 마크업을 새로 짜지 않는다. 판별 기준은 `docs/conventions/wds-component-usage.md`.
- **Stream 고유 UI만 새 컴포넌트로 만든다** — WDS에 없는, Stream 서비스에서만 쓰는 화면 조각(카드, 리스트 아이템 등).

## 1. 파일 위치

`coding-style.md`의 기능 기반(feature-based) 구조를 따른다.

- 지금 다루는 화면/기능 전용이면 `features/<기능>/components/<ComponentName>.tsx`
- 이미 다른 화면에서도 쓰이는 게 Figma 상에서 확인되면 `components/ui/<ComponentName>.tsx`
- **애매하면 먼저 `features/` 아래에 둔다.** 두 번째 화면에서 실제로 재사용될 때 `components/ui/`로 옮긴다 — 성급하게 공용 폴더부터 만들지 않는다(coding-style.md의 "빈 폴더 미리 만들지 않는다"와 같은 이유).

## 2. 파일 구조

- **컴포넌트 하나 = 파일 하나** (`ComponentName.tsx`). 폴더로 쪼개지 않는다 — 실제로 서브컴포넌트가 분리될 필요가 생기면 그때 판단한다.
- Figma의 variant(예: `trailingControl: Button | Stepper`)는 **Props의 유니온 타입 하나로 매핑**한다. variant 조합마다 별도 컴포넌트를 만들지 않는다.
- Props는 `interface`로 선언한다(coding-style.md TypeScript 규칙).

```tsx
interface RentalItemCardProps {
itemName: string
quantity: number
trailingControl?: 'button' | 'stepper'
}
```

## 3. WDS 컴포넌트 사용

- 매칭된 서브트리는 `get_design_context`가 준 raw JSX 대신 **실제 WDS export로 치환**한다.
- export 이름은 반드시 `node_modules/@wanteddev/wds/dist/components/`에서 확인 후 쓴다 — 이름을 추측하지 않는다.
- 예: Figma `Button/Button` → `import { Button } from '@wanteddev/wds'`
- 예: Figma `Chip/Chip` → `import { Chip } from '@wanteddev/wds'`
- 아이콘은 `@wanteddev/wds-icon`에서 가져온다.
- **WDS 컴포넌트 내부를 임의로 오버라이드하지 않는다.** 간격·배치 같은 레이아웃 조정은 감싸는 wrapper에서 한다.

## 4. Stream 고유 UI (신규 컴포넌트)

- `get_design_context`의 raw JSX/Tailwind는 **레퍼런스일 뿐, 그대로 커밋하지 않는다.** 프로젝트 Tailwind 클래스로 다시 짜되, 색상은 아래 "색상 토큰" 규칙을 따른다.

### 색상 토큰

- 색은 `text-[#171719]`처럼 hex를 직접 박지 않는다. `src/index.css`의 `@theme` 블록에 있는 시맨틱 토큰(`text-label-normal`, `bg-background-alternative`, `border-line-solid-neutral`, `text-primary`, `bg-primary-subtle` 등)을 쓴다. 이 토큰들은 `@wanteddev/wds/global.css`가 심어둔 `--semantic-*`/`--atomic-*` CSS 변수를 그대로 별칭 연결한 것이라 다크 테마 전환도 자동으로 따라간다.
- 필요한 색이 아직 토큰으로 없으면, hex를 추측해서 쓰지 말고 `get_variable_defs(fileKey, nodeId)`로 해당 노드의 실제 Figma 변수명·값을 확인한 뒤 `index.css`의 `@theme`에 새 토큰을 추가한다. `Line/Normal/Neutral`(반투명 `#70737c29`)과 `Line/Solid/Neutral`(불투명 `#eaebec`)처럼 이름이 비슷해도 값이 다른 토큰이 있으니 이름만 보고 넘겨짚지 않는다.
- 컴포넌트 인스턴스가 없는 화면 배경/외곽선처럼 Figma 값이 실제로는 안 보이는 경우(예: Bottom Nav 상단 border가 바로 위 배경과 같은 색이라 안 보였던 사례)도 있다 — 이럴 땐 왜 다른 토큰으로 바꿨는지 주석으로 남긴다.
### 타이포그래피

- 글자 크기·굵기를 `text-xs`/`text-[17px]`/`font-semibold`처럼 Tailwind로 직접 짓지 않는다. `@wanteddev/wds`의 `Typography` 컴포넌트를 쓴다 — Figma의 이름 있는 타입 스타일(Headline 2/Bold 등)과 `variant`+`weight` 조합이 1:1로 대응한다(`node_modules/@wanteddev/wds/dist/components/typography/style.js`에서 실측 확인 가능).
- Tailwind에는 11px(Caption 2) 같은 값이 기본 스케일에 없어서, 대충 가까운 `text-xs`(12px)를 썼다가 실제로 다른 크기가 되는 사고가 실제로 있었다(Bottom Nav 탭 라벨). `Typography`를 쓰면 이 스케일 자체가 WDS 값이라 이런 어긋남이 구조적으로 없어진다.
- 색은 `className`의 Tailwind 색상 토큰이 아니라 `Typography`의 `color` prop(예: `color="semantic.label.normal"`)으로 준다. `Typography`가 `color` 미지정 시 `color: inherit`을 자체 CSS-in-JS로 주입하는데, 이 스타일이 Tailwind 유틸리티 레이어보다 우선순위가 높아서(`@wanteddev/wds/global.css`를 `layer(base)`로 감싸야 했던 것과 같은 이유) `className="text-label-normal"`을 같이 줘도 씹힐 수 있다.
- `variant`/`weight` → Figma 이름 대응표(자주 쓰는 것만):

| `variant` | `weight` | 실제 크기 | Figma 이름 |
|---|---|---|---|
| `headline1` | `bold` | 18px / SemiBold | Headline 1/Bold |
| `headline2` | `bold` | 17px / SemiBold | Headline 2/Bold |
| `headline2` | `medium` | 17px / Medium | Headline 2/Medium |
| `label1` | `bold` | 14px / SemiBold | Label 1/Normal - Bold |
| `caption1` | `bold` | 12px / SemiBold | Caption 1/Bold |
| `caption1` | `medium` | 12px / Medium | Caption 1/Medium |
| `caption1` | `regular` | 12px / Regular | Caption 1/Regular |
| `caption2` | `medium` | 11px / Medium | Caption 2/Medium |

- **예외**: 서드파티 라이브러리가 `className` 문자열만 받아서 자기 DOM에 그대로 꽂는 자리(예: `@ncdai/react-wheel-picker`의 `classNames` prop)는 `Typography`로 감쌀 수 없다 — 이럴 땐 Tailwind `text-[17px]` 같은 값을 그대로 쓰되, 어느 Figma 타입 스타일을 옮긴 값인지 주석을 남긴다(`BililgeRentalSheet.tsx`의 `WHEEL_CLASS_NAMES` 참고).

- Stream 자체 이미지·아이콘(일러스트, 물품 아이콘 등)은 `download_assets`로 받아 `src/assets/`에 커밋한다. Figma asset URL은 **7일 후 만료**되므로 절대 코드에 그대로 참조하지 않는다.
- `data-node-id` 같은 Figma 추적용 속성은 컴포넌트 마크업에 남기지 않는다. 대신 파일 최상단에 원본 Figma 노드를 알 수 있는 주석 한 줄만 남긴다 — 나중에 디자인이 바뀌었을 때 다시 대조할 수 있도록:

```tsx
// Figma: Rental Item Card (nodeId 1041:61407)
```

## 5. 완료 기준 체크리스트

- [ ] WDS로 확인된 요소는 전부 import로 대체했다 (raw JSX 없음)
- [ ] 텍스트는 `Typography`(`variant`+`weight`)로 썼다 — 서드파티가 className만 받는 자리가 아닌 이상 `text-xs`/`text-[Npx]` 직접 사용 없음
- [ ] Stream 고유 요소만 새 컴포넌트로 작성했다
- [ ] Props가 Figma variant를 유니온 타입으로 반영한다
- [ ] 이미지/아이콘 asset을 다운로드해 커밋했다 (만료되는 Figma URL 미참조)
- [ ] 파일 위치가 재사용 범위(feature 전용 vs 공용)에 맞는다
- [ ] `pnpm check`(Biome) 통과
Loading