- SWViewerHeader: data-driven viewer menu (button / toggle / menu / tabs / switch / custom), More by collapseBelow, trailing slot, onCommand; SWHeader logo props with no default logo - SWViewerMenu: dropdown, check / radio, multi-level submenu, context menu at a point - SWViewerPanel: viewer popup frame with free children / footer, drag, corner resize, collapse, modal - Panel controls: SWViewerSection / Field / Hint / Switch / Slider / Input / Button / Badge / Status - SWHeader black text outline tokens on viewer text, matching icon outline (drop-shadow) - Storybook SW/Viewer stories; remove SW/Tool story (SW/Popup kept) - AI guide ai/VIEWER.md, example H, verification scripts and evidence
12 KiB
SW 뷰어 모드 상단 메뉴·팝업 (2026-10-19)
- 작업 위치: worktree
D:\디자인시스템\HMDesign-SW-Viewer, 브랜치feature/sw-viewer-header(기준feature/sw-packagee8409ef). Task A+B 통합 worktree(HMDesign-SW-Integration)는 변경하지 않았습니다. Commit·Push 없음. - 범위(사용자 확정): HMDesign Storybook 데모 기준. 실제 SW 프로그램 연결과 DWG/DXF 기능은 제외했습니다. 참고 프로젝트
D:\디자인시스템\테스트\dwg-dxf-viewer-hm은 읽기만 했고, 최신 소스는 scratchpad로 빌드해vite preview로 띄웠습니다(참고 폴더에 쓰기 없음). - 추가 요청 반영: ① Viewer Header 텍스트·아이콘에 SW Header와 같은 검정 외곽선 ② Storybook
Tool Popup메뉴 정리:SW/Tool삭제.SW/Popup은 공통SWPopup예시이므로 Commit 승인 시 지시에 따라 복원·유지 ③ 로고 미제공 시HM등 아무것도 표시하지 않음. - 증거:
docs/sw/viewer-qa/(같은 해상도 캡처,report.json74항목),docs/sw/viewer-qa/regression/regression.json(기존 SW Header 33장 픽셀 비교).
A. 분석 결과
참고 뷰어 상단 메뉴(Toolbar.tsx, sw-header.css — @hm-design/ui SWHeader 조합, 1440px 실측)
- 52px Header(그라디언트 #266651 → #123328 → #0A221D, 1px #071E18 테두리), 72px 사선 로고 면(HM), 파일명 면
clamp(220px, 25vw, 360px), 객체 수정 면(반경 6, 테두리 #135643). - 그룹: 파일(파일 열기 109×34, 샘플▾ 80×34) / 도면 공간 field 면(Model·Layout 탭 97·87×40, 개수 11px) / 화면 보기 field 면(전체 보기, 2.5D·어두운 배경 스위치 칸 52·70×40) / 오른쪽 끝(레이어·설정·속성 토글 81·68·68×40, 상태 11px, 정보 32×40).
- 상태: Hover = #266651 면, On·Open·선택 탭 = #FFC600 글자, Disabled = 60%, 스위치 off #0A221D / on #FFC600.
- 반응형: 1180px 미만 = 샘플·탭·스위치가 더보기(베이지 #F5F0E5, 260px)로, 900px 미만 = 패널 토글도 더보기로, 560px 미만 = 아이콘만 표시하고 상태 글자 숨김.
참고 팝업·설정창
- 샘플 Dropdown(흰 면, #DEDBD2 테두리, 반경 4, 항목 36px, 강조 rgba(189,223,212,.45))과 더보기 Dropdown(라벨, 체크, 라디오 구획).
- DraggablePanel 3종(레이어 320×420, 옵션 340×520, 속성 320×420): 베이지 #E0DACE, 2px #897445, 제목 막대 #221D13·#FFC600 700, 곡선 녹색 닫기(Hover #E40000), 접기, 드래그(경계 10px), 네이티브 resize, 본문 12px 패딩, 카드 섹션 #F5F0E5.
- 라이선스 모달 Dialog.
- Context Menu와 다단계 서브메뉴는 참고 뷰어에 없습니다. 요청에 따라 공통 Dropdown 기능으로 추가했습니다.
기존 SW 패키지와의 차이
- 기존
SWHeader는 Figma 26:8944 기준(49px, 고정 필드 구성)입니다. 데이터 기반 메뉴, 탭, 스위치, 드래그 패널이 없습니다. SWPopup은 314px 고정 Figma 속성창 프레임으로, 이동·크기 조절·접기를 지원하지 않습니다.- 재사용: 사용자 확정 면 토큰 3종(
--hm-sw-header-document-*,object-*,property-*, 참고 뷰어와 같은 값), SW 외곽선 토큰(--hm-sw-header-text-outline,label-outline,text-outline-room),SWTheme범위·버튼 초기화,SWHeader로고 Props 규칙.
분류
| 항목 | 분류 | 근거 |
|---|---|---|
| 일반 모드 Header | 재사용(변경 없음) | SWHeader |
| 면 배경·외곽선·글꼴 | 재사용 | 기존 토큰 |
| 뷰어 Header | 신규 | 기존 SWHeader는 Figma 고정 구성이고, 뷰어 메뉴 구조·크기가 다름 |
| Dropdown·서브메뉴·Context | 신규 | SW 패키지에 범용 Dropdown 없음(필드 전용 Dropdown만 있음) |
| 뷰어 팝업 | 신규 | SWPopup 프레임(314px Figma art)과 외형·동작이 다름. Variant로 만들면 기존 속성창 DOM·CSS를 바꿔야 해서 분리 |
B. 패키지 변경 결과
신규 파일
packages/sw/src/components/sw-viewer/:types.ts,SWViewerHeader.tsx,SWViewerMenu.tsx,SWViewerPanel.tsx,SWViewerControls.tsx,index.tspackages/sw/src/theme/sw-viewer.csspackages/sw/ai/VIEWER.md,packages/sw/ai/examples/ExampleH-ViewerMode.tsxpackages/sw/tests/viewer.browser.mjs,viewer-regression.browser.mjs
수정 파일
packages/sw/src/index.ts: 끝에 Export 1블록packages/sw/ai/AI_USAGE.md: 문서 표 1행packages/sw/tests/storybook-inventory.mjs: 삭제한 Story id 기록
기존 컴포넌트·sw.css·SWHeaderPropertyPanel.tsx는 수정하지 않았습니다. A+B 통합 작업과 충돌 가능성이 있는 곳은 index.ts·AI_USAGE.md 각 1군데뿐입니다.
공개 API(@hm-design/sw)
SWViewerHeader:groups·trailing·onCommand·documentTitle·logo/logoSrc/logoAlt/onHomeClickSWViewerHeaderButtonSWViewerMenu:entries·anchorRef/anchorPoint·surface·initialFocusSWViewerPanel:children·footer·headerActions·크기·위치·strategy·드래그·크기 조절·접기·modal- 패널 콘텐츠:
SWViewerSection,SWViewerField,SWViewerHint,SWViewerSwitch,SWViewerSlider,SWViewerInput,SWViewerButton,SWViewerBadge,SWViewerStatus - 타입:
SWViewerHeaderItem,SWViewerHeaderGroup,SWViewerMenuEntry,SWViewerCommand,SWViewerPanelPlacement및 각 Props
외곽선(SW Header 분석 → 같은 기준 적용)
- 텍스트: SW Header는 14px 글자에 검정 1.3px(16 text-shadow), 12px 라벨에 1px을 씁니다. 뷰어의 14px 글자(파일명·버튼·탭·로고)는
--hm-sw-header-text-outline, 11px(스위치 캡션·개수·상태)는--hm-sw-header-label-outline을 그대로 사용합니다. 말줄임 파일명에는overflow-clip-margin을 적용했습니다. - 아이콘: SW Header 아이콘 자산(print·K·레이어)은 채움 + 1px 검정 바깥 Stroke(Figma mask outside) + glow(stdDeviation 1.615, #061A14)입니다. 프로그램 아이콘은 자유 SVG라서 같은 효과를
drop-shadow체인(1px × 4방향 + glow)으로 재현합니다. 토큰--hm-sw-viewer-icon-outline이며 아이콘 윤곽을 따라갑니다. - 색·크기·굵기·간격은 유지합니다. Hover·Active는 채움 색만 바뀌고, Disabled는 버튼 전체 opacity로 함께 흐려집니다. Dropdown과 패널에는 외곽선이 없습니다(SW Header More 메뉴와 같음).
로고
SWHeader와 같은 Props(logo,logoSrc,logoAlt,onHomeClick)를 씁니다.- 로고를 주지 않으면 사선 끝 24px만 남고 문자·아이콘은 없습니다.
- 로고를 주면 72px 면이 되고, 로고가 더 넓으면
24 + 로고 + 25px입니다. Header 높이 52px와 메뉴 위치는 변하지 않습니다.
Storybook
SW/Viewer10개: Viewer Header(로고 없음 기본), Menu Groups, Item States, Header + Dropdown(서브메뉴·체크·라디오·Context Menu), Settings Popup(footer), Popup Content Variants, Variable Size Popups, Responsive Widths, SWHeader vs Viewer Header(모드 전환), Logo- 공개 API만 사용합니다. Story CSS는 배치와 Story 자체 목록에만 쓰고
hm-sw-*는 사용하지 않습니다. SW/Tool(sw-tool.stories.tsx)만 삭제했습니다.SW/Popup(sw-popup.stories.tsx, 공통SWPopup예시)과sw-integrated-stories.css는 원본 그대로 유지합니다.SWToolButton/SWToolGroup/SWPopup과 그 API도 유지합니다.- 삭제한
sw-tool--tool-buttons를 여는 기존integrated-improvement.browser.mjs는 과거 검증 기록용으로만 남습니다. 지금 다시 실행하면 해당 단계가 실패합니다.
AI 지침: ai/VIEWER.md(역할·사용 환경·Props·이벤트·Import·Viewer 적용 조건·콘텐츠 교체·외곽선·로고·주의사항·올바른 예/잘못된 예), 예제 H, AI_USAGE.md 문서 표 반영.
C. SW 프로그램 통합 결과
이번 범위에서 제외(사용자 결정)했으므로 NOT TESTED입니다. Storybook SWHeader vs Viewer Header에서 Header 교체만 UI로 시연했고, 화면 상태(파일명·패널)는 유지됩니다.
메뉴 명령은 모두 onCommand 로그로만 표시하며 실제 기능은 미연결입니다: 파일 열기, 전체 보기, 선택 확대, 인쇄, 내보내기, 측정.
D. 검증 결과
| 항목 | 판정 | 근거 |
|---|---|---|
| Typecheck | PASS | npm run typecheck(전체 패키지 build + tsc -b + 5개 workspace) exit 0 |
| Package Build | PASS | build:packages / build:sw 성공 |
| Storybook Build | PASS | npm run build-storybook exit 0. CSS 경고 1건은 기존 docs의 bg-[var(...)] 문구(기존부터 있음) |
| 공개 Export | PASS | ai-docs.check.mjs 25/25(문서 식별자·예제 Import·링크) |
| 독립 소비 프로젝트 | PASS (일부) | ai-template-consumer.mjs: npm pack → 새 프로젝트 설치 → 예제 A~H tsc + vite build 통과. 예제 H의 브라우저 렌더링은 소비 프로젝트에서 미실행(Storybook에서만 확인) |
| 실제 화면 비교 | PASS (알려진 차이 있음) | 1440×900 같은 해상도 캡처와 수치 비교. 버튼·토글·탭·스위치 칸 크기가 참고와 같음(px 단위). 도면 공간 field 면은 42px로 참고(41px)와 1px 차이. 원인은 참고 Tabs 루트 39px. 파일명 면 x는 로고 규칙 때문에 −48px(의도된 차이) |
| 사용자 인터랙션 | PASS | viewer.browser.mjs 74/74 PASS (아래 항목 참조) |
| 외곽선 | PASS | 텍스트 1.3px/1px 검정 각 16 shadow, 아이콘 drop-shadow 5개, 색·크기·굵기 유지, Hover·Disabled에서 유지, 3배 확대 캡처(outline-*.png) |
| 로고 | PASS | 없음: 문자·이미지 0, 면 24px. logoSrc·logo 표시. 높이 52px, 메뉴 y 동일 |
SW/Tool 삭제·SW/Popup 유지 |
PASS | dev index.json: SW 제목은 SW/Header, SW/Popup, SW/Viewer (viewer.browser.mjs 재실행) |
| 기존 기능 회귀 | PASS | 기존 SW/Header Story 11개 × 3폭(1920/1180/768) 픽셀 차이 0(33/33). 비교 대상은 기준 Storybook(6024, e8409ef)과 이 브랜치. test:components 9/9, test:guard 94/94, git diff --check 통과 |
| Window Move Motion Story | NOT TESTED | 애니메이션이라 픽셀 비교에서 제외 |
| Firefox·Safari, 실제 창 크기 변경 | NOT TESTED | Chrome headless만 실행. 폭은 viewport와 Story 폭으로 재현 |
viewer.browser.mjs 74개 항목: 메뉴 열기·위치·Enter/Arrow/Escape(Focus 복귀)·바깥 클릭, 탭 화살표, 스위치, Hover 면, 토글 → 팝업, 패널 Focus·Escape·Focus 복귀, 모서리 크기 조절, 드래그·경계 10px, 접기·더블클릭, 닫기 Hover #E40000, 앞으로 가져오기, 모달 배경·Focus Trap·Escape, 서브메뉴 →/← 3단계, 체크·라디오·비활성 항목, menuAlign·menuWidth, Context Menu 포인터 위치, 화면 경계, 1440/1100/860/520 가로 넘침 0, More 구획(샘플 도면/도면 공간/화면 보기/패널), More 체크·라디오 명령, 모드 전환과 상태 유지, 로고, 외곽선, 메뉴 삭제, 페이지 오류 0.
참고 뷰어와 의도적으로 다른 점
- 모서리 크기 조절: 네이티브
resize대신 같은 위치의 Grip을 씁니다. Firefox 등 모든 브라우저에서 동작하고 자동 검증할 수 있습니다. - 패널 Escape 닫기를 추가했습니다(Focus가 패널 안에 있을 때).
- 로고 기본 표시를 없앴습니다(사용자 결정).
- 서브메뉴와 Context Menu를 추가했습니다(요청 범위).
E. 최종 판정
PARTIAL: 패키지 컴포넌트 구현, Storybook, AI 지침, 주요 UI·인터랙션 검증은 끝났습니다. PASS가 아닌 이유는 요청 원문의 “SW 프로그램 뷰어 모드 통합”이 이번 범위에서 제외되어(사용자 결정) 진행하지 않았기 때문입니다. Commit·Push는 승인 대기입니다.