작성규칙 · 디자인원칙

@boospatch/ui를 다룰 때 따라야 하는 두 출처. CLAUDE.md는 코드 차원의 컨벤션, DESIGN.md는 브랜드·시각 원칙.

CLAUDE.md

packages/design-system/CLAUDE.md

@boospatch/ui 작성규칙

CLAUDE.md — @boospatch/ui

부스패치 디자인시스템의 단일 출처. 토큰·primitive·Pretendard 폰트를 묶어 메인 레포(boospatch-frontend)와 카탈로그 앱(apps/lab/src/app/)이 동일 패키지로 소비.

전체 운영 룰: 루트 /CLAUDE.md. 자세한 컨벤션: .claude/skills/boospatch-component-conventions/SKILL.md.


패키지 구조 — Primitives · Charts · Maps

packages/design-system/
├── package.json        ─ name="@boospatch/ui", peer react>=19, recharts (optional)
├── src/
│   ├── index.ts        ─ primitives entry (Button·Txt·Badge 등). 컴포넌트·utility만 export, 토큰 X
│   ├── charts/         ─ 차트 카테고리 (`@boospatch/ui/charts`)
│   │   ├── ChartContainer.tsx      (foundation, generic)
│   │   ├── ChartTooltip.tsx         (foundation, generic)
│   │   ├── RadarChart.tsx           (generic — recharts 의존하지만 도메인 무관)
│   │   ├── shared/                  (axis ticks · gradient · scatter · utils)
│   │   ├── domain/                  (부동산 데이터 모양과 결합)
│   │   │   ├── ListingPriceBandsChart.tsx
│   │   │   ├── RealTradesChart.tsx
│   │   │   ├── GapPriceChart.tsx
│   │   │   └── SaleQuantityChart.tsx
│   │   └── index.ts                 (foundation + generic + domain 일괄 re-export)
│   ├── maps/           ─ 맵 카테고리 (`@boospatch/ui/maps`)
│   │   ├── useNaverMapScript.ts    (foundation)
│   │   ├── MapCanvas.tsx           (foundation)
│   │   ├── MapTooltip.tsx          (foundation)
│   │   ├── useTooltipHoverBridge.ts (foundation)
│   │   ├── naver-maps.d.ts         (ambient SDK types)
│   │   ├── domain/                 (부동산 마커)
│   │   │   ├── PillMarker.tsx
│   │   │   ├── DotMarker.tsx
│   │   │   └── ClusterBubble.tsx
│   │   └── index.ts
│   ├── tokens.css      ─ 토큰 진입 (3계층 re-import: shared → web → app)
│   ├── tokens/
│   │   ├── shared.css      ─ palette · semantic alias · font · 의미 typescale · 픽셀 alias · radius · animation 전체
│   │   ├── web.css         ─ 용도 typescale (데스크탑) · spacing 0.5/1.5/2.5 (밀도형) · z-index · ring · gradient · scrollbar utility
│   │   └── app.css         ─ typescale 모바일 톤다운 · spacing collapse · ring transparent · *신규* elevation/safe-area/touch-target ([data-platform="app"] 컨텍스트)
│   ├── fonts.css       ─ Pretendard @font-face (Variable)
│   ├── fonts/          ─ PretendardVariable.woff2 자산
│   ├── components/     ─ <Name>.tsx primitive
│   └── utils/
│       └── cn.ts       ─ clsx + tailwind-merge
└── CLAUDE.md

카테고리 구분 원칙:

  • primitives (src/components/, root entry): 순수 UI — 외부 도메인·라이브러리 의존 없음. Button/Tag/Input 등 어디서든 동작.
  • charts (src/charts/, /charts subpath): 시각화 카테고리. 직접 자식은 generic (RadarChart, foundations). domain/ 서브폴더는 부동산 데이터 모양과 강결합.
  • maps (src/maps/, /maps subpath): Naver Maps SDK 위의 인프라. 직접 자식은 generic (MapCanvas 등). domain/ 서브폴더는 부동산 단지 시각화 마커.

단일 entry 컨벤션: charts / maps 한 entry에서 generic + domain 모두 export. 구분은 폴더 트리 + 카탈로그 배지가 책임. 외부 호환 layer 없음.

소비측 import:

import "@boospatch/ui/tokens.css";
import "@boospatch/ui/fonts.css";

// primitives
import { Button, Txt, Badge } from "@boospatch/ui";

// charts (generic + domain 한 entry)
import { RadarChart, ChartContainer, ListingPriceBandsChart } from "@boospatch/ui/charts";

// maps (foundation + 도메인 마커)
import { MapCanvas, useNaverMapScript, PillMarker } from "@boospatch/ui/maps";

// recharts는 차트 사용 시 consumer가 별도 install (optional peer dep).

토큰 의미 계층 (palette → semantic → component)

토큰 의미는 3계층. 상위 계층은 하위만 참조, 역참조 금지.

