디자인팀 요구다. 클래스명 하나로 쓰고 이름은 Figma의 `ico/House`를 대소문자까지
그대로 담는다. 굵기별 @font-face가 따로라 화면이 쓰는 굵기만 내려받는다.
기존 SVG 컴포넌트에서 뽑은 path로 구워 그림이 같다는 것이 데이터 수준에서 보장된다
(글리프 대조 결과 불일치 0.97%, 전부 외곽선 안티에일리어싱).
duotone은 글리프 하나가 두 색을 못 가져 배경겹을 별도 글리프로 넣고 CSS가 겹친다.
Co-Authored-By: Claude Opus 5
시안의 `ico/*`는 Phosphor Icons를 그대로 올린 것이다. `ico/House` Regular와 Phosphor
`house.svg`는 문 너비 16.67%·문 span 25%·벽 두께 8.33%가 전부 같고, 프레임 구조도
`Format=Stroke|Outline × Weight=Thin|Light|Regular|Bold|Fill|Duotone`으로 Phosphor의
weight 체계 그대로다. 그래서 Figma를 1,512번 호출하는 대신 원본에서 생성했다.
- @fox/tools/build-icons.py 신설. build-tokens.py와 같은 자리·같은 철학(Figma가 SSOT이고
생성물은 재현 가능)이다. 실행 1.4초.
- core/icons/glyphs/*.tsx 1,512개 + fox-icon.tsx(공용 껍데기) + index.ts 배럴.
기존 icons.tsx(8종 수기 이식)는 이 안에 포함되므로 삭제했다.
- 굵기를 이름이 아니라 `weight` prop으로 바꿨다. 시안의 `Weight=` 변형과 1:1이다.
FoxCaretLeftBoldIcon → .
- viewBox를 Phosphor 원본의 256으로 통일했다. 기존 8종은 Figma export라 16/24 박스에
translate가 붙어 있었지만 같은 그림을 축소한 것이다(House bbox x=32 → 32/256×16=2로
기존 translate와 일치).
검증 — 기존 8종과 새 생성물을 256×256으로 래스터화해 픽셀 비교했다. 차이가 잉크의 0.33%
이하(안티에일리어싱 경계)였고 Pause는 0픽셀이었다. weight 매핑이 유일한지도 오답을 넣어
확인했다: Play를 regular로 두면 58.4%, bold면 60.7%, Plus를 regular로 두면 34.0% 어긋난다.
즉 시안의 Play·Pause는 fill, Plus는 bold다 — 이름에 표시가 없어 놓치기 쉬운 지점이라
fox-carousel-button 주석과 README에 명시했다.
번들 — 배럴이 크지만 프로덕션에는 쓰는 글리프만 들어간다(안 쓰는 아이콘의 path 문자열이
프로덕션 .js 어디에도 없음을 확인). build 6초, tsc 3초로 영향 없다.
라이선스 — Phosphor는 MIT다. 사본에 고지를 함께 두도록 요구하므로 생성기가 원본 LICENSE를
core/icons/PHOSPHOR-LICENSE.txt로 옮긴다.
Co-Authored-By: Claude Opus 5
값의 출처가 컴파일된 CSS로 옮겨간 뒤 매니페스트가 제공하던 것은 Figma 변수 경로와
"원본에선 참조였으나 컬렉션이 없어 값으로 굳은 것"(chart-alt 18개) 표시 둘뿐이었다.
둘 다 쓰지 않기로 해 생성물·화면·변환기에서 모두 걷어낸다.
변환기는 이제 SCSS만 생성한다. 화면은 스타일시트 외에 아무것도 참조하지 않는다.
Co-Authored-By: Claude Opus 5
Figma 변수 페이지와 1:1로 대조하기 위한 감사 화면으로 바꾼다. 분류를 우리 CSS 그룹이
아니라 원본 컬렉션/모드로 두고 — Mode(Light/Dark) · Responsive(PC/Mobile) · Size ·
Theme · Primitive — 파일에 값이 적혀 있으면 그 값을, 다른 토큰을 가리키면 참조 토큰을
표시한다. 토큰 이름 아래에 Figma 변수 경로를 함께 적는다.
CSSOM 읽기로는 이 요구를 만족할 수 없어 걷어냈다. CSS는 alias를 var()로 흡수하고
light/dark를 light-dark() 한 줄로 합치므로 "원본이 값을 적었는지 토큰을 가리켰는지"를
되살릴 수 없다. 대신 변환기가 원본 구조 그대로를 담은 매니페스트를 함께 생성한다 —
여전히 자동 생성이라 목록을 손으로 관리하지 않는다.
미리보기도 CSS 변수가 아니라 매니페스트의 해석값을 쓴다. 변수를 쓰면 PC 섹션을 좁은
창에서 볼 때 모바일 값이, Light 섹션을 다크 테마에서 볼 때 다크 색이 그려진다.
⚠️ 매니페스트를 만들며 잡은 것: 이 export에는 `theme`이라는 이름의 컬렉션이 둘이고
(제공된 파랑 계열, 미제공 청록 계열) 변수 경로까지 같아, 이름만으로 매칭하면 chart-alt
18개가 엉뚱하게 해결된 것처럼 보인다. 값 대조를 넣어 "미제공 컬렉션"으로 표시한다.
SCSS 생성 쪽은 원래부터 값 대조를 하고 있어 영향이 없었다.
Co-Authored-By: Claude Opus 5
토큰 531개를 손으로 옮기면 오타가 섞이고 Figma 재수출 때마다 반복해야 한다.
변환 규칙(1rem = 10px, 알파 색상의 rgb() 표기, alias의 var() 보존)을 코드로
고정해 재수출 시 재실행만으로 갱신되게 한다.
Co-Authored-By: Claude Opus 5