Figma btn-page(404:5121)의 네 변형을 옮긴다. 자식은 버튼 그룹이고 여럿이면
양끝, 하나면 가운데다.
자식 수를 React에서 세지 않고 CSS `:has(> :only-child)`로 판단한다. 프래그먼트나
조건부 렌더로 자식이 갈려도 실제 DOM이 기준이라 어긋나지 않고, React를 안 쓰는
소비자도 표시할 클래스가 없다.
패널이 자식에게 강제하는 두 가지(사용자 승인):
- 패널 안 그룹 간격은 gap-3(8px). 단독으로 쓰는 그룹의 gap-2(4px)는 그대로다.
- 모바일에서는 패널도 그룹도 세로로 쌓이고 버튼이 폭을 채운다.
시안이 패널 안 버튼에만 주는 min-width 160px은 변수 바인딩이 없고 토큰 스케일에도
160이 없어 리터럴로 둔다(사용자 승인). 상단 80px 여백은 spacing-top-2xlg이며
offset={false}로 끌 수 있다.
Co-Authored-By: Claude Opus 5
Figma btn-group(398:4854)에서 가져온 건 간격뿐이다 — 크기·방향과 무관하게
gap-2(4px) 하나여서 그룹에 크기별 스타일이 없다. 배치 규칙(방향·정렬·줄바꿈)은
지시받은 사양이다.
크기는 그룹이 단일 진실 공급원이다. 자식을 cloneElement로 덮어써서 자식이
저마다 다른 size를 줘도 그룹 값으로 통일된다. 세로일 때는 fullWidth까지 함께
내려주고 CSS도 stretch라, React를 안 쓰는 소비자도 같은 결과를 얻는다.
Children.map이 프래그먼트 안으로 들어가지 않아 직접 내려간다. 그러지 않으면
<>…로 감싼 버튼이 덮어쓰기를 피해 가고 Fragment에 size가 붙어 경고가 난다.
호스트 요소(div·span)는 DOM에 없는 속성이 넘어가지 않도록 건드리지 않는다.
Co-Authored-By: Claude Opus 5
Figma 시안(관리자페이지 node 390:439)을 토큰만으로 옮겼다. 컴파일된 CSS의 토큰 참조
50개, 원시 hex/px/rem 리터럴 0개다.
시안에서 확인한 것(추측하지 않음): gap은 lg·md·sm이 gap-2이고 xsm만 gap-1이다.
primary에는 테두리가 없고 secondary·default만 border-1을 갖는다. disabled는 계열과
무관하게 테두리가 사라진다(시안에서 disabled-border 미사용). 높이만 고정이고 좌우
padding만 지정돼 너비는 가변이다.
토큰이 아닌 코드 세 가지를 사용자 승인 후 넣었다.
- line-height: 1 / letter-spacing: -0.025em — 시안 텍스트 스타일 label/*-strong의 값이나
Figma에서 변수로 export되지 않아 토큰이 없다. 네 크기가 같은 값이라 규칙 하나로 끝난다.
- box-sizing: border-box — 높이 고정 + secondary·default의 1px 테두리 때문에 필수다.
없으면 계열별 바깥 높이가 2px 어긋난다.
- cursor·white-space·flex-shrink — 구조·상호작용 규칙. 버튼 스코프에만 적용한다.
모양 규칙은 @fox/styles/_fox-button.scss가 소유하고 module이 @use로 끌어올린다 —
클래스명이 모듈 스코프로 감싸져 전역 충돌이 없고, index.scss는 이 파티셜을 포함하지
않아 CSS가 중복 출력되지 않는다.
아이콘은 계열별 색을 토큰으로 입히기 위해 ReactNode로 받는다(currentColor 전제).
크기는 슬롯이 form-icon-* 토큰으로 정한다.
error 계열은 시안 미정이라 클래스를 비워 뒀다.
Co-Authored-By: Claude Opus 5