계층위치역할
palettetokens/shared.css 상단원시 색상 (--color-primary-400, --color-gray-50 등). hex/oklch 직접 정의
semantictokens/shared.css 중단의미 alias (--color-success: var(--color-primary-400), --color-surface: var(--color-gray-50) 등). palette만 참조
componentcomponents/*.tsx 안에서semantic만 참조 (bg-surface, text-fg-muted). palette 직접 참조 지양 (예외: brand identity가 강한 곳 bg-primary-400)

규칙: 컴포넌트가 hex나 oklch 값을 직접 입력하면 PR 차단. 반드시 Tailwind utility class 또는 var(--color-*) 통해.

토큰 플랫폼 분리 (shared / web / app)

플랫폼별 값은 3파일 분할. 컴포넌트가 어떤 토큰을 쓰는지는 그대로 (e.g. text-display), 셀렉터 컨텍스트에서 변수 값만 cascade로 갈아끼움.

파일적용 컨텍스트내용
shared.css모든 컨텍스트palette · semantic alias · font · 의미 typescale · radius · animation. 양쪽이 동일
web.css@theme default용도 typescale 데스크탑값(36/32/24/20) · spacing 추가(2/6/10) · z-index · ring · gradient
app.css[data-platform="app"] 셀렉터typescale 모바일(32/28/22/18) · spacing collapse(4/8/12) · ring transparent · 신규 elevation/safe-area/touch-target

전환은 지역 wrapper로: 카탈로그 <PlatformScope platform="app"> (apps/lab/src/app/_components/PlatformScope.tsx)이 <div data-platform="app">을 부착해 자식 트리만 cascade 발동. 전역(<html>)에 박지 않는 이유: PC 웹 카탈로그 메인 영역(매트릭스/표)이 모바일 토큰으로 바뀌면 어색해짐. 모바일 토큰은 지역적 검수 도구.

자세한 매핑은 tokens/{shared,web,app}.css 헤더 주석. 시각 비교는 카탈로그 /tokens Platform 탭.


컴포넌트 작성 룰 (요약)

자세한 명세는 .claude/skills/boospatch-component-conventions/SKILL.md. 여기서는 위반 시 PR 차단되는 핵심 룰만:

  1. tailwind-variants(tv) 사용. class-variance-authority(CVA) 신규 작성 금지 (기존 코드 점진 전환)
  2. forwardRef 금지. React 19 ref-as-prop — ref?: Ref<HTMLElement> 직접 받기
  3. 'use client' 최소화. 이벤트 핸들러·Radix hook·브라우저 API 사용 컴포넌트만. 정적(Badge/Txt/Icon/SvgIcon)은 server component
  4. boolean prop ≤2개. 그 이상은 union enum (shape: 'rect' | 'pill') 또는 compound (Menu.Trigger / Menu.Content)
  5. 토큰만 통한 스타일링. hex/oklch 직접 입력 금지. bg-[#06b281] 같은 arbitrary value도 PR 리뷰에서 토큰화 요청
  6. Txt variant 우선. 신규 텍스트는 <Txt variant="display|hero|h1|h2|body-l|body|body-bold|caption|tag"> 디자이너 프리셋. size+weight 자유 조합은 예외만 (DESIGN.md §3.2)
  7. a11y 의무:
    • interactive 컴포넌트는 focus-visible ring (outline-ring)
    • touch target ≥44×44px (size 'm' 이상)
    • 키보드 인터랙션 (Space/Enter/Backspace 등) 명세
    • 장식 아이콘은 aria-hidden="true", 의미 아이콘은 aria-label 필수

신규 컴포넌트 PR 체크리스트

PR 머지 전 모두 통과해야 함:

  • tv variants 정의, default variants 명시
  • React 19 ref-as-prop, forwardRef 미사용
  • 'use client'를 의식적으로 박았는가? (정적이면 제거)
  • boolean prop 2개 이하
  • semantic 토큰만 사용 (또는 brand identity 명분으로 palette 직접)
  • focus-visible ring 시각 확인
  • 키보드 인터랙션 매뉴얼 테스트 (Tab/Space/Enter/Backspace)
  • apps/lab/src/app/components/<Name>/page.tsx 카탈로그 추가
  • variant 매트릭스 시각 검증 (모든 size × color × state 조합)
  • index.ts에 export 추가
  • 카탈로그에 a11y 체크리스트 표 명시
  • AI slop 자가검증 — 보라 그라디언트·Inter/Roboto·균등 SaaS 그리드 X

의존성 정책

카테고리라이브러리비고
varianttailwind-variantsCVA 대체. slot/extend 지원
class mergingclsx, tailwind-mergeutils/cn.ts로 래핑
아이콘lucide-reacttree-shake 위해 named import 강제
Radix (G3 도입 예정)@radix-ui/react-{dialog,popover,tooltip,toast,slot}peer로
polymorphic자체 구현외부 라이브러리(@radix-ui/react-slot)는 G3 시점 검토

peerDependencies: react ≥19, react-dom ≥19. 기타 외부 의존성은 최소화. 무거운 라이브러리(Framer Motion 등) 도입 전 PR에서 토론 의무.


참조 skill

이 패키지에서 작업할 때 호출 순서 (루트 CLAUDE.md와 동일):

  1. boospatch-component-conventions — 부스패치 오버라이드 (필수)
  2. frontend-design — AI slop 회피
  3. ui-ux-pro-max — 색상·타이포 결정 재료
  4. vercel-composition-patterns — boolean → compound
  5. vercel-react-best-practices — server-first, React 19
  6. web-design-guidelines — a11y/UX 최종 검증