--- name: react-headless-dev description: SEED React Headless component development specialist. Use when developing unstyled, logic-only components in packages/react-headless folder. Focuses on data-driven primitives, custom hooks, and state management without styling concerns. allowed-tools: Read, Write, Edit, MultiEdit, Bash, Glob, Grep --- # React Headless Component Developer Develop unstyled React components following SEED headless architecture patterns. ## Purpose 이 스킬은 SEED Design System의 React Headless 컴포넌트를 개발합니다. Headless 컴포넌트는 스타일 없이 순수한 데이터 로직과 상태 관리만 제공하며, `@seed-design/react` 패키지에서 스타일을 입힐 수 있는 기반을 제공합니다. ## When to Use 다음 상황에서 이 스킬을 사용하세요: 1. **새 Headless 컴포넌트 생성**: `packages/react-headless/` 폴더에 새로운 컴포넌트 추가 2. **Headless 로직 리팩토링**: 기존 컴포넌트의 비즈니스 로직 개선 또는 분리 3. **Custom Hook 구현**: 컴포넌트의 상태 관리와 이벤트 핸들링 로직 작성 4. **Primitive 조합**: React 기본 요소들을 조합한 컴포지션 패턴 구현 5. **Data Attributes 정의**: 컴포넌트 상태를 표현하는 data attributes 설계 **트리거 키워드**: "headless component", "unstyled component", "custom hook", "primitive composition", "packages/react-headless" ## Architecture Principles ### 1. Style-Free Logic **원칙**: 스타일 관련 로직 없이 순수 컴포넌트 데이터 로직만 제공 ```typescript // ❌ Bad: 스타일 관련 로직 포함 const Button = () => { const className = size === 'large' ? 'btn-lg' : 'btn-sm' return ) } ) ``` **가이드라인**: - 파일명: `{Component}.tsx` (예: `Checkbox.tsx`, `Radio.tsx`) - 단순히 커스텀 훅에서 반환된 props를 spread - DOM 요소 조합 및 children 배치만 담당 - 복잡한 로직은 hook에 위임 ### 4. State-Driven Data Attributes **원칙**: Data attributes는 컴포넌트의 상태를 나타내는 데이터 위주로 작성 ```typescript // ✅ Good: 상태를 나타내는 data attributes ) } ) {Component}.displayName = '{Component}' ``` **Component 작성 가이드**: 1. **Props Spreading**: - Hook props와 DOM props 분리 - Hook에서 반환된 props를 spread 2. **Ref Forwarding**: - `forwardRef` 사용하여 ref 전달 - 적절한 DOM 요소에 ref 연결 3. **Children Composition**: - children의 위치와 렌더링 방식 고려 4. **DisplayName**: - 디버깅을 위해 displayName 설정 ### Step 5: Multi-Part Components (선택) Parts가 여러 개인 경우: **Step 5-1**: 각 Part별 파일 생성 ```typescript // DialogTrigger.tsx export const DialogTrigger = forwardRef( (props, ref) => { const { triggerProps } = useDialogContext() return