# 컴포넌트 작성 규약 아직 컴포넌트가 없습니다. 디자인 확정에 따라 하나씩 추가합니다. ## 파일 배치 컴포넌트 하나당 폴더 하나. 스타일을 같은 폴더에 두어야 폴더째 복사·삭제가 가능합니다. ``` components/ button/ button.tsx 컴포넌트 button.module.scss 스타일 (반드시 .module.scss — 전역 오염 방지) index.ts export { Button } from "./button"; index.ts 배럴 — export * from "./button"; ``` ## 작성 규칙 **1. 스타일은 `abstracts`만 `@use` 한다.** ```scss @use "@fox/styles/abstracts" as fox; .button { padding: fox.space(2) fox.space(4); border-radius: fox.radius(md); background: fox.color(primary); color: fox.color(on-primary); @include fox.typo(label-lg); @include fox.focus-ring; @include fox.transition((background-color, color)); } ``` `@fox/styles`(진입점)를 `@use` 하면 안 됩니다 — 그쪽은 CSS를 출력하므로 컴포넌트마다 토큰 선언 전체가 복제됩니다. `abstracts`는 출력이 0입니다. **2. 원시 디자인 값을 쓰지 않는다.** `color: #4f46e5`, `padding: 13px`, `border-radius: 12px` 금지. 전부 `fox.*()` 함수로 토큰을 지목합니다. 없는 토큰 이름을 쓰면 빌드가 실패하므로 오타는 배포까지 갈 수 없습니다. **맞는 토큰이 없다고 해서 원시 값을 쓰지 말고, 토큰을 먼저 추가**합니다 (`@fox/styles/tokens/`). 예외는 의미가 고정되어 토큰화가 무의미한 값뿐입니다 — `0`, `100%`, `1px`(구분선), `auto`, `inherit`. **3. 기본은 Server Component로 둔다.** `'use client'`는 상호작용(상태·이벤트 핸들러·브라우저 API)이 실제로 필요한 컴포넌트에만 붙입니다. CSS Module은 빌드타임에 클래스명 문자열로 바뀔 뿐이라 런타임 JS가 없으므로, 스타일링만 하는 컴포넌트는 서버에 남을 수 있습니다. 여기에 불필요하게 `'use client'`를 붙이면 이 컴포넌트를 쓰는 화면 전체가 클라이언트로 내려갑니다. **4. variant는 클래스 맵으로 고정한다.** ```tsx import styles from "./button.module.scss"; import { cx } from "@fox/core/utils"; type ButtonVariant = "primary" | "secondary" | "ghost"; const VARIANT: Record = { primary: styles.primary, secondary: styles.secondary, ghost: styles.ghost, }; export function Button({ variant = "primary", className, ...props }: ButtonProps) { return