feat(sw): viewer mode header, dropdown and popup panel

- 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
This commit is contained in:
shkim4 committed 2026-10-19 16:09:26 +09:00
1 parent e8409eff44
commit 7f42923ccf
50 files changed
+3838 -92

No files matched your search

+112
View File
@@ -0,0 +1,112 @@
# SW 뷰어 모드 상단 메뉴·팝업 (2026-10-19)
- 작업 위치: worktree `D:\디자인시스템\HMDesign-SW-Viewer`, 브랜치 `feature/sw-viewer-header`(기준 `feature/sw-package` e8409ef). 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.json` 74항목), `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.ts`
- `packages/sw/src/theme/sw-viewer.css`
- `packages/sw/ai/VIEWER.md`, `packages/sw/ai/examples/ExampleH-ViewerMode.tsx`
- `packages/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`/`onHomeClick`
- `SWViewerHeaderButton`
- `SWViewerMenu`: `entries`·`anchorRef`/`anchorPoint`·`surface`·`initialFocus`
- `SWViewerPanel`: `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 + 로고 + 25`px입니다. Header 높이 52px와 메뉴 위치는 변하지 않습니다.
**Storybook**
- `SW/Viewer` 10개: 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는 승인 대기입니다.
Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

@@ -0,0 +1,237 @@
{
"base": "http://127.0.0.1:6024",
"next": "http://127.0.0.1:6034",
"results": [
{
"id": "overview",
"width": 1920,
"size": "1920x1000 / 1920x1000",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "overview",
"width": 1180,
"size": "1180x1000 / 1180x1000",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "overview",
"width": 768,
"size": "768x1000 / 768x1000",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "interactive-states",
"width": 1920,
"size": "1920x2517 / 1920x2517",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "interactive-states",
"width": 1180,
"size": "1180x2527 / 1180x2527",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "interactive-states",
"width": 768,
"size": "768x2623 / 768x2623",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "logo-slot",
"width": 1920,
"size": "1920x1000 / 1920x1000",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "logo-slot",
"width": 1180,
"size": "1180x1000 / 1180x1000",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "logo-slot",
"width": 768,
"size": "768x1000 / 768x1000",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "document-dropdown",
"width": 1920,
"size": "1920x9112 / 1920x9112",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "document-dropdown",
"width": 1180,
"size": "1180x9122 / 1180x9122",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "document-dropdown",
"width": 768,
"size": "768x9298 / 768x9298",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "responsive-more",
"width": 1920,
"size": "1920x10042 / 1920x10042",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "responsive-more",
"width": 1180,
"size": "1180x10052 / 1180x10052",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "responsive-more",
"width": 768,
"size": "768x10048 / 768x10048",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "k-guide",
"width": 1920,
"size": "1920x1037 / 1920x1037",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "k-guide",
"width": 1180,
"size": "1180x1028 / 1180x1028",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "k-guide",
"width": 768,
"size": "768x1023 / 768x1023",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "property-panel-compare",
"width": 1920,
"size": "1920x1000 / 1920x1000",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "property-panel-compare",
"width": 1180,
"size": "1180x1000 / 1180x1000",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "property-panel-compare",
"width": 768,
"size": "768x1000 / 768x1000",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "composed-controls",
"width": 1920,
"size": "1920x1000 / 1920x1000",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "composed-controls",
"width": 1180,
"size": "1180x1000 / 1180x1000",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "composed-controls",
"width": 768,
"size": "768x1000 / 768x1000",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "document-open",
"width": 1920,
"size": "1920x10771 / 1920x10771",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "document-open",
"width": 1180,
"size": "1180x10761 / 1180x10761",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "document-open",
"width": 768,
"size": "768x10797 / 768x10797",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "hidden-sub-controls",
"width": 1920,
"size": "1920x1710 / 1920x1710",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "hidden-sub-controls",
"width": 1180,
"size": "1180x1700 / 1180x1700",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "hidden-sub-controls",
"width": 768,
"size": "768x1676 / 768x1676",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "detail-buttons",
"width": 1920,
"size": "1920x1000 / 1920x1000",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "detail-buttons",
"width": 1180,
"size": "1180x1000 / 1180x1000",
"diffPixels": 0,
"result": "PASS"
},
{
"id": "detail-buttons",
"width": 768,
"size": "768x1000 / 768x1000",
"diffPixels": 0,
"result": "PASS"
}
]
}
+621
View File
@@ -0,0 +1,621 @@
{
"storybook": "http://127.0.0.1:6034",
"reference": "http://127.0.0.1:5182",
"comparison": {
"reference": {
"document": [
{
"x": 73,
"y": 1,
"w": 337,
"h": 50,
"text": "C0060202-001"
}
],
"object": [
{
"x": 412,
"y": 1,
"w": 1027,
"h": 50,
"text": "파일 열기샘플 Mode"
}
],
"field": [
{
"x": 622,
"y": 6,
"w": 197,
"h": 41,
"text": "Model17,377L"
},
{
"x": 823,
"y": 5,
"w": 249,
"h": 42,
"text": "전체 보기2.5D어두운"
}
],
"button": [
{
"x": 421,
"y": 9,
"w": 109,
"h": 34,
"text": "파일 열기"
},
{
"x": 534,
"y": 9,
"w": 80,
"h": 34,
"text": "샘플"
},
{
"x": 828,
"y": 9,
"w": 109,
"h": 34,
"text": "전체 보기"
},
{
"x": 1402,
"y": 6,
"w": 32,
"h": 40,
"text": ""
}
],
"toggle": [
{
"x": 1086,
"y": 6,
"w": 81,
"h": 40,
"text": "레이어"
},
{
"x": 1171,
"y": 6,
"w": 68,
"h": 40,
"text": "설정"
},
{
"x": 1243,
"y": 6,
"w": 68,
"h": 40,
"text": "속성"
}
],
"tab": [
{
"x": 627,
"y": 7,
"w": 97,
"h": 40,
"text": "Model17,377"
},
{
"x": 728,
"y": 7,
"w": 87,
"h": 40,
"text": "Layout237"
}
],
"switchField": [
{
"x": 942,
"y": 6,
"w": 52,
"h": 40,
"text": "2.5D"
},
{
"x": 998,
"y": 6,
"w": 70,
"h": 40,
"text": "어두운 배경"
}
]
},
"package": {
"document": [
{
"x": 25,
"y": 1,
"w": 360,
"h": 50,
"text": "C0060202-001"
}
],
"object": [
{
"x": 387,
"y": 1,
"w": 1053,
"h": 50,
"text": "파일 열기샘플Model"
}
],
"field": [
{
"x": 597,
"y": 5,
"w": 197,
"h": 42,
"text": "Model17,377L"
},
{
"x": 798,
"y": 5,
"w": 249,
"h": 42,
"text": "전체 보기2.5D어두운"
}
],
"button": [
{
"x": 396,
"y": 9,
"w": 109,
"h": 34,
"text": "파일 열기"
},
{
"x": 509,
"y": 9,
"w": 80,
"h": 34,
"text": "샘플"
},
{
"x": 803,
"y": 9,
"w": 109,
"h": 34,
"text": "전체 보기"
},
{
"x": 1402,
"y": 6,
"w": 32,
"h": 40,
"text": ""
}
],
"toggle": [
{
"x": 1086,
"y": 6,
"w": 81,
"h": 40,
"text": "레이어"
},
{
"x": 1171,
"y": 6,
"w": 68,
"h": 40,
"text": "설정"
},
{
"x": 1243,
"y": 6,
"w": 68,
"h": 40,
"text": "속성"
}
],
"tab": [
{
"x": 602,
"y": 6,
"w": 97,
"h": 40,
"text": "Model17,377"
},
{
"x": 702,
"y": 6,
"w": 87,
"h": 40,
"text": "Layout237"
}
],
"switchField": [
{
"x": 916,
"y": 6,
"w": 52,
"h": 40,
"text": "2.5D"
},
{
"x": 972,
"y": 6,
"w": 70,
"h": 40,
"text": "어두운 배경"
}
]
}
},
"results": [
{
"name": "geometry button sizes equal to reference",
"result": "PASS",
"detail": "reference 109x34 80x34 109x34 32x40 / package 109x34 80x34 109x34 32x40"
},
{
"name": "geometry toggle sizes equal to reference",
"result": "PASS",
"detail": "reference 81x40 68x40 68x40 / package 81x40 68x40 68x40"
},
{
"name": "geometry tab sizes equal to reference",
"result": "PASS",
"detail": "reference 97x40 87x40 / package 97x40 87x40"
},
{
"name": "geometry switchField sizes equal to reference",
"result": "PASS",
"detail": "reference 52x40 70x40 / package 52x40 70x40"
},
{
"name": "geometry field sizes equal to reference (±1px height, known)",
"result": "PASS",
"detail": "reference 197x41 249x42 / package 197x42 249x42"
},
{
"name": "geometry document well height / top (x: logo rule)",
"result": "PASS",
"detail": "reference x73 y1 h50 / package x25 y1 h50"
},
{
"name": "menu opens on click",
"result": "PASS",
"detail": ""
},
{
"name": "menu has 3 entries",
"result": "PASS",
"detail": ""
},
{
"name": "menu placed under its button",
"result": "PASS",
"detail": "menu 549,365 button 549,361"
},
{
"name": "trigger shows open state",
"result": "PASS",
"detail": ""
},
{
"name": "ArrowDown moves focus in menu",
"result": "PASS",
"detail": ""
},
{
"name": "Escape closes menu",
"result": "PASS",
"detail": ""
},
{
"name": "Escape returns focus to trigger",
"result": "PASS",
"detail": ""
},
{
"name": "Enter opens with first entry focused",
"result": "PASS",
"detail": ""
},
{
"name": "Enter selects entry (document changes)",
"result": "PASS",
"detail": ""
},
{
"name": "onCommand reports menu entry",
"result": "PASS",
"detail": "Command: samples/sample-dxf"
},
{
"name": "outside click closes menu",
"result": "PASS",
"detail": ""
},
{
"name": "tabs ArrowRight selects Layout",
"result": "PASS",
"detail": ""
},
{
"name": "header switch toggles",
"result": "PASS",
"detail": ""
},
{
"name": "hover face #266651",
"result": "PASS",
"detail": ""
},
{
"name": "toggle opens panel",
"result": "PASS",
"detail": ""
},
{
"name": "toggle pressed state + #FFC600",
"result": "PASS",
"detail": ""
},
{
"name": "panel focused on open",
"result": "PASS",
"detail": ""
},
{
"name": "Escape closes panel",
"result": "PASS",
"detail": ""
},
{
"name": "focus returns to toggle",
"result": "PASS",
"detail": ""
},
{
"name": "corner resize changes size",
"result": "PASS",
"detail": "320x420 → 263x323"
},
{
"name": "drag moves panel",
"result": "PASS",
"detail": "dx -300 dy 30"
},
{
"name": "drag stays inside bounds (10px edge)",
"result": "PASS",
"detail": "right gap 10, bottom gap 10"
},
{
"name": "collapse hides body",
"result": "PASS",
"detail": ""
},
{
"name": "title double click expands",
"result": "PASS",
"detail": ""
},
{
"name": "panel content callback",
"result": "PASS",
"detail": ""
},
{
"name": "close hover #E40000 / white X",
"result": "PASS",
"detail": ""
},
{
"name": "close button closes",
"result": "PASS",
"detail": ""
},
{
"name": "last touched panel on top",
"result": "PASS",
"detail": "layer z 37, options z 36"
},
{
"name": "modal popup opens with backdrop",
"result": "PASS",
"detail": ""
},
{
"name": "modal focus stays inside",
"result": "PASS",
"detail": ""
},
{
"name": "modal Escape closes",
"result": "PASS",
"detail": ""
},
{
"name": "ArrowRight opens submenu with focus",
"result": "PASS",
"detail": ""
},
{
"name": "submenu opens to the side",
"result": "PASS",
"detail": "parent right 596, sub left 596"
},
{
"name": "third level opens on hover",
"result": "PASS",
"detail": ""
},
{
"name": "ArrowLeft closes one level",
"result": "PASS",
"detail": ""
},
{
"name": "checkbox entry toggles via onCommand",
"result": "PASS",
"detail": "Command: file/lineweight=true"
},
{
"name": "checkbox state reflected",
"result": "PASS",
"detail": ""
},
{
"name": "disabled entry does nothing",
"result": "PASS",
"detail": ""
},
{
"name": "menuAlign end + menuWidth",
"result": "PASS",
"detail": "width 220"
},
{
"name": "context menu opens at pointer",
"result": "PASS",
"detail": "90,729"
},
{
"name": "context entry reported",
"result": "PASS",
"detail": ""
},
{
"name": "menu stays inside the viewport",
"result": "PASS",
"detail": "left 4, right 224"
},
{
"name": "no horizontal overflow at 1440 / 1100 / 860 / 520",
"result": "PASS",
"detail": "[[1440,0,0],[1100,0,0],[860,0,0],[520,0,0]]"
},
{
"name": "1440: no More",
"result": "PASS",
"detail": ""
},
{
"name": "1100: More, samples/tabs/switches moved",
"result": "PASS",
"detail": ""
},
{
"name": "860: panel toggles moved too",
"result": "PASS",
"detail": ""
},
{
"name": "520: 파일 열기 / 전체 보기 icon only",
"result": "PASS",
"detail": ""
},
{
"name": "More sections like the reference",
"result": "PASS",
"detail": "샘플 도면 | 기본 도면 · DWG | 평면 및 종단면도 · DWG | 기본 도형 · DXF | 도면 공간 | Model · 17,377개 | Layout · 237개 | 화면 보기 | 2.5D | 어두운 배경 | 패널 | 레이어 | 설정 | 속성"
},
{
"name": "More face beige 260px",
"result": "PASS",
"detail": ""
},
{
"name": "More checkbox reports command",
"result": "PASS",
"detail": "Command: layers=true"
},
{
"name": "More radio selects tab value",
"result": "PASS",
"detail": ""
},
{
"name": "mode switch shows viewer header",
"result": "PASS",
"detail": ""
},
{
"name": "brand click returns to normal SWHeader",
"result": "PASS",
"detail": ""
},
{
"name": "state kept across mode switch (layer panel still open)",
"result": "PASS",
"detail": ""
},
{
"name": "logo none: no HM / text / icon",
"result": "PASS",
"detail": "{\"text\":\"\",\"img\":false,\"width\":24,\"docX\":25,\"height\":52,\"fileOpenY\":9}"
},
{
"name": "logo none: cap shrinks to its edge (no wide gap)",
"result": "PASS",
"detail": "{\"text\":\"\",\"img\":false,\"width\":24,\"docX\":25,\"height\":52,\"fileOpenY\":9}"
},
{
"name": "logoSrc shows the image (cap = 24 + logo + 25, min 72)",
"result": "PASS",
"detail": "{\"text\":\"\",\"img\":true,\"width\":94,\"docX\":95,\"height\":52,\"fileOpenY\":9,\"logoWidth\":45}"
},
{
"name": "logo element shown",
"result": "PASS",
"detail": "{\"text\":\"LOGO\",\"img\":true,\"width\":81,\"docX\":82,\"height\":52,\"fileOpenY\":9}"
},
{
"name": "header height and menu row unchanged with / without logo",
"result": "PASS",
"detail": "52/9 52/9 52/9"
},
{
"name": "text outline 1.3px black on 14px text (label / file name / tab)",
"result": "PASS",
"detail": "rgb(0, 0, 0) 1.3px 0px 0px, rgb(0, 0, 0) 1.2px 0.5px 0px, rg"
},
{
"name": "label outline 1px black on 11px captions / counts",
"result": "PASS",
"detail": "rgb(0, 0, 0) 1px 0px 0px, rgb(0, 0, 0) 0.92px 0.38px 0px, rg"
},
{
"name": "icon outline: 4 x 1px black drop-shadows + #061A14 glow",
"result": "PASS",
"detail": "drop-shadow(rgb(0, 0, 0) 1px 0px 0px) drop-shadow(rgb(0, 0, 0) -1px 0px 0px) drop-shadow(r"
},
{
"name": "fill / size / weight / spacing kept",
"result": "PASS",
"detail": "rgb(255, 255, 255) 14px 500 normal"
},
{
"name": "hover changes fill only (outline kept)",
"result": "PASS",
"detail": ""
},
{
"name": "disabled fades text + outline together",
"result": "PASS",
"detail": "[\"0.6\",true]"
},
{
"name": "SW/Tool removed from the sidebar",
"result": "PASS",
"detail": "SW/Header, SW/Viewer, SW/Popup"
},
{
"name": "SW/Popup, SW/Header and SW/Viewer remain",
"result": "PASS",
"detail": ""
},
{
"name": "no page errors",
"result": "PASS",
"detail": ""
}
],
"errors": []
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB