CDS 프론트엔드 (설계 / 구현 / 리팩터링)
소스 오브 트루스는 upstream 레포지토리 https://github.com/Caho1/open-claude-ui (MIT)입니다: AGENTS.md (토큰, 프리셋, 컴포넌트), code-examples/ 그리고 docs/v2/ (Claude Desktop 2.0, v2.37337.1). 아래 경로는 해당 레포지토리를 기준으로 합니다. 레포지토리를 프로젝트 옆에 클론하거나 열어서 사용하거나 GitHub에서 읽으세요. 이 스킬은 워크플로우이며, 값을 중복 정의하지 않습니다. 작업이 v2 동작(밀도, 사이드바, effort, 컴포지터 모션, 오프라인 큐)과 관련된 경우 references/v2-delta.md를 읽으세요.
0. 먼저 베이스라인을 선택하세요
- CDS 1.x (
code-examples/의 기본값): 따뜻한 클레이 악센트, 20px 컴포저, 8px 반경, Framer Motion 스프링. - CDS 2.0 (docs/v2): 차가운
#FCFCFB캔버스, 12/14px 컴포저, 6/8px 반경, 24/32px 컨트롤, CSS-컴포지터 모션. 어느 것을 사용할지 묻거나 추론하세요. 하나의 표면 내에서 혼용하지 마십시오. 많은 v2 토큰(--cds-h-control,data-density)은 docs에 문서화되어 있지만code-examples/cds-theme.css에는 아직 정의되지 않았습니다. 사용하기 전에 정의하세요.
1. 워크플로우
- 분류: 작업을 분류하세요: 새 컴포넌트 / 스타일 변경 / 리팩터링 / 감사.
- 작성 전 재사용:
code-examples/(30개 모듈, AGENTS.md §3에 인덱스 있음)와src/index.ts를 확인하세요. 합성하거나 확장하세요. 처음부터 다시 만들지 마십시오. - 토큰: 모든 색상, 반경, 지속 시간 및 easing은
--cds-*변수 또는 Tailwind 별칭에서 가져옵니다. 원시 hex나 임시ms는 사용하지 않습니다. - 모션: 아래 표에 따라 선택하세요.
- 에지 가드 (3절): 입력, 스크롤 또는 iframe 코드에 적용하세요.
- 검증 (4절): 실패를 그대로 보고하세요.
2. 결정 규칙
모션 선택
| 상황 | 사용 |
|---|---|
| 호버/프레스/페이드/스켈레톤/진입, 스트리밍 중 실행되는 모든 것 | 순수 CSS + --cds-dur-* + --cds-ease-* (컴포지터 전용: transform, opacity, filter) |
| 드래그 해제, 속도나 레이아웃에 의존하는 너비/높이 | SPRING_BOUNCY / SNAPPY / GENTLE / HEAVY_SNAP 중 하나를 사용한 Framer Motion |
| 축소 모션 | 스냅, 상태 변경을 절대 제거하지 않음. prefers-reduced-motion을 존중함 |
절대 transition: all, 절대 linear, 절대 하드코딩된 스프링 숫자를 사용하지 마십시오. var(--cds-dur-*)를 사용하는 transition 약칭은 토큰이 정의되지 않은 경우 자동으로 죽으므로, 다섯 가지 모두(60ms/120/200/300/450)를 정의하세요. |
표면 및 테두리: surface-0..3 + 헤어라인 border-subtle (v2에서 0.5px)로 레이어링하세요. 테두리가 있는 컨테이너 내부의 컨트롤은 border-none을 받습니다. 그림자는 표면에서 고정 알파 블랙 대신 color-mix()로 파생하세요. 순수한 #000/#fff를 절대 사용하지 마십시오 (코드 블록 #0d0d0c는 예외).
밀도: 컨트롤 크기는 --cds-h-control / --cds-radius / --cds-icon에서 가져오며, 고정 px를 사용하지 않으므로 Compact와 Comfortable이 모두 작동합니다. 44px 히트 영역 미만으로 떨어지는 Compact 행은 음수 마진 터치 증가(--cmp-chin-touch-grow)를 사용하세요.
숫자: 모든 타이머, 카운터, 토큰 게이지, 줄 번호는 tabular-nums를 사용하세요.
정보 설계 (v2 입장): 채팅 장난감이 아닌 워크스테이션입니다. 널찍한 카드보다는 조밀한 상태 행(28px, 브랜치, PR, 실행 하트비트)을 선호하세요. 비용/위험을 명시적으로 표시하세요(최대 경고, 사용 게이지가 있는 effort 계층). 사용자 입력을 소중히 다루세요.
3. 비협상 가드
- IME: Enter로 전송하기 전에
if (e.nativeEvent.isComposing || e.keyCode === 229) return;. - 스트리밍 스크롤:
Date.now() - lastUserScroll < 150이면 자동 핀고정하지 마세요. 하단에서 40px 이내일 때만 핀고정. - 모델 생성 HTML용 iframe:
allow-same-origin없이 샌드박스, origin-확인된 postMessage,navigator.userActivation으로 게이트. - Zero-loss 입력: 실패/오프라인 전송은 유지(IndexedDB 큐)되며 리로드 시 복원.
- 환경 불변성: 컨텍스트 윈도우 / 워크트리 / MCP 설정은 세션이 생성되면 고정됩니다. 세션 중간에 편집하는 UI를 만들지 마십시오.
- 바이너리 에셋 금지 (
.ttf/.otf/.mp3/.wav): 시스템 폰트 스택과 Web Audio 합성만 사용. - 라이트(
:root)와 다크(.dark) 모두 확인해야 합니다. 차가운 보라/네온 그라디언트는 사용하지 마십시오 (1.x). - 키보드: 목록/그리드는 로빙 포커스(
useClaudeRovingFocus)를 사용합니다. 다이얼로그는 포커스를 트랩합니다.
4. 리팩터링 / 감사 체크리스트
대상에서 다음을 grep하세요: hex 리터럴, rounded-[…px], transition-all, ease-linear, duration-[…], 프리셋 외부의 stiffness:, IME 가드가 없는 Enter onKeyDown, 스트리밍 코드의 scrollTo/scrollTop =, allow-same-origin, 테두리가 있는 부모 내에 중첩된 1px 테두리. 각각을 토큰/프리셋/가드로 교체하세요. 동작은 유지하고 표현만 변경하세요(요청이 없는 한).
그런 다음 실행, 모두 종료 코드 0이어야 함:
npm run typecheck && npm run check:tokens && npm run build
AGENTS.md에 --cds-* 참조를 추가한 경우, check:tokens가 cds-theme.css에 해당 참조가 존재할 것을 요구합니다.
5. 출력 계약
어떤 베이스라인(1.x/2.0)을 사용했는지, 어떤 기존 모듈을 재사용했는지, 어떤 토큰/프리셋을 선택했는지와 그 이유, 검증 결과를 명시하세요. 검증되지 않은 항목(예: 시각적 다크 모드 확인)은 검증되지 않음으로 표시하세요.