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
디자인 레이어가 React + CSS Modules 전용이던 문제를 푼다. 기존 클래스명은
`.button`·`.label`·`.icon`처럼 일반명사여서, CSS Modules 스코프 밖으로 나가면 소비
프로젝트의 동명 클래스와 전부 충돌했다. SCSS만 쓰는 프로젝트(Vue·Svelte·서버 템플릿)는
버튼을 다시 만들 수밖에 없었다.
`fox-` 접두사 + BEM(fox-button__label · fox-button--primary)으로 바꿔 이름을 전역
유일하게 만들고 CSS Modules를 걷어냈다. 충돌 방지는 도구가 아니라 접두사 규율이 담당한다.
React 컴포넌트는 이 클래스를 조립하는 얇은 래퍼가 되고, 래퍼 없이도 같은 디자인을 얻는다.
진입점을 둘 다 제공한다 — `@fox/styles/components`(전부)와 개별 파티셜
`@fox/styles/fox-button`(안 쓰는 CSS를 번들에서 뺀다). 둘을 같이 써도 Sass가 모듈을
한 번만 로드해 중복되지 않는다.
마크업 계약을 스타일 파일 상단 주석과 @fox/README.md에 적었다 — React 밖 소비자는
그것만 보고 DOM을 짤 수 있어야 한다.
앱 화면 스타일은 `.module.scss` 그대로다(앱 전용이라 스코프가 이득). 규약 문서도 그
구분이 드러나게 고쳤다.
Co-Authored-By: Claude Opus 5