Files
HMDesign/docs/sw/sw-header-layer-dropdown-verification-2026-10-16.md
T

11 KiB
Raw Blame History

SW Header 레이어 Dropdown 검증 기록 (2026-10-16)

범위: @hm-design/sw 레이어 필드 Dropdown과 전구·눈꽃·자물쇠 On/Off. 기준: Figma rj6wpsfk24lOWvWiVRAANP 5개 Node. 규격은 디자인 명세 §5.2, 사용법은 사용 가이드를 따릅니다.

1. 작업 환경

항목 값
Worktree / Branch D:\디자인시스템\HMDesign-SW / feature/sw-package
HEAD 9407c85 (시작·종료 동일, Commit 없음)
시작 상태 M package.json, M package-lock.json, ?? docs/sw/, ?? packages/sw/, ?? src/sw/ — 기존 미커밋·Untracked 파일 보존(시작 시 스크래치 백업, Reset/Clean/Checkout 없음)
검증 Storybook npx storybook dev -p 6047(6024·6031·6032는 다른 세션 사용 중)

2. Figma 5개 Node

# Node 내용 확인 방법
① 26:10940 header/menu/레이어 (default 26:10941, hover 26:10952, Variant3 26:10963) 필드·펼침 목록·레이어 상세 get_design_context + screenshot
② 26:10810 icon_전구 4 Variant: 컬러 / 컬러 Hover(검정 25%) / 회색(ellipse #E6E6E6→#555) / 회색 Hover get_design_context + screenshot
③ 26:10855 icon_눈꽃 4 Variant SVG(#00CCFF / #949494, Hover = 검정 25% 타일 추가) 동일
④ 26:10912 icon_자물쇠 4 Variant SVG(#E4BF4D·#D8A300 / #BEBEBE·#A1A1A1, Hover = 타일 추가) 동일
⑤ 26:10687 header/dropdown/brown/row (Default 26:10688, Hover 26:10695) 행 234 × 30, Hover #62533D / #FF5C00 동일

Prototype의 Smart Animate(Off → Off Hover, ease-out 300ms)는 사용자 요청서 기재값을 따랐습니다. Figma Prototype player 재생으로는 확인하지 않았습니다(NOT VERIFIED).

3. 자산

  • 신규 8개(layer-ellipse-off, layer-freeze-hover/off/off-hover, layer-lock-hover/off/off-hover, layer-detail)를 Figma MCP에서 내려받아 packages/sw/src/assets/에 저장. 수정·재작성 없음.
  • 기존 layer-union/ellipse/state-a/state-b는 Figma 원본과 mask id 외 동일 → 재사용.
  • Hover SVG = Default SVG + <rect 20×20 rx2 fill=black 25%> 1줄 외 동일(정규화 diff).
  • packages/sw/src, src/sw, packages/sw/dist, storybook-static에서 figma.com/api 검색 0건.

4. 디자인 측정 (Storybook SW / Header / Layer Dropdown, 1920 프레임, getBoundingClientRect·computed style)

항목 기대(Figma) 측정 판정
필드 234 × 38, x 467 234 × 38, x 466.7(헤더 기준) MATCH
펼친 필드 테두리 #081813, radius 3 3 0 0, 라벨·값 #FFC600 rgb(8,24,19), 3px 3px 0 0, rgb(255,198,0) MATCH
펼침 외곽선 236 × 320 at −1/−1, radius 4 ::before inset −39 / −1 / −1 / −1, radius 4, 노란 gradient MATCH
목록 234 × 280, 필드 바로 아래 234 × 280, y = 필드 하단 MATCH
배경·그림자·radius #27241D, 0 4px 8px rgba(16,48,38,.25), 0 0 3 3 동일 MATCH
행 234 × 30 × 8 234 × 30, 8개 MATCH
아이콘 20 × 20, x+12 / 32 / 52 동일 MATCH
견본 16 × 16 at x+80, 안쪽 14 × 14 동일 MATCH
이름 x+104(+1), #F6F4F2, 700 동일 MATCH
하단 40, 버튼 오른쪽 12px 40, 버튼 오른쪽 끝 = 목록 −12 MATCH
레이어 상세 radius 24, 배경 rgba(197,177,158,.15), 아이콘 14, 글자 opacity .35 동일, 버튼 107.3 × 24(글자 69.3) MATCH(글자 폭은 글꼴 차이)
행 Hover #62533D / #FF5C00 rgb(98,83,61) / rgb(255,92,0)(고정·실제 Hover 모두) MATCH
아이콘 Hover 전구 검정 25% 배경, 눈꽃·자물쇠 Hover SVG 전구 rgba(0,0,0,.25), Hover img opacity 1 MATCH
Off Hover 전환 300ms ease-out Off: 0.3s ease-out, On: 0s MATCH
헤더 높이 49 49 MATCH

3배 확대 아이콘 표(12개 Variant)를 Figma screenshot과 육안 비교: 형태·색 일치. 픽셀 diff는 수행하지 않았습니다.

5. 동작 검증

JS 이벤트(click, PointerEvent, KeyboardEvent)와 실제 마우스·키보드 입력(브라우저 pane left_click, hover, key)으로 확인했습니다.

시나리오 결과
필드 클릭 → 열림, 다시 클릭 → 닫힘 PASS (aria-expanded 동기화, onLayerMenuOpenChange true/false)
전구 / 눈꽃 / 자물쇠 클릭(JS 4회, 실제 마우스 1회, 키보드 Space·Enter 2회) PASS — 각 Callback 1회, onLayerSelect 0회, 목록 유지, 해당 레이어만 변경(상태표 확인)
행 선택(JS, 실제 Enter) PASS — onLayerSelect 1회, 목록 닫힘, Focus 필드 복귀, 필드에 레이어명·상태 아이콘 반영(회색 전구 확인)
바깥 pointerdown, 다른 필드 pointerdown PASS — 닫힘
Escape(JS, 실제 키) PASS — 닫힘, Focus 필드
↓(닫힘) PASS — 열림, 현재 레이어 이름 버튼 Focus(2px #F0F7F5 outline)
↓↑ / ←→ PASS — 같은 열 유지 행 이동, 행 안 이동
Tab 진입 / Shift+Tab 두 번으로 이탈 PASS — 목록 안에서는 유지, 밖으로 나가면 닫힘
레이어 상세(Callback 있음) PASS — onLayerDetail 1회 후 닫힘
레이어 상세(Callback 없음) PASS — disabled, opacity 1(Figma 외형), cursor default
Callback 없는 아이콘 PASS — role="img" span 24개, 버튼 0개
disabled 레이어 PASS — 아이콘 3개·선택 버튼 모두 disabled
20개 레이어 PASS — 목록 240px 내부 스크롤(scrollHeight 600), 전체 280, 헤더 가로 스크롤 0
레이어 없음 PASS — 하단만(40px), 필드는 layer.name
긴 레이어명 PASS — 행·필드 ellipsis, 오른쪽 padding 12 유지
콘솔 오류 0건

6. 반응형

Layer Dropdown의 Callback 예제 프레임 폭을 바꿔 측정하고, 같은 폭의 기존 Responsive Story(layers 없음) 필드 위치와 비교했습니다.

폭 필드 x / 폭 (기존과 동일) 열린 뒤 필드 이동 헤더 가로 스크롤 목록 헤더 안 목록 이동 아이콘·텍스트 겹침 견본
1920 466.7 / 234 ✔ 없음 0 ✔ 0 없음 16 × 16
1800 346.7 / 234 ✔ 없음 0 ✔ 0 없음 16 × 16
1799 466.7 / 234 ✔ 없음 0 ✔ 0 없음 16 × 16
1440 466.7 / 234 ✔ 없음 0 ✔ 0 없음 16 × 16
1180 306.7 / 234 ✔ 없음 0 ✔ 0 없음 16 × 16
1080 207.7 / 234 ✔ 없음 0 ✔ 0 없음 16 × 16
900 246.7 / 234 ✔ 없음 0 ✔ 0 없음 16 × 16
768 310.7 / 234 ✔ 없음 0 ✔ 0 없음 16 × 16
640 182.7 / 234 ✔ 없음 0 ✔ 0 없음 16 × 16
390 167.7 / 113.7 ✔ 없음 0 ✔ 왼쪽 이동, 오른쪽 여백 1.3 없음 16 × 16
  • 1차 측정에서 390px 열림 상태에 헤더 scrollWidth가 1px 늘어나는 문제(외곽선이 목록 밖 1px)를 발견해, 이동 계산에 1px 여백을 두도록 수정 후 320 / 360 / 390 / 500 / 519 / 640에서 0을 재확인했습니다.
  • 390에서 실제 조작(열기 + 자물쇠 Toggle → Callback 1회, 목록 유지) 확인. 브라우저 Viewport 390 에뮬레이션은 Storybook 페이지 내부 폭이 766px로 잡혀 헤더 프레임 390 기준으로만 확인했습니다(실기기 NOT VERIFIED).
  • 더보기 메뉴 정책·기존 Breakpoint 변경 없음(필드 위치가 기존 Story와 동일).

7. 회귀 확인

항목 결과
layers 미전달 필드 기존 DOM(아이콘 4개 img 14×18 / 14×14 / 20×20 / 20×20, aria-expanded=false)과 동일
Composed Controls 고정 Hover 5개 필드 값 #FFC600, Gradient ring opacity 1, 선 미리보기 #FFC600 유지
문서 Dropdown·창 이동·인쇄·최소화·종료·속성 토글 CSS 변경 없음(diff는 레이어 관련 규칙 추가뿐)

8. Build

명령 결과
npm run typecheck -w @hm-design/sw PASS
npm run build:sw PASS (dist/styles.css 45.35 kB, dist/index.js 202.28 kB)
npm run typecheck(root, packages build 포함) PASS
npm run build(root) PASS (기존 500 kB chunk 경고만)
npm run build-storybook PASS, index에 sw-header--layer-dropdown

9. 아이콘 색상 ↔ 상태 매핑 확정 검증 (사용자 확정, 2026-10-16)

확정 기준: 전구 컬러 visible=true / 회색 false, 눈꽃 컬러 frozen=false(동결 해제) / 회색 true(동결), 자물쇠 컬러 locked=false(잠금 해제) / 회색 true(잠금). 클릭 시 해당 boolean 반전값을 Callback으로 전달합니다. 기존 구현(layerIconOn(), onChange(layer, !pressed))이 이 기준과 같아 동작 코드는 바꾸지 않았고, 타입 주석·Story 설명·문서의 잠정 표기만 확정으로 바꿨습니다. SVG·Default/Hover CSS 변경 없음.

검증: Storybook Layer Dropdown의 Callback 예제에서 각 아이콘을 두 번씩 클릭했습니다. 색은 렌더링된 SVG의 실제 fill(전구 #FAB846/#9C9C9C, 눈꽃 #00CCFF/#949494, 자물쇠 #E4BF4D/#BEBEBE)로 판정했습니다.

레이어 · 아이콘 클릭 전 Callback 클릭 후
layer-0 전구 visible=true 컬러 onLayerVisibilityChange(layer-0, false) false 회색
layer-0 전구 false 회색 (layer-0, true) true 컬러
layer-0 눈꽃 frozen=false 컬러 onLayerFreezeChange(layer-0, true) true 회색
layer-0 눈꽃 true 회색 (layer-0, false) false 컬러
layer-0 자물쇠 locked=false 컬러 onLayerLockChange(layer-0, true) true 회색
layer-0 자물쇠 true 회색 (layer-0, false) false 컬러
layer-5 전구 visible=false 회색 onLayerVisibilityChange(layer-5, true) true 컬러
layer-5 전구 true 컬러 (layer-5, false) false 회색
layer-5 눈꽃 frozen=true 회색 onLayerFreezeChange(layer-5, false) false 컬러
layer-5 눈꽃 false 컬러 (layer-5, true) true 회색
layer-5 자물쇠 locked=true 회색 onLayerLockChange(layer-5, false) false 컬러
layer-5 자물쇠 false 컬러 (layer-5, true) true 회색
  • 모든 클릭에서 Callback 1회, onLayerSelect 0회, 목록 유지. aria-pressed는 표시됨 / 동결됨 / 잠김과 일치.
  • 클릭하지 않은 다른 레이어 7개의 상태는 변하지 않음.

10. 남은 차이 · NOT VERIFIED

  • 아이콘 색상 ↔ 상태 매핑은 위 §9로 확정·검증했습니다. 실제 SW 호스트에서 이 값으로 도면이 표시·동결·잠금되는지는 외부 연동이 필요합니다(NOT VERIFIED).
  • 실제 SW 호스트에서의 레이어 표시·동결·잠금 반영과 레이어 상세 화면: 패키지 단독 검증 불가(NOT VERIFIED).
  • 현재 레이어 이름 #FFC600, 목록 최대 높이 240px, 좁은 폭 왼쪽 이동은 Figma에 없는 구현값입니다.
  • 레이어 상세 버튼 Hover는 Figma Variant가 없어 추가하지 않았습니다.
  • Figma Smart Animate 곡선의 Prototype player 실재생 비교, 픽셀 diff, 실기기 390px, 스크린리더 실사용 검증은 수행하지 않았습니다.