docs(sw): Dotum default font, Footer design check and real viewer consumer QA

Report docs/sw/sw-dotum-font-2026-10-20.md and evidence docs/sw/sw-dotum-font-qa/: Noto -> Dotum layout diff of 40 SW
Stories x 4 widths, Header hysteresis trace, Footer design items (4 PASS), SW regression runs with baseline failure
classification, and the isolated HMDesignSwTest-viewer run (Chrome 34/34, Firefox 15/15; original project untouched).
Open items: synthesized-bold overflow in fixed Header cells and Footer POLYGON / WIPEOUT labels (design review),
viewer-regression not run, macOS / Linux fallback not verified.
This commit is contained in:
shkim4 committed 2026-10-20 16:59:55 +09:00
1 parent 942f72ae12
commit 6504668e85
149 files changed
+78083

No files matched your search

+97
View File
@@ -0,0 +1,97 @@
# SW 기본 글꼴 Dotum · Footer 디자인 확인 · 실제 Viewer 소비 프로젝트 검증 (2026-10-20)
범위: `feature/sw-package`, 기준 HEAD `454472d`(원격 동일). SW 패키지(`packages/sw`), SW Story(`src/sw/sw-theme.stories.tsx`), AI 문서, README만 변경했습니다. Web UI·OrgChart 코드·토큰은 변경하지 않았습니다(공통 `AI_GUIDE.md` 사본 동기화만 각 패키지 `ai/`에 반영). **Commit·Push 전(승인 대기).** 증거: [sw-dotum-font-qa/](./sw-dotum-font-qa/).
## 1. 변경 내용
| 파일 | 변경 | 이유 |
|---|---|---|
| `packages/sw/src/theme/sw.css` | `--hm-sw-header-font-family: Dotum, "돋움", "Malgun Gothic", "Apple SD Gothic Neo", sans-serif` (이전 `"Noto Sans KR", …`) | SW 기본 글꼴 = 돋움. 토큰 1곳(가장 바깥 SW 범위)에서만 선언, 컴포넌트별 `font-family` 없음 |
| 〃 | `.hm-sw-header__mode` padding `0 8px` → `0 4px` (칸 90px 유지) | 돋움에는 Bold 글꼴이 없어 700이 합성 Bold(글자당 약 +1px). `그리기모드` 77.8px > 내용 폭 74px로 말줄임 → 칸 폭·가운데 정렬은 그대로 두고 여백만 줄여 해결 |
| `packages/sw/src/theme/sw-footer.css` | 주석만(Noto → Dotum) | 사실 정정 |
| `packages/sw/tests/theme-inheritance.browser.mjs`, `src/sw/sw-theme.stories.tsx` | 기본값 = Dotum, 상속 확인용 검증 값 = Noto Sans KR로 교체 | 기본값과 검증 값이 같으면 상속 검사가 무의미해짐. 검사 항목·조건 수는 동일(23) |
| `packages/sw/tests/ai-template-consumer.browser.mjs` | 토큰 글꼴 기대값 Noto → Dotum | 기본값 변경 반영 |
| `packages/sw/tests/footer-design-review.browser.mjs` (신규) | Footer 확인 4건 + 텍스트 규칙 계산값·상태별 캡처 | §4 판정 근거 |
| `docs/ai/AI_GUIDE.md` (+ `sync:ai-docs`로 ui·sw·org-chart·org-chart-react 사본) | 혼합 규칙 1에 "SW = 돋움, Web = Noto Sans KR, OrgChart = 자기 설정, 서로 복사 금지" | 공통 규칙 |
| `packages/sw/ai/AI_USAGE.md`, `DESIGN_RULES.md`, `VIEWER.md`, `COMPOSITION_PATTERNS.md`, `examples/ExampleJ-Theme.tsx`, `README.md` | "Noto 기본 / Dotum 승인 대기" 문구 → "돋움 기본, SWTheme·SW 토큰 우선, Web 글꼴 복사 금지, 합성 Bold 폭 주의". 예시 글꼴 값은 프로그램 결정 예시(Malgun Gothic)로 교체 | 문서 일관성 |
글꼴 파일·CDN 의존성은 추가하지 않았습니다. 돋움은 Windows 기본 `gulim.ttc`에 포함된 시스템 글꼴이며, 실제 렌더링 글꼴을 CDP `getPlatformFontsForNode`로 확인했습니다(Header·Footer·Popup·Viewer 모두 `Dotum`, 대체 글꼴 0).
## 2. Dotum 전후 레이아웃 차이 (SW Story 40개 × 1920/1280/900/640)
증거: `font-diff/layout-diff-noto-to-dotum.json`, `font-diff/clipped-text-dotum-vs-noto.json`, before/after 캡처.
- 페이지·Header 가로 넘침: 0건(전후 동일). Header 필드는 Figma 고정 폭이라 Breakpoint(1800/1180/1080/900/640) 계산은 변하지 않음(1920→520 전 구간 `fields` clientWidth = scrollWidth).
- 높이: `line-height: normal` 텍스트 상자가 20 → 16px(돋움 metric). 정렬은 flex 가운데라 화면상 위치 차이 없음.
- 글자 폭: 한글은 비슷하거나 좁고, 라틴·숫자·700(합성 Bold)은 넓어짐(예: `255,229,0` 72 → 87px, `파일 열기` 59 → 70px). 내용 폭 필드는 그만큼 넓어지고 파일명이 나머지를 가져감(설계된 동작).
- 새로 잘리는 텍스트(고정 폭 칸):
| 항목 | 돋움 / 칸 | 처리 |
|---|---|---|
| Header `그리기모드` (90px 칸) | 77.8 > 74 | **FIXED** (padding 4px) |
| Header 값 `Standard`(문자/치수스타일), `0_Layer_Cludmark`(레이어 142), 스케일 `1.00`(38px) | 0.3~1.5px 초과 | **REVIEW REQUIRED** — 원인은 700 합성 Bold. Figma 고정 폭을 바꾸거나 굵기 정책(700 vs Figma Dotum Regular+Stroke)을 바꾸는 디자인 결정이라 임의 수정하지 않음 |
| Footer 명령 라벨 `POLYGON`, `WIPEOUT` (64px) | 76.9 / 69.9 (Noto에서도 66.9 / 66.3으로 이미 잘림) | **REVIEW REQUIRED** — 기존 문제가 커짐. 글자 크기·자간은 Figma 값 |
| Story fixture 문자열(`Display...`, 뷰어 `상태 확인용.dwg` 100px, 패널 제목 `250 × auto (최소 폭)`) | 1~6px 초과 | 말줄임 설계 동작(데이터 길이 문제), 변경 없음 |
- Popup·Viewer Panel·SWSelect·SWSlider·Footer 탭: 새 잘림 0, 가로 넘침 0. Popup 값(500)은 합성 Bold 대상이 아니어서 Regular로 보임(Figma와 같은 인상).
## 3. Header 히스테리시스 재검증 (돋움)
`footer-popup-viewer-refinement` 47/47, `integrated-improvement`(options·popup) 89/89 PASS. 테스트 조건은 그대로입니다. Trace(`[폭, Open 표시, hold]`): 넓어질 때 `520 0 → 560 0 → 600 1 → 640 1(actions) → 680 1(actions) → 720 1 → 760 1 → 820 1 → 900 1(color) → 1080 1(color)`, 1920 모두 복귀, 줄일 때 1800에서 Open이 먼저 More로 이동, 다시 넓히면 600에서 1회 복귀 — 수정안 A(Noto) 기록과 동일. 콘솔 오류·React #185(무한 업데이트)·ResizeObserver 오류 0.
## 4. Footer 디자인 확인 4건 (Storybook `SW/Footer › 전체 Footer · 실제 조합`, 돋움)
증거: `footer-design/`(21/21 PASS, 상태별 캡처).
| 항목 | 판정 | 실제 확인 |
|---|---|---|
| 3-1 전체보기 Hover(보조기능·명령어) | **PASS** | Hover 시 `::after` 링 opacity 0 → 1이 버튼 74 × 71 전체를 덮음(gra-border-orange 1px), 두 줄 글자 모두 `#FF5C00`. 크기·글자 위치 변화 0. 일부만 남는 테두리 없음. Selected(`aria-pressed`/`expanded`)는 같은 규칙, Disabled는 Hover 제외 |
| 3-2 하단 분류 `+` / Layout `+` Hover | **PASS** | 분류 `+`(28 × 12): 아이콘만 주황 +로 교체, 면 없음, 크기 동일. Layout `+`(24 × 22): 버튼 모양 마스크 안에 gra-border-orange 면 + 흰 + 외곽선. 클릭 동작은 Story Callback으로 유지(기존 47/47 검사) |
| 3-3 비선택 Model 탭 | **PASS** | 토큰 `--hm-sw-footer-gra-border-orange` = 지정 그라데이션과 정확히 같음(`#DA6813 8.52% / #FFBB89 37.93% / #E5690D 71.85% / #AE3607 92.77%`). 선택 = 주황 면, 비선택 = `tab-model.svg` 베이지 면. 비선택 베이지는 Figma 26:9914 `model` Default(베이지)와 일치. 참고: Figma Hover(베이지 + 주황 글자)·On(갈색)은 2026-10-20 사용자 요청으로 주황 면 + 검정 글자로 바뀐 상태 그대로 |
| 3-4 명령이 적은 분류 선택 배경 | **PASS** | 도형·수정·편집·문자 포함 12개 분류 모두: vacant 면 하단(1074) < 선택 탭 상단(1078), Pocket 뒤(좌·중·우) 면이 하나(`menu__viewport`). 갈라짐 재발 없음. 2차에 보고한 변화(명령이 적은 분류의 Pocket 면이 어두운 vacant → 그룹 면)는 그대로이며 디자인 확인 권장 사항으로 유지 |
| 3-5 Model·Layout 텍스트 | **PASS** | 돋움 12px 400 `#161410`, 외곽선 없음. Model 선택·비선택·Hover, Layout Default·Hover의 글자 상자·색 동일 |
## 5. 실제 소비 프로젝트 독립 검증 (HMDesignSwTest-viewer)
- 원본: `D:\디자인시스템\HMDesignSwTest-viewer` — HEAD `15ef6ef`(detached), Submodule `68fbcf6`(+ 미커밋 `sw.css` popup scrollbar 6줄), 작업 트리 변경 20개. **읽기만 했고 변경 없음**(검증 후 HEAD·Submodule·변경 20개·`package-lock.json` 시각 2026-10-19 그대로).
- 독립 환경: 세션 scratchpad `viewer-verify/`. 원본 작업 트리(미커밋 변경 포함, `node_modules`·`dist`·`.git`·`HMDesign` 제외)를 복사하고, `HMDesign/packages/{ui,sw}` 자리에 이 저장소 스냅샷을 배치(구조 = Git Submodule 경로 + npm Workspace 그대로, publish 전제 없음). 민감 설정 파일 없음.
- 시험한 소스: `454472d` + 작업 트리 변경(`consumer-viewer/hmdesign-snapshot.patch`, sha256 앞 16자 `7982bda27eb02f45`), `packages/sw/dist/styles.css` `09e9f80d…`. 원본 Submodule이 갖고 있던 scrollbar 미커밋 수정은 `454472d`에 이미 포함됨(`3a5e29f` 조상).
- `npm install`(workspace 링크 `@hm-design/sw|ui` → 스냅샷) → `tsc -b --noEmit` + `vite build` PASS → `vite preview`(5391).
- Chrome 34/34 PASS(`consumer-viewer/chromium-result.json`): 돋움 렌더링(Header 102 glyph 전부 Dotum), Web 토큰 `--hm-font-family-base` Noto 유지, DXF·DWG 3종 로드(simple.dxf 1.3s, BasicSample.dwg 1.4s, civil.dwg 1.9s, 도면 픽셀 확인), 휠 확대·드래그 팬·F(전체 보기), 모델/배치 탭 전환, 샘플 Dropdown 열기·Escape·샘플 로드, 2.5D 전환, 옵션 패널(SWViewerPanel) 열기·SWViewerSlider 값 변경과 숫자 입력 동기화·SWViewerSwitch·제목 드래그 이동·크기 조절·본문 세로 스크롤·잘린 글자 0·Escape 닫기, 레이어 패널, 정보(modal) Escape, 1920/1180/900/560/375 가로 넘침 0과 More 메뉴. 콘솔 오류 0(프로그램에 favicon 없음 — 기존).
- Firefox 158(설치본, WebDriver BiDi) 15/15 PASS: 돋움 해석, civil.dwg 로드, Header 글꼴, 메뉴 열기·Escape, 옵션 패널, 1400/500 가로 넘침 0.
- 이 프로그램은 SW **뷰어 모드**만 사용합니다(SWViewer* 14종). SWHeader·Home Menu·Footer·SWPopup·SWSelect·SWSlider(일반)는 프로그램에 없어 Storybook 검증으로 대신했습니다.
- 사용 규칙 점검(수정하지 않음, 보고만):
1. `src/App.tsx:74` 화면 루트에 `className="hm-sw-theme"`를 직접 붙임 → 규칙상 `<SWTheme>` 사용(소비 코드가 `hm-sw-*` class를 붙이지 않음).
2. `LoadProgress`가 Web `Progress`를 SW 화면 최상단에 사용 — 뷰어 모드에서 Web 컨트롤 허용 지점(`SWViewerPanel` children) 밖. 대응 SW 컴포넌트 없음 → 문서상 "없는 컴포넌트" 절차 대상.
3. `index.css`가 Web 시맨틱 토큰(`--background` 등)을 SW 팔레트로 재정의하고 `--hm-font-family-base`·`body` 글꼴을 Noto로 지정 — Web+SW 한 문서 혼합(AI_GUIDE §5 혼합 규칙 4, NOT VERIFIED 조합). SW 영역은 `hm-sw-theme` 덕분에 돋움으로 표시됨을 확인.
4. 패널 목록·좌표 표시(`viewer-panels.css`)는 프로그램 레이아웃이며 `--hm-sw-viewer-*` 토큰만 사용(규칙 범위 안).
- CAD 엔진·도면 처리 코드는 변경하지 않았습니다.
## 6. 테스트 결과와 실패 분류
| 테스트 | 결과 | 분류 |
|---|---|---|
| `footer-popup-viewer-refinement` | 47/47 | — |
| `integrated-improvement` options·popup | 89/89 | — |
| `theme-inheritance` | 23/23 | — |
| `viewer.browser` | 70/70 | — |
| `storybook-simplification` | 9/9 | — |
| `footer-design-review`(신규) | 21/21 | — |
| `overview` | 51 PASS / 3 FAIL | FAIL 3 = 과거 Commit(`50bf5bd`) 대비 Story 수(24, 현재 40)·소스 동일성 스냅샷 → **기존(오래된 스냅샷 테스트)**. 행동 검사는 모두 PASS |
| `overview-firefox` | 9/9 | — |
| `dropdown-consolidation` | 223 PASS / 5 FAIL | FAIL 5 = `c165753` 대비 Story 수·소스·`git diff` 스냅샷 → **기존** |
| `home-menu-integration` | 22/23 | FAIL 1 `without homeMenu: logo click…` → **기존**(이전 보고에서 47972c5로 재현, 이번 실행도 같은 항목·같은 메시지) |
| `storybook-unused-removal` | 93 중 FAIL 5 | **기존**(10-19 inventory·source 스냅샷, 이전 보고와 같은 5건) |
| `range-cross-browser`, `property-fields`, `property-close` | 미실행 | **기존** — 삭제된 Story(`sw-header--property-panel`, `--property-fields`)를 엶. 속성창 동작은 `footer-popup-viewer-refinement`·`integrated-improvement` popup·`overview`가 대신 검사 |
| `typecheck`(workspace), `build:sw`, `build-storybook`, `check:ai-docs`, `ai-docs.check` 37/37 | PASS | — |
글꼴 변경으로 새로 생긴 실패: 0건(`그리기모드` 잘림은 테스트 실패가 아니라 측정으로 발견해 수정). 스냅샷 테스트는 삭제·완화하지 않았습니다 — 최신 Story 구조로 기준을 다시 잡으려면 별도 승인이 필요합니다(기준 스냅샷 교체 = QA 기준 변경).
## 7. 미검증 · 남은 항목
- REVIEW REQUIRED: Header 고정 폭 값 칸의 0.3~1.5px 합성 Bold 초과(`Standard`, `0_Layer_Cludmark`, `1.00`), Footer `POLYGON`/`WIPEOUT` 잘림 — 굵기 정책(700) 또는 Figma 칸 폭 결정 필요.
- **미검증:** 돋움이 없는 macOS·Linux는 Malgun Gothic → Apple SD Gothic Neo → sans-serif로 대체(실기기 미검증).
- **미실행:** `viewer-regression.browser.mjs`(기준선 픽셀 비교). 이 테스트는 변경 전(base)과 변경 후 Storybook 두 개를 받아 `.hm-sw-header`·`.hm-sw-property` 요소를 픽셀 단위로 비교합니다. 이번 변경은 글꼴 자체를 바꾸므로 base(Noto) 대비 모든 텍스트 픽셀이 달라지는 것이 의도된 결과이고, 실행하려면 `454472d` 기준 Storybook을 별도로 빌드해 띄워야 합니다(같은 `dist`를 쓰는 build 동시 실행 금지). 픽셀 동일성 대신 같은 페이지 Noto 주입 비교(§2)·계산값·화면 캡처로 레이아웃 차이를 확인했습니다.
- **별도 개선 대상(이번 범위 밖, 원본 수정 금지):** 소비 프로젝트의 ① 화면 루트 `className="hm-sw-theme"` 직접 사용(→ `<SWTheme>`) ② Web `Progress`를 허용 지점 밖에서 사용 ③ Web 시맨틱 토큰·`--hm-font-family-base`·`body` 글꼴 재정의.
- 원본 `HMDesignSwTest-viewer`는 무변경 상태를 유지합니다.
- Commit 분리 계획(승인 후): ① `feat(sw): default font Dotum` — `sw.css`·`sw-footer.css` ② `test(sw): theme / consumer tests for the Dotum default` — 테스트 2개·`sw-theme.stories.tsx`·`footer-design-review` ③ `docs: SW Dotum / Web Noto font rule` — AI 문서·README·사본 ④ `docs(sw): Dotum QA evidence` — 이 보고서·`sw-dotum-font-qa/`.
Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

@@ -0,0 +1,263 @@
{
"base": "http://127.0.0.1:5391",
"engine": "chromium",
"loads": {
"simple.dxf": {
"status": "ready",
"ms": 1199,
"colors": 52,
"nonBg": 0.0182,
"name": "simple.dxf",
"tabs": 0
},
"BasicSample.dwg": {
"status": "ready",
"ms": 1365,
"colors": 118,
"nonBg": 0.0446,
"name": "BasicSample.dwg",
"tabs": 2
},
"civil.dwg": {
"status": "ready",
"ms": 1829,
"colors": 420,
"nonBg": 0.1904,
"name": "civil.dwg",
"tabs": 2
}
},
"results": [
{
"name": "Font: SWViewerHeader text = Dotum (SW default)",
"result": "PASS",
"detail": {
"Dotum": 20
}
},
{
"name": "Font: rendered platform font in header = Dotum (installed, no fallback)",
"result": "PASS",
"detail": {
"Dotum": 102
}
},
{
"name": "Theme: SW token --hm-sw-header-font-family = Dotum stack",
"result": "PASS",
"detail": {
"font": "Dotum, \"돋움\", \"Malgun Gothic\", \"Apple SD Gothic Neo\", sans-serif",
"bg": "rgba(0, 0, 0, 0)"
}
},
{
"name": "Web UI token --hm-font-family-base unchanged (Noto Sans KR)",
"result": "PASS",
"detail": "\"Noto Sans KR\", \"Malgun Gothic\", \"Apple SD Gothic Neo\", sans-serif"
},
{
"name": "Load simple.dxf: status ready + drawing pixels",
"result": "PASS",
"detail": {
"status": "ready",
"ms": 1199,
"colors": 52,
"nonBg": 0.0182,
"name": "simple.dxf",
"tabs": 0
}
},
{
"name": "Load BasicSample.dwg: status ready + drawing pixels",
"result": "PASS",
"detail": {
"status": "ready",
"ms": 1365,
"colors": 118,
"nonBg": 0.0446,
"name": "BasicSample.dwg",
"tabs": 2
}
},
{
"name": "Load civil.dwg: status ready + drawing pixels",
"result": "PASS",
"detail": {
"status": "ready",
"ms": 1829,
"colors": 420,
"nonBg": 0.1904,
"name": "civil.dwg",
"tabs": 2
}
},
{
"name": "Viewer: wheel zoom changes the drawing",
"result": "PASS",
"detail": "0.316"
},
{
"name": "Viewer: drag pan changes the view",
"result": "PASS",
"detail": "0.323"
},
{
"name": "Viewer: F (fit) restores the full view",
"result": "PASS",
"detail": "0.002 < 0.327"
},
{
"name": "Header: space tab switch (inactive → active) re-renders the canvas",
"result": "PASS",
"detail": "2 tabs, now Model17,377"
},
{
"name": "Header: 샘플 dropdown opens (SWViewerMenu) with Dotum",
"result": "PASS",
"detail": {
"Dotum": 6
}
},
{
"name": "Header: Escape closes the dropdown",
"result": "PASS",
"detail": ""
},
{
"name": "Header: sample menu loads simple.dxf",
"result": "PASS",
"detail": "simple.dxf / ready"
},
{
"name": "Viewer: 2.5D switch toggles and re-renders",
"result": "PASS",
"detail": "0.0217"
},
{
"name": "Panel: 설정 opens SWViewerPanel",
"result": "PASS",
"detail": ""
},
{
"name": "Panel: text = Dotum (program list cells keep their monospace)",
"result": "PASS",
"detail": {
"Dotum": 25
}
},
{
"name": "Panel: SWViewerSlider changes value and syncs the number input",
"result": "PASS",
"detail": "1 → 1.2, input 1.2"
},
{
"name": "Panel: SWViewerSwitch toggles (그리드)",
"result": "PASS",
"detail": "false → true"
},
{
"name": "Panel: title drag moves the panel",
"result": "PASS",
"detail": "(904,56) → (704,168)"
},
{
"name": "Panel: resize grip changes size",
"result": "PASS",
"detail": "340×520 → 413×353"
},
{
"name": "Panel: body scrolls vertically, no horizontal overflow",
"result": "PASS",
"detail": {
"scrollable": true,
"before": 0,
"after": 207,
"overflowX": false
}
},
{
"name": "Panel: no clipped text after Dotum",
"result": "PASS",
"detail": []
},
{
"name": "Panel: closes (Escape)",
"result": "PASS",
"detail": ""
},
{
"name": "Panel: 레이어 opens with layer rows",
"result": "PASS",
"detail": "2 rows"
},
{
"name": "Panel: 정보 (modal) opens and Escape closes it",
"result": "PASS",
"detail": "open=true"
},
{
"name": "Responsive 1920: header/page no horizontal overflow",
"result": "PASS",
"detail": {
"overflow": false,
"doc": false,
"more": false
}
},
{
"name": "Responsive 1180: header/page no horizontal overflow",
"result": "PASS",
"detail": {
"overflow": false,
"doc": false,
"more": false
}
},
{
"name": "Responsive 900: header/page no horizontal overflow (More shown)",
"result": "PASS",
"detail": {
"overflow": false,
"doc": false,
"more": true
}
},
{
"name": "Responsive 900: More opens with collapsed items",
"result": "PASS",
"detail": "5 items"
},
{
"name": "Responsive 560: header/page no horizontal overflow (More shown)",
"result": "PASS",
"detail": {
"overflow": false,
"doc": false,
"more": true
}
},
{
"name": "Responsive 375: header/page no horizontal overflow (More shown)",
"result": "PASS",
"detail": {
"overflow": false,
"doc": false,
"more": true
}
},
{
"name": "Responsive 375: More opens with collapsed items",
"result": "PASS",
"detail": "8 items"
},
{
"name": "Console / page / HTTP errors: none (favicon.ico 404 = program has no icon, pre-existing)",
"result": "PASS",
"detail": {
"errors": [],
"favicon404": 0
}
}
],
"errors": []
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 286 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

@@ -0,0 +1,128 @@
{
"base": "http://127.0.0.1:5391",
"version": "158.0",
"results": [
{
"name": "Firefox 1400: civil.dwg loads (status)",
"result": "PASS",
"data": "ready"
},
{
"name": "Firefox 1400: Dotum resolves to an installed face (width differs from fallbacks)",
"result": "PASS",
"data": {
"dotum": 170,
"malgun": 162.3,
"mono": 168
}
},
{
"name": "Firefox 1400: SWViewerHeader computed font = Dotum",
"result": "PASS",
"data": {
"Dotum": 15
}
},
{
"name": "Firefox 1400: no horizontal overflow",
"result": "PASS",
"data": {
"header": 0,
"page": 0,
"more": false,
"h": 52
}
},
{
"name": "Firefox 1400: header menu opens (Dotum)",
"result": "PASS",
"data": {
"items": 3,
"font": "Dotum"
}
},
{
"name": "Firefox 1400: Escape closes the menu",
"result": "PASS"
},
{
"name": "Firefox 1400: options SWViewerPanel opens, Dotum, scrollable body, no clipped text",
"result": "PASS",
"data": {
"opened": "toggle",
"panel": {
"w": 340,
"h": 520,
"font": "Dotum",
"scroll": true,
"clipped": 0,
"inView": true
}
}
},
{
"name": "Firefox 500: civil.dwg loads (status)",
"result": "PASS",
"data": "ready"
},
{
"name": "Firefox 500: Dotum resolves to an installed face (width differs from fallbacks)",
"result": "PASS",
"data": {
"dotum": 170,
"malgun": 162.3,
"mono": 168
}
},
{
"name": "Firefox 500: SWViewerHeader computed font = Dotum",
"result": "PASS",
"data": {
"Dotum": 3
}
},
{
"name": "Firefox 500: no horizontal overflow",
"result": "PASS",
"data": {
"header": 0,
"page": 0,
"more": true,
"h": 52
}
},
{
"name": "Firefox 500: header menu opens (Dotum)",
"result": "PASS",
"data": {
"items": 10,
"font": "Dotum"
}
},
{
"name": "Firefox 500: Escape closes the menu",
"result": "PASS"
},
{
"name": "Firefox 500: options SWViewerPanel opens, Dotum, scrollable body, no clipped text",
"result": "PASS",
"data": {
"opened": "more",
"panel": {
"w": 340,
"h": 520,
"font": "Dotum",
"scroll": true,
"clipped": 0,
"inView": true
}
}
},
{
"name": "Firefox: no console errors (favicon 404 excluded)",
"result": "PASS",
"data": []
}
],
"errors": []
}
@@ -0,0 +1,396 @@
diff --git a/README.md b/README.md
index 06a943a..648c5fb 100644
--- a/README.md
+++ b/README.md
@@ -124,7 +124,7 @@ import { OrgChart } from "@hm-design/org-chart-react" // Core: @hm-design/org-ch
별도 React 앱은 [Tailwind v4 검색 범위 가이드](docs/guidelines/runtime-portability.md#21-tailwind-v4-소비자-검색-범위)를 확인합니다. `source("./")`는 CSS 위치에 따라 범위가 달라지며 HM `tailwind.css`의 명시 source를 유지해야 합니다. 공개 package Theme는 동봉된 `dist/fonts/`를 상대 URL로 참조합니다. 개발 저장소·포터블 ZIP·React 소비자·단일 HTML의 차이는 [폰트·Asset 경로](docs/guidelines/runtime-portability.md#41-noto-sans-kr-경로-실행-환경별-확인)를 따릅니다.
-SW는 Tailwind 없이 앱 진입점에서 `import "@hm-design/sw/styles.css"`를 한 번 추가합니다. 한 화면에서는 SW 일반 모드와 뷰어 모드 중 하나를 고르고, 글꼴 등 토큰은 가장 바깥 `<SWTheme style>`에서 바꿉니다([SW 사용 안내](packages/sw/ai/AI_USAGE.md)). SW 기본 글꼴은 Noto Sans KR이며 Figma의 Dotum을 기본값으로 쓸지는 디자인 승인 대기입니다. OrgChart는 Core CSS 두 개(`@hm-design/org-chart/engine.css`, `/style.css`)의 URL을 `stylesheetUrls`로 전달합니다(Shadow DOM, [OrgChart React README](packages/org-chart-react/README.md)).
+SW는 Tailwind 없이 앱 진입점에서 `import "@hm-design/sw/styles.css"`를 한 번 추가합니다. 한 화면에서는 SW 일반 모드와 뷰어 모드 중 하나를 고르고, 글꼴 등 토큰은 가장 바깥 `<SWTheme style>`에서 바꿉니다([SW 사용 안내](packages/sw/ai/AI_USAGE.md)). SW 기본 글꼴은 돋움(Dotum, 설치된 시스템 글꼴)이고 Web UI 기본 글꼴은 Noto Sans KR입니다. 서로의 글꼴 설정을 복사하지 않습니다. OrgChart는 Core CSS 두 개(`@hm-design/org-chart/engine.css`, `/style.css`)의 URL을 `stylesheetUrls`로 전달합니다(Shadow DOM, [OrgChart React README](packages/org-chart-react/README.md)).
화면 생성 Reference: [Navigation 선택 근거](docs/guidelines/navigation-single-mode.md#선택-근거), [GNB Desktop·Mobile 구성](docs/patterns/gnb.md#8-desktop--mobile)과 [내부 Sidebar](docs/patterns/gnb.md#15-gnb-only-sidebar-composition-2026-10-08), [FilterBar 조회·초기화 소비 예제](docs/patterns/filter-bar.md#61-조회-버튼으로-적용하는-소비-예제). 일반 업무 목록의 모드를 임의 확정하거나 FilterBar에 조회 API가 있다고 가정하지 않습니다.
diff --git a/docs/ai/AI_GUIDE.md b/docs/ai/AI_GUIDE.md
index 8ac07f4..5fd7e42 100644
--- a/docs/ai/AI_GUIDE.md
+++ b/docs/ai/AI_GUIDE.md
@@ -138,7 +138,7 @@
혼합 규칙:
-1. 영역마다 하나의 패키지를 정하고 그 영역의 신규 UI는 그 패키지의 토큰만 읽습니다. Web 토큰(`--hm-sem-*`)을 SW 영역에, SW 토큰(`--hm-sw-*`)을 Web 영역에 쓰지 않습니다. OrgChart 내부는 `--hm-orgchart-*`만 씁니다.
+1. 영역마다 하나의 패키지를 정하고 그 영역의 신규 UI는 그 패키지의 토큰만 읽습니다. Web 토큰(`--hm-sem-*`)을 SW 영역에, SW 토큰(`--hm-sw-*`)을 Web 영역에 쓰지 않습니다. OrgChart 내부는 `--hm-orgchart-*`만 씁니다. 글꼴도 같습니다: SW 기본 글꼴은 돋움(Dotum, `--hm-sw-header-font-family`), Web 기본 글꼴은 Noto Sans KR(`--hm-font-family-base`), OrgChart는 자기 설정을 유지합니다. 한 패키지의 글꼴 값을 다른 영역에 복사하지 않습니다.
2. 다른 패키지 컴포넌트는 **문서에 허용된 지점에서만** 씁니다.
- SW 일반 모드 `SWPopup`의 `children` 안 Web 컨트롤(SW 카탈로그가 허용, 예: Popup 하단 `Button`)
- SW 뷰어 모드 `SWViewerPanel`의 `children` 안 Web 컨트롤 — `SWViewer*` 컨트롤로 안 될 때만(SW `AI_USAGE.md` §0.4)
diff --git a/packages/org-chart-react/ai/AI_GUIDE.md b/packages/org-chart-react/ai/AI_GUIDE.md
index 8ac07f4..5fd7e42 100644
--- a/packages/org-chart-react/ai/AI_GUIDE.md
+++ b/packages/org-chart-react/ai/AI_GUIDE.md
@@ -138,7 +138,7 @@
혼합 규칙:
-1. 영역마다 하나의 패키지를 정하고 그 영역의 신규 UI는 그 패키지의 토큰만 읽습니다. Web 토큰(`--hm-sem-*`)을 SW 영역에, SW 토큰(`--hm-sw-*`)을 Web 영역에 쓰지 않습니다. OrgChart 내부는 `--hm-orgchart-*`만 씁니다.
+1. 영역마다 하나의 패키지를 정하고 그 영역의 신규 UI는 그 패키지의 토큰만 읽습니다. Web 토큰(`--hm-sem-*`)을 SW 영역에, SW 토큰(`--hm-sw-*`)을 Web 영역에 쓰지 않습니다. OrgChart 내부는 `--hm-orgchart-*`만 씁니다. 글꼴도 같습니다: SW 기본 글꼴은 돋움(Dotum, `--hm-sw-header-font-family`), Web 기본 글꼴은 Noto Sans KR(`--hm-font-family-base`), OrgChart는 자기 설정을 유지합니다. 한 패키지의 글꼴 값을 다른 영역에 복사하지 않습니다.
2. 다른 패키지 컴포넌트는 **문서에 허용된 지점에서만** 씁니다.
- SW 일반 모드 `SWPopup`의 `children` 안 Web 컨트롤(SW 카탈로그가 허용, 예: Popup 하단 `Button`)
- SW 뷰어 모드 `SWViewerPanel`의 `children` 안 Web 컨트롤 — `SWViewer*` 컨트롤로 안 될 때만(SW `AI_USAGE.md` §0.4)
diff --git a/packages/org-chart/ai/AI_GUIDE.md b/packages/org-chart/ai/AI_GUIDE.md
index 8ac07f4..5fd7e42 100644
--- a/packages/org-chart/ai/AI_GUIDE.md
+++ b/packages/org-chart/ai/AI_GUIDE.md
@@ -138,7 +138,7 @@
혼합 규칙:
-1. 영역마다 하나의 패키지를 정하고 그 영역의 신규 UI는 그 패키지의 토큰만 읽습니다. Web 토큰(`--hm-sem-*`)을 SW 영역에, SW 토큰(`--hm-sw-*`)을 Web 영역에 쓰지 않습니다. OrgChart 내부는 `--hm-orgchart-*`만 씁니다.
+1. 영역마다 하나의 패키지를 정하고 그 영역의 신규 UI는 그 패키지의 토큰만 읽습니다. Web 토큰(`--hm-sem-*`)을 SW 영역에, SW 토큰(`--hm-sw-*`)을 Web 영역에 쓰지 않습니다. OrgChart 내부는 `--hm-orgchart-*`만 씁니다. 글꼴도 같습니다: SW 기본 글꼴은 돋움(Dotum, `--hm-sw-header-font-family`), Web 기본 글꼴은 Noto Sans KR(`--hm-font-family-base`), OrgChart는 자기 설정을 유지합니다. 한 패키지의 글꼴 값을 다른 영역에 복사하지 않습니다.
2. 다른 패키지 컴포넌트는 **문서에 허용된 지점에서만** 씁니다.
- SW 일반 모드 `SWPopup`의 `children` 안 Web 컨트롤(SW 카탈로그가 허용, 예: Popup 하단 `Button`)
- SW 뷰어 모드 `SWViewerPanel`의 `children` 안 Web 컨트롤 — `SWViewer*` 컨트롤로 안 될 때만(SW `AI_USAGE.md` §0.4)
diff --git a/packages/sw/ai/AI_GUIDE.md b/packages/sw/ai/AI_GUIDE.md
index 8ac07f4..5fd7e42 100644
--- a/packages/sw/ai/AI_GUIDE.md
+++ b/packages/sw/ai/AI_GUIDE.md
@@ -138,7 +138,7 @@
혼합 규칙:
-1. 영역마다 하나의 패키지를 정하고 그 영역의 신규 UI는 그 패키지의 토큰만 읽습니다. Web 토큰(`--hm-sem-*`)을 SW 영역에, SW 토큰(`--hm-sw-*`)을 Web 영역에 쓰지 않습니다. OrgChart 내부는 `--hm-orgchart-*`만 씁니다.
+1. 영역마다 하나의 패키지를 정하고 그 영역의 신규 UI는 그 패키지의 토큰만 읽습니다. Web 토큰(`--hm-sem-*`)을 SW 영역에, SW 토큰(`--hm-sw-*`)을 Web 영역에 쓰지 않습니다. OrgChart 내부는 `--hm-orgchart-*`만 씁니다. 글꼴도 같습니다: SW 기본 글꼴은 돋움(Dotum, `--hm-sw-header-font-family`), Web 기본 글꼴은 Noto Sans KR(`--hm-font-family-base`), OrgChart는 자기 설정을 유지합니다. 한 패키지의 글꼴 값을 다른 영역에 복사하지 않습니다.
2. 다른 패키지 컴포넌트는 **문서에 허용된 지점에서만** 씁니다.
- SW 일반 모드 `SWPopup`의 `children` 안 Web 컨트롤(SW 카탈로그가 허용, 예: Popup 하단 `Button`)
- SW 뷰어 모드 `SWViewerPanel`의 `children` 안 Web 컨트롤 — `SWViewer*` 컨트롤로 안 될 때만(SW `AI_USAGE.md` §0.4)
diff --git a/packages/sw/ai/AI_USAGE.md b/packages/sw/ai/AI_USAGE.md
index cb50552..b09a057 100644
--- a/packages/sw/ai/AI_USAGE.md
+++ b/packages/sw/ai/AI_USAGE.md
@@ -102,8 +102,9 @@ import "@hm-design/sw/styles.css" // 앱 진입점에서 한 번
- **금지:** `@hm-design/sw/src/...`, `@hm-design/sw/dist/components/...` 같은 내부 경로 Import. `dist`에 내부 모듈의 `.d.ts`가 보여도 공개 API가 아니다.
- Peer: `react`, `react-dom` `^19.0.0`. 런타임 dependency 없음. `@hm-design/ui`·조직도 패키지와 무관하다.
- SVG·PNG 자산은 JS에 data URI로 포함되어 별도 설정이 없다.
-- 글꼴 파일은 포함하지 않는다. 앱에서 Noto Sans KR(400/500/700)을 로드한다(없으면 Malgun Gothic → Apple SD Gothic Neo).
-- SW 기본 글꼴은 Noto Sans KR이다(Figma는 Dotum). **Dotum을 기본으로 쓸지는 디자인 승인 대기**이므로 AI가 임의로 Dotum을 적용하지 않는다. 프로그램(사용자)이 글꼴을 정한 경우에만 §3.1 방법으로 `--hm-sw-header-font-family`를 바꾸고, 결과 보고에 "글꼴 변경 — 디자인 승인 대기 항목"으로 적는다.
+- SW 기본 글꼴은 돋움(Dotum)이다(`--hm-sw-header-font-family: Dotum, "돋움", "Malgun Gothic", "Apple SD Gothic Neo", sans-serif`, Figma와 같음). 설치된 시스템 글꼴(Windows)을 쓰며 패키지는 글꼴 파일을 포함하지 않는다. 돋움이 없는 환경은 Malgun Gothic → Apple SD Gothic Neo로 대체된다. 앱이 별도 글꼴 파일을 로드할 필요는 없다.
+- SW 화면은 `SWTheme`(또는 SW 컴포넌트 루트)와 SW 토큰의 글꼴을 그대로 쓴다. Web UI의 기본 글꼴(Noto Sans KR, `--hm-font-family-base`)이나 Web `theme.css`의 글꼴 설정을 SW 화면에 복사하지 않고, SW 컴포넌트에 `font-family`를 개별 지정하지 않는다. 프로그램(사용자)이 다른 글꼴을 정한 경우에만 §3.1 방법으로 `--hm-sw-header-font-family`를 바꾸고 결과 보고에 "글꼴 변경"으로 적는다.
+- 돋움에는 Bold 글꼴이 없어 700은 브라우저가 합성 Bold로 그리며 글자당 약 1px 넓어진다. Figma 고정 폭 칸(예: 가중치·스케일 38px, 레이어 값, 문자/치수스타일)에 긴 값이 들어가면 말줄임이 된다.
- CSS는 전역(`html`, `body`, `*`)을 건드리지 않는다. `body` margin 등 페이지 기본값은 소비 앱이 정한다.
- 스크롤바: SW 전용 스크롤바 디자인은 없다. 기존 SW 컴포넌트는 브라우저 기본 스크롤바를 쓰며(속성Bar만 `scrollbar-width: thin`), Popup 본문 스크롤은 `SWPopup`이 처리한다. 새 스크롤 영역에 임의 스크롤바 색·두께를 만들지 않는다.
- TypeScript에서 CSS side-effect import 오류가 나면 Vite의 `vite/client` 타입을 포함한다.
@@ -122,7 +123,7 @@ SW 토큰(`--hm-sw-header-*`, `--hm-sw-property-*`, `--hm-sw-viewer-*`, `--hm-sw
1. 화면 전체(Header·Panel·Menu가 같은 값)를 바꾸려면 화면을 `<SWTheme style={theme}>` 하나로 감싸고 거기서만 토큰을 정합니다. 프로그램 class(`<SWTheme className="app-sw-theme">` + `.app-sw-theme { --hm-sw-header-font-family: … }`)도 됩니다.
```tsx
- const appSWTheme = { "--hm-sw-header-font-family": '"Noto Sans KR", sans-serif' } as CSSProperties
+ const appSWTheme = { "--hm-sw-header-font-family": '"Malgun Gothic", sans-serif' } as CSSProperties // 프로그램이 정한 값만
<SWTheme style={appSWTheme}>
<SWViewerHeader … /> {/* Dropdown·More 포함 */}
<SWViewerPanel …>…</SWViewerPanel>
diff --git a/packages/sw/ai/COMPOSITION_PATTERNS.md b/packages/sw/ai/COMPOSITION_PATTERNS.md
index 891e8f9..ad08596 100644
--- a/packages/sw/ai/COMPOSITION_PATTERNS.md
+++ b/packages/sw/ai/COMPOSITION_PATTERNS.md
@@ -235,7 +235,7 @@ const sections: SWHomeMenuSectionData[] = [
일반·뷰어 모드 공통입니다. 토큰 기본값은 가장 바깥 SW 범위에서만 선언되고 안쪽 SW 요소는 상속합니다([AI_USAGE.md](./AI_USAGE.md) §3.1).
```tsx
-const appSWTheme = { "--hm-sw-header-font-family": '"Noto Sans KR", sans-serif' } as CSSProperties // 프로그램이 정한 값만
+const appSWTheme = { "--hm-sw-header-font-family": '"Malgun Gothic", sans-serif' } as CSSProperties // 프로그램이 정한 값만
<SWTheme style={appSWTheme}> {/* 가장 바깥 범위: 여기서만 지정 */}
<SWViewerHeader … /> {/* Dropdown·More까지 상속 */}
@@ -246,7 +246,7 @@ const appSWTheme = { "--hm-sw-header-font-family": '"Noto Sans KR", sans-serif'
```
- 일반 모드도 같습니다: `<SWTheme style={appSWTheme}>` 안의 `SWHeader`(Dropdown·창 이동 Tooltip)·`SWFooter`(`SWFooterCommandLine`·명령 등록 안내)가 같은 값을 씁니다.
-- 기본 글꼴은 Noto Sans KR입니다. Dotum 기본 적용은 디자인 승인 대기이므로 AI가 임의로 Dotum을 넣지 않습니다.
+- 기본 글꼴은 돋움(Dotum)입니다. 기본값을 쓸 때는 글꼴 토큰을 지정하지 않습니다. Web UI 글꼴(Noto Sans KR)을 SW 화면에 넣지 않습니다.
- `hm-sw-*` class 선택자로 토큰을 덮거나 `!important`, 컴포넌트마다 같은 값 반복 지정을 하지 않습니다.
## 9. 하지 말 것
diff --git a/packages/sw/ai/DESIGN_RULES.md b/packages/sw/ai/DESIGN_RULES.md
index 85ac0be..437eda1 100644
--- a/packages/sw/ai/DESIGN_RULES.md
+++ b/packages/sw/ai/DESIGN_RULES.md
@@ -44,7 +44,7 @@
| 항목 | 값 |
|---|---|
-| 글꼴 | Noto Sans KR → Malgun Gothic → Apple SD Gothic Neo (`--hm-sw-header-font-family`, Figma Dotum 대체 — 현재 패키지 기본값). 폰트 파일은 앱이 로드. **Dotum 기본 적용 여부는 디자인 승인 대기**: 기본값을 바꾸지 않으며, 프로그램이 정한 경우에만 [AI_USAGE.md](./AI_USAGE.md) §3.1 방법으로 변경 |
+| 글꼴 | 돋움(Dotum) → Malgun Gothic → Apple SD Gothic Neo (`--hm-sw-header-font-family: Dotum, "돋움", "Malgun Gothic", "Apple SD Gothic Neo", sans-serif`, Figma와 같음, 2026-10-20). 설치된 시스템 글꼴을 쓰며 글꼴 파일은 포함하지 않음. Web UI 기본 글꼴(Noto Sans KR)과 별개. 다른 글꼴은 프로그램이 정한 경우에만 [AI_USAGE.md](./AI_USAGE.md) §3.1 방법으로 변경. 돋움 700은 합성 Bold(글자당 약 +1px) |
| 기본 / 라벨 | 14px / 12px (`--hm-sw-header-font-size` / `--hm-sw-header-label-size`) |
| Weight | 400, 500, 700만 사용(600 없음). 값·제목·토글 700 |
| 자간 | 값 0.04em, 라벨 0.02em, 파일명 0.06em |
@@ -180,7 +180,7 @@ Container `hm-sw-header` 기준 Breakpoint: **< 1800** 선/문자/치수스타
## 13. Footer (`SWFooter*`, Figma 26:10097) — SW 일반 모드 전용
-원본 `src/theme/sw-footer.css`. 토큰은 `--hm-sw-footer-*`(`.hm-sw-header`, `.hm-sw-theme` 범위). 값은 Figma Plugin API로 읽은 값입니다(2026-10-20). 글꼴은 Header와 같이 Dotum 대신 Noto Sans KR, 글자 외곽선은 Header 토큰(`--hm-sw-header-text-outline` 1.3px / `--hm-sw-header-label-outline` 1px)을 공유하고, Figma의 자기 색 0.3 / 0.4px stroke는 Header 2026-10-16 수정과 같이 그리지 않습니다.
+원본 `src/theme/sw-footer.css`. 토큰은 `--hm-sw-footer-*`(`.hm-sw-header`, `.hm-sw-theme` 범위). 값은 Figma Plugin API로 읽은 값입니다(2026-10-20). 글꼴은 Header와 같은 SW 기본 글꼴(돋움), 글자 외곽선은 Header 토큰(`--hm-sw-header-text-outline` 1.3px / `--hm-sw-header-label-outline` 1px)을 공유하고, Figma의 자기 색 0.3 / 0.4px stroke는 Header 2026-10-16 수정과 같이 그리지 않습니다.
| 항목 | 값 | 토큰 |
|---|---|---|
diff --git a/packages/sw/ai/VIEWER.md b/packages/sw/ai/VIEWER.md
index 6c76a21..4fdae42 100644
--- a/packages/sw/ai/VIEWER.md
+++ b/packages/sw/ai/VIEWER.md
@@ -101,7 +101,7 @@ const groups: SWViewerHeaderGroup[] = [
| 뷰어 Header를 `div` + `button`으로 다시 만들기, `hm-sw-viewer-*` class를 소비 코드에 붙이기 | 데이터(`groups`)와 `custom` / `trailing`으로 구성 |
| Header 버튼 글자에 `-webkit-text-stroke`·`border`로 외곽선 만들기 | 외곽선은 패키지 토큰이 이미 적용합니다 |
| 메뉴 색·간격을 `#123456`, `margin` 등 임의 값으로 덮기 | 토큰 `--hm-sw-viewer-*` / `--hm-sw-header-*`만 가장 바깥 SW 범위(`<SWTheme>` 또는 단독 컴포넌트 루트)의 `style`로 조정(기본값 유지 권장, [AI_USAGE.md](./AI_USAGE.md) §3.1) |
-| Header·Dropdown·More·Panel의 글꼴을 각각 따로 지정, `.hm-sw-viewer-menu` 등 class로 덮기 | 화면을 `<SWTheme style={theme}>` 하나로 감싸면 Header·Dropdown·More·Panel이 같은 값을 상속합니다. 글꼴 기본값은 Noto Sans KR이며 Dotum 기본 적용은 디자인 승인 대기 |
+| Header·Dropdown·More·Panel의 글꼴을 각각 따로 지정, `.hm-sw-viewer-menu` 등 class로 덮기 | 화면을 `<SWTheme style={theme}>` 하나로 감싸면 Header·Dropdown·More·Panel이 같은 값을 상속합니다. 글꼴 기본값은 돋움(Dotum)이며 Web UI 글꼴(Noto Sans KR)을 복사하지 않습니다 |
| 존재하지 않는 Props 추측(`items`, `content`, `renderBody` …) | 위 표와 `dist/index.d.ts`가 전부 |
| 일반 모드 화면에서 `SWViewerHeader` 사용, 뷰어에서 `SWHeader` 재스타일 | 모드별 Header를 바꿔 끼웁니다 |
| 기능 없는 메뉴를 가짜 동작으로 연결 | 항목 제외 또는 `disabled` + 미연결 보고 |
diff --git a/packages/sw/ai/examples/ExampleJ-Theme.tsx b/packages/sw/ai/examples/ExampleJ-Theme.tsx
index 3b1d240..91bc5e9 100644
--- a/packages/sw/ai/examples/ExampleJ-Theme.tsx
+++ b/packages/sw/ai/examples/ExampleJ-Theme.tsx
@@ -1,8 +1,8 @@
// Example J — SW theme tokens (both modes). The only official way to change SW tokens: `style` (or the program's own
// class) on the OUTERMOST SW scope. Here one <SWTheme> wraps the viewer screen, so the header, its dropdowns, More,
// and every panel read the same value. Portals leave the DOM tree: wrap their content in <SWTheme> with the same style.
-// The font below is a placeholder for a program decision: the SW default stays Noto Sans KR (a Dotum default is
-// pending design approval), so only set it when the program has decided to.
+// The font below is a placeholder for a program decision: the SW default is Dotum (2026-10-20) and needs no token,
+// so only set it when the program has decided on another font. Never copy the Web UI font (Noto Sans KR) here.
import { useState, type CSSProperties } from "react"
import { createPortal } from "react-dom"
import {
@@ -12,7 +12,7 @@ import {
/** One theme object for the screen and for every portal. Token names only (`--hm-sw-*`), never `hm-sw-*` classes. */
export const appSWTheme = {
- "--hm-sw-header-font-family": '"Noto Sans KR", "Malgun Gothic", "Apple SD Gothic Neo", sans-serif',
+ "--hm-sw-header-font-family": '"Malgun Gothic", "Apple SD Gothic Neo", sans-serif',
} as CSSProperties
export function ExampleJTheme({ onEvent }: { onEvent?: (name: string) => void }) {
diff --git a/packages/sw/src/theme/sw-footer.css b/packages/sw/src/theme/sw-footer.css
index 41f13b1..9e63565 100644
--- a/packages/sw/src/theme/sw-footer.css
+++ b/packages/sw/src/theme/sw-footer.css
@@ -1,6 +1,6 @@
/* @hm-design/sw — SW Footer (Figma "레이아웃 분리" 26:10097 bottom bar, components 26:9459 … 26:10097, read
through the Figma Plugin API 2026-10-20). Footer-only tokens. Text keeps the SW typography of sw.css
- (Noto Sans KR instead of Dotum, black OUTSIDE outline as 16 text-shadows, own-color 0.3 / 0.4px strokes removed
+ (Dotum like Figma since 2026-10-20, black OUTSIDE outline as 16 text-shadows, own-color 0.3 / 0.4px strokes removed
like the 2026-10-16 header fix). Never touches global selectors, SWHeader or SWPopup classes.
Declared on the outermost SW scope only, like sw.css: the command line inside the bar inherits the tokens. */
diff --git a/packages/sw/src/theme/sw.css b/packages/sw/src/theme/sw.css
index ad511f5..27441bb 100644
--- a/packages/sw/src/theme/sw.css
+++ b/packages/sw/src/theme/sw.css
@@ -17,8 +17,10 @@
--hm-sw-header-logo-width: 32px;
--hm-sw-header-logo-height: 17px;
- /* Typography (Figma Dotum is replaced by Noto Sans KR on purpose) */
- --hm-sw-header-font-family: "Noto Sans KR", "Malgun Gothic", "Apple SD Gothic Neo", sans-serif;
+ /* Typography: SW default is Dotum like Figma (2026-10-20). Installed system font only (Windows gulim.ttc); the
+ package ships no font file. Malgun Gothic / Apple SD Gothic Neo cover systems without Dotum. Web UI keeps
+ Noto Sans KR (its own token); this token never leaves the SW scope. */
+ --hm-sw-header-font-family: Dotum, "돋움", "Malgun Gothic", "Apple SD Gothic Neo", sans-serif;
--hm-sw-header-font-size: 14px;
--hm-sw-header-label-size: 12px;
@@ -539,7 +541,9 @@
flex: 0 1 90px;
min-width: 0;
margin-left: -1px;
- padding: 0 8px;
+ /* 4px (was 8px): Dotum has no bold face, so 700 is synthesized ~1px wider per glyph ("그리기모드" 77.8px);
+ the centered label fits the Figma 90px cell again. */
+ padding: 0 4px;
overflow: hidden;
text-align: center;
white-space: nowrap;
diff --git a/packages/sw/tests/ai-template-consumer.browser.mjs b/packages/sw/tests/ai-template-consumer.browser.mjs
index b4b1abf..ad917cc 100644
--- a/packages/sw/tests/ai-template-consumer.browser.mjs
+++ b/packages/sw/tests/ai-template-consumer.browser.mjs
@@ -41,7 +41,7 @@ await page.evaluate(() => document.fonts.ready)
const assets = await page.evaluate(() => [...document.images].map(image => ({ src: image.currentSrc.slice(0, 30), ok: image.complete && image.naturalWidth > 0 })))
check("1 all SVG/PNG assets decode (data URI, no external path)", assets.length > 0 && assets.every(item => item.ok && item.src.startsWith("data:")), { count: assets.length, broken: assets.filter(item => !item.ok) })
const tokens = await page.evaluate(() => { const s = getComputedStyle(document.querySelector('[data-example="b"] .hm-sw-theme')); return { height: s.getPropertyValue("--hm-sw-header-height").trim(), font: s.fontFamily } })
-check("1 styles.css loaded; SWTheme provides tokens", tokens.height === "49px" && tokens.font.includes("Noto Sans KR"), tokens)
+check("1 styles.css loaded; SWTheme provides tokens", tokens.height === "49px" && tokens.font.startsWith("Dotum"), tokens)
// 2. Example A: default header unchanged (Figma 1920 coordinates)
const a = section("a")
diff --git a/packages/sw/tests/theme-inheritance.browser.mjs b/packages/sw/tests/theme-inheritance.browser.mjs
index 007855e..1e6ebab 100644
--- a/packages/sw/tests/theme-inheritance.browser.mjs
+++ b/packages/sw/tests/theme-inheritance.browser.mjs
@@ -1,7 +1,7 @@
// SW theme token inheritance (2026-10-20, A-1).
// 1) SW/Theme › Theme Inheritance: a token set through `style` on the outermost SW scope reaches the header, dropdowns,
// More, panels, footer command line and tooltips; portals get it only when wrapped in a themed <SWTheme>; areas do
-// not mix; unthemed components keep Noto Sans KR. Dotum is a verification value only (not the SW default).
+// not mix; unthemed components keep the SW default Dotum (2026-10-20). Noto Sans KR is a verification value only.
// 2) Regression: every existing SW Story renders identically with the new cascade and with the legacy cascade
// (token blocks re-declared on every `.hm-sw-header, .hm-sw-theme`, i.e. the code before this change): computed
// font / color / geometry of every SW element and an element screenshot comparison. No Story sets an override,
@@ -22,9 +22,9 @@ const [storybook = 'http://127.0.0.1:6024', outArg] = process.argv.slice(2)
const out = path.resolve(outArg ?? 'docs/sw/theme-inheritance-qa')
await mkdir(out, { recursive: true })
-const VERIFY = 'Dotum, 돋움, sans-serif'
+const VERIFY = '"Noto Sans KR", sans-serif'
const NESTED = '"Malgun Gothic", sans-serif'
-const DEFAULT = '"Noto Sans KR", "Malgun Gothic", "Apple SD Gothic Neo", sans-serif'
+const DEFAULT = 'Dotum, 돋움, "Malgun Gothic", "Apple SD Gothic Neo", sans-serif'
const results = []
const check = (name, pass, detail = '') => { results.push({ name, result: pass ? 'PASS' : 'FAIL', detail }); console.log(`${pass ? 'PASS' : 'FAIL'} ${name}${detail ? ` — ${detail}` : ''}`) }
const errors = []
@@ -67,52 +67,52 @@ const fmt = map => Object.entries(map).map(([family, count]) => `${count}× ${fa
// Default (no theme): header, then its sample dropdown and More.
const def = scope('default')
- check('기본: 단독 SWViewerHeader = Noto Sans KR', only(await fonts(page, `${def} .hm-sw-viewer-header`), DEFAULT), fmt(await fonts(page, `${def} .hm-sw-viewer-header`)))
+ check('기본: 단독 SWViewerHeader = 기본 Dotum', only(await fonts(page, `${def} .hm-sw-viewer-header`), DEFAULT), fmt(await fonts(page, `${def} .hm-sw-viewer-header`)))
await page.locator(`${def} .hm-sw-viewer-header [aria-haspopup="menu"]`).first().click()
await page.waitForSelector(`${def} .hm-sw-viewer-menu`)
- check('기본: Dropdown = Noto Sans KR', only(await fonts(page, `${def} .hm-sw-viewer-menu`), DEFAULT), fmt(await fonts(page, `${def} .hm-sw-viewer-menu`)))
+ check('기본: Dropdown = 기본 Dotum', only(await fonts(page, `${def} .hm-sw-viewer-menu`), DEFAULT), fmt(await fonts(page, `${def} .hm-sw-viewer-menu`)))
await page.keyboard.press('Escape')
await page.locator(`${def} .hm-sw-viewer-header button[aria-label="추가 도구"]`).click()
await page.waitForSelector(`${def} .hm-sw-viewer-menu[data-surface="beige"]`)
- check('기본: More = Noto Sans KR', only(await fonts(page, `${def} .hm-sw-viewer-menu`), DEFAULT), fmt(await fonts(page, `${def} .hm-sw-viewer-menu`)))
+ check('기본: More = 기본 Dotum', only(await fonts(page, `${def} .hm-sw-viewer-menu`), DEFAULT), fmt(await fonts(page, `${def} .hm-sw-viewer-menu`)))
await page.keyboard.press('Escape')
// Viewer, themed through <SWTheme style>.
const viewer = scope('viewer-themed')
- check('뷰어 테마: SWViewerHeader 전체 = Dotum', only(await fonts(page, `${viewer} .hm-sw-viewer-header`), VERIFY), fmt(await fonts(page, `${viewer} .hm-sw-viewer-header`)))
+ check('뷰어 테마: SWViewerHeader 전체 = 검증 글꼴', only(await fonts(page, `${viewer} .hm-sw-viewer-header`), VERIFY), fmt(await fonts(page, `${viewer} .hm-sw-viewer-header`)))
await page.locator(`${viewer} .hm-sw-viewer-header [aria-haspopup="menu"]`).first().click()
await page.waitForSelector(`${viewer} .hm-sw-viewer-menu`)
- check('뷰어 테마: Dropdown = Dotum', only(await fonts(page, `${viewer} .hm-sw-viewer-menu`), VERIFY), fmt(await fonts(page, `${viewer} .hm-sw-viewer-menu`)))
+ check('뷰어 테마: Dropdown = 검증 글꼴', only(await fonts(page, `${viewer} .hm-sw-viewer-menu`), VERIFY), fmt(await fonts(page, `${viewer} .hm-sw-viewer-menu`)))
await page.keyboard.press('Escape')
await page.locator(`${viewer} .hm-sw-viewer-header button[aria-label="추가 도구"]`).click()
await page.waitForSelector(`${viewer} .hm-sw-viewer-menu[data-surface="beige"]`)
- check('뷰어 테마: More = Dotum', only(await fonts(page, `${viewer} .hm-sw-viewer-menu`), VERIFY), fmt(await fonts(page, `${viewer} .hm-sw-viewer-menu`)))
+ check('뷰어 테마: More = 검증 글꼴', only(await fonts(page, `${viewer} .hm-sw-viewer-menu`), VERIFY), fmt(await fonts(page, `${viewer} .hm-sw-viewer-menu`)))
// A submenu of More, if any, is a nested menu inside a nested menu.
const sub = page.locator(`${viewer} .hm-sw-viewer-menu[data-surface="beige"] [aria-haspopup="menu"]`).first()
if (await sub.count()) {
await sub.hover()
await page.waitForTimeout(150)
- check('뷰어 테마: More 서브메뉴 = Dotum', only(await fonts(page, `${viewer} .hm-sw-viewer-menu`), VERIFY), fmt(await fonts(page, `${viewer} .hm-sw-viewer-menu`)))
+ check('뷰어 테마: More 서브메뉴 = 검증 글꼴', only(await fonts(page, `${viewer} .hm-sw-viewer-menu`), VERIFY), fmt(await fonts(page, `${viewer} .hm-sw-viewer-menu`)))
}
await page.keyboard.press('Escape')
const panels = await page.locator(`${viewer} .hm-sw-viewer-panel`).count()
- check('뷰어 테마: SWViewerPanel(제목·입력·버튼·스위치·힌트) = Dotum', panels === 2 && only(await fonts(page, `${viewer} .hm-sw-viewer-panel`), VERIFY), `${panels} panels · ${fmt(await fonts(page, `${viewer} .hm-sw-viewer-panel`))}`)
+ check('뷰어 테마: SWViewerPanel(제목·입력·버튼·스위치·힌트) = 검증 글꼴', panels === 2 && only(await fonts(page, `${viewer} .hm-sw-viewer-panel`), VERIFY), `${panels} panels · ${fmt(await fonts(page, `${viewer} .hm-sw-viewer-panel`))}`)
await page.screenshot({ path: path.join(out, 'viewer-themed-more.png'), clip: await page.locator(viewer).boundingBox() })
// General mode: SWHeader (+ open layer dropdown, window-move tooltip), SWFooter (+ command line, guide tooltip).
const general = scope('general-themed')
const headerFonts = await fonts(page, `${general} .hm-sw-header`, '.hm-sw-header__motion-tooltip')
- check('일반 테마: SWHeader + 열린 레이어 Dropdown = Dotum (창 이동 Tooltip 별도)', only(headerFonts, VERIFY), fmt(headerFonts))
+ check('일반 테마: SWHeader + 열린 레이어 Dropdown = 검증 글꼴 (창 이동 Tooltip 별도)', only(headerFonts, VERIFY), fmt(headerFonts))
const tooltip = await page.locator(`${general} .hm-sw-header__motion-tooltip`).evaluate(element => getComputedStyle(element).fontFamily)
check('일반 테마: 창 이동 Tooltip = Inter → 테마 글꼴', tooltip === `Inter, ${VERIFY}`, tooltip)
const layerMenu = await page.locator(`${general} .hm-sw-header`).getByText('A-WALL').count()
check('일반 테마: 레이어 Dropdown이 열린 상태(목록 행 A-WALL 표시)', layerMenu > 0, `${layerMenu} row`)
- check('일반 테마: SWFooter = Dotum', only(await fonts(page, `${general} .hm-sw-footer`), VERIFY), fmt(await fonts(page, `${general} .hm-sw-footer`)))
- check('일반 테마: 명령창(SWFooterCommandLine, 중첩 hm-sw-theme) = Dotum', only(await fonts(page, `${general} .hm-sw-footer-command`), VERIFY), fmt(await fonts(page, `${general} .hm-sw-footer-command`)))
+ check('일반 테마: SWFooter = 검증 글꼴', only(await fonts(page, `${general} .hm-sw-footer`), VERIFY), fmt(await fonts(page, `${general} .hm-sw-footer`)))
+ check('일반 테마: 명령창(SWFooterCommandLine, 중첩 hm-sw-theme) = 검증 글꼴', only(await fonts(page, `${general} .hm-sw-footer-command`), VERIFY), fmt(await fonts(page, `${general} .hm-sw-footer-command`)))
await page.locator(`${general} .hm-sw-footer-add`).first().focus()
await page.waitForTimeout(150)
const guide = page.locator(`${general} .hm-sw-footer [role="tooltip"]`)
- check('일반 테마: 명령 등록 안내(Tooltip) = Dotum', (await guide.count()) > 0 && only(await fonts(page, `${general} .hm-sw-footer [role="tooltip"]`), VERIFY), fmt(await fonts(page, `${general} .hm-sw-footer [role="tooltip"]`)))
+ check('일반 테마: 명령 등록 안내(Tooltip) = 검증 글꼴', (await guide.count()) > 0 && only(await fonts(page, `${general} .hm-sw-footer [role="tooltip"]`), VERIFY), fmt(await fonts(page, `${general} .hm-sw-footer [role="tooltip"]`)))
// Portals.
const [plain, themed, insideSource] = await page.evaluate(() => {
@@ -122,15 +122,15 @@ const fmt = map => Object.entries(map).map(([family, count]) => `${count}× ${fa
!!document.querySelector('[data-theme-case="portal-source"] [data-portal]')]
})
check('Portal: DOM이 테마 영역 밖에 렌더링됨', !insideSource)
- check('Portal: SWTheme만 감싸면 기본 글꼴(테마 미전달)', plain.startsWith('"Noto Sans KR"'), plain)
+ check('Portal: SWTheme만 감싸면 기본 글꼴(테마 미전달)', plain === DEFAULT, plain)
check('Portal: 같은 theme style의 SWTheme으로 감싸면 테마 적용', themed === VERIFY, themed)
// Areas.
const area = name => fonts(page, `${scope(name)} .hm-sw-viewer-hint`)
- check('영역 A(Dotum)', only(await area('area-a'), VERIFY), fmt(await area('area-a')))
+ check('영역 A(검증 글꼴)', only(await area('area-a'), VERIFY), fmt(await area('area-a')))
check('영역 B(기본) — 옆 영역 값이 섞이지 않음', only(await area('area-b'), DEFAULT), fmt(await area('area-b')))
const outer = await page.locator(`${scope('area-c')} > .hm-sw-viewer-hint`).evaluate(element => getComputedStyle(element).fontFamily)
- check('영역 C 바깥(Dotum)', outer === VERIFY, outer)
+ check('영역 C 바깥(검증 글꼴)', outer === VERIFY, outer)
check('영역 C 안쪽 SWTheme style(Malgun Gothic)만 안쪽에 적용', only(await area('area-c-nested'), NESTED), fmt(await area('area-c-nested')))
await page.screenshot({ path: path.join(out, 'theme-inheritance-full.png'), fullPage: true })
await page.close()
@@ -213,7 +213,7 @@ for (const width of [1920, 1440, 1180, 900, 560]) for (const id of ids) {
await page.waitForSelector(`${viewer} .hm-sw-viewer-menu[data-surface="beige"]`)
const more = await fonts(page, `${viewer} .hm-sw-viewer-menu`)
const command = await fonts(page, '[data-theme-case="general-themed"] .hm-sw-footer-command')
- check('대조: 기존 구조 주입 시 More·명령창이 Noto로 되돌아감(결함 재현)', only(more, DEFAULT) && only(command, DEFAULT), `More ${fmt(more)} · 명령창 ${fmt(command)}`)
+ check('대조: 기존 구조 주입 시 More·명령창이 기본 글꼴로 되돌아감(결함 재현)', only(more, DEFAULT) && only(command, DEFAULT), `More ${fmt(more)} · 명령창 ${fmt(command)}`)
await page.close()
}
const failedRegression = regression.filter(item => item.result !== 'PASS')
diff --git a/packages/ui/ai/AI_GUIDE.md b/packages/ui/ai/AI_GUIDE.md
index 8ac07f4..5fd7e42 100644
--- a/packages/ui/ai/AI_GUIDE.md
+++ b/packages/ui/ai/AI_GUIDE.md
@@ -138,7 +138,7 @@
혼합 규칙:
-1. 영역마다 하나의 패키지를 정하고 그 영역의 신규 UI는 그 패키지의 토큰만 읽습니다. Web 토큰(`--hm-sem-*`)을 SW 영역에, SW 토큰(`--hm-sw-*`)을 Web 영역에 쓰지 않습니다. OrgChart 내부는 `--hm-orgchart-*`만 씁니다.
+1. 영역마다 하나의 패키지를 정하고 그 영역의 신규 UI는 그 패키지의 토큰만 읽습니다. Web 토큰(`--hm-sem-*`)을 SW 영역에, SW 토큰(`--hm-sw-*`)을 Web 영역에 쓰지 않습니다. OrgChart 내부는 `--hm-orgchart-*`만 씁니다. 글꼴도 같습니다: SW 기본 글꼴은 돋움(Dotum, `--hm-sw-header-font-family`), Web 기본 글꼴은 Noto Sans KR(`--hm-font-family-base`), OrgChart는 자기 설정을 유지합니다. 한 패키지의 글꼴 값을 다른 영역에 복사하지 않습니다.
2. 다른 패키지 컴포넌트는 **문서에 허용된 지점에서만** 씁니다.
- SW 일반 모드 `SWPopup`의 `children` 안 Web 컨트롤(SW 카탈로그가 허용, 예: Popup 하단 `Button`)
- SW 뷰어 모드 `SWViewerPanel`의 `children` 안 Web 컨트롤 — `SWViewer*` 컨트롤로 안 될 때만(SW `AI_USAGE.md` §0.4)
diff --git a/src/sw/sw-theme.stories.tsx b/src/sw/sw-theme.stories.tsx
index a389af1..bc4c2d8 100644
--- a/src/sw/sw-theme.stories.tsx
+++ b/src/sw/sw-theme.stories.tsx
@@ -14,9 +14,9 @@ import "./sw-viewer-stories.css"
// SW theme token inheritance (2026-10-20). The official way to change SW tokens: set them through `style` (or the
// consumer's own class) on the OUTERMOST SW scope — <SWTheme> around the screen, or the component root when it is
// used alone. Nested SW roots (viewer menus, More, panels, footer command line) inherit the value.
-// Dotum is used here ONLY to make the inheritance visible: it is NOT the SW default font (design approval pending).
+// The SW default font is Dotum (2026-10-20). Noto Sans KR is used here ONLY to make the inheritance visible.
const KICKER = "HM DESIGN SYSTEM / SW"
-const VERIFY_FONT = 'Dotum, "돋움", sans-serif'
+const VERIFY_FONT = '"Noto Sans KR", sans-serif'
const VERIFY_THEME = { "--hm-sw-header-font-family": VERIFY_FONT } as CSSProperties
const NESTED_THEME = { "--hm-sw-header-font-family": '"Malgun Gothic", sans-serif' } as CSSProperties
@@ -77,8 +77,8 @@ export const ThemeInheritance: Story = {
render: () => (
<StoryPage>
<StoryPageHeader kicker={KICKER} title="SW — 테마 토큰 상속"
- description={<>SW 토큰은 가장 바깥 SW 범위(<code>&lt;SWTheme&gt;</code> 또는 단독 컴포넌트 루트)에서 한 번 선언되고, 안쪽 Dropdown·More·패널·명령창은 그 값을 상속합니다. 토큰은 가장 바깥 범위의 <code>style</code>로만 바꿉니다. 아래 Dotum은 <strong>상속 확인용 검증 값</strong>이며 SW 기본 글꼴(Noto Sans KR)은 바뀌지 않습니다(Dotum 기본 적용은 디자인 승인 대기).</>} />
- <StorySection title="1. 기본 (테마 지정 없음)" description="단독 SWViewerHeader. 기본 글꼴 Noto Sans KR. 1000px 폭이라 일부 항목이 More(⋯)로 이동합니다.">
+ description={<>SW 토큰은 가장 바깥 SW 범위(<code>&lt;SWTheme&gt;</code> 또는 단독 컴포넌트 루트)에서 한 번 선언되고, 안쪽 Dropdown·More·패널·명령창은 그 값을 상속합니다. 토큰은 가장 바깥 범위의 <code>style</code>로만 바꿉니다. SW 기본 글꼴은 Dotum이며, 아래 Noto Sans KR은 <strong>상속 확인용 검증 값</strong>입니다.</>} />
+ <StorySection title="1. 기본 (테마 지정 없음)" description="단독 SWViewerHeader. 기본 글꼴 Dotum. 1000px 폭이라 일부 항목이 More(⋯)로 이동합니다.">
<ViewerArea width={1000} data-theme-case="default" />
</StorySection>
<StorySection title="2. 뷰어 모드 — SWTheme style로 글꼴 지정" description="<SWTheme style={{ '--hm-sw-header-font-family': … }}> 안의 Header·Dropdown·More·패널(내부 컨트롤 포함)이 같은 글꼴을 씁니다.">
@@ -105,10 +105,10 @@ export const ThemeInheritance: Story = {
</StorySection>
<StorySection title="5. 여러 테마 영역" description="옆 영역끼리 값이 섞이지 않고, 안쪽 SWTheme의 style은 그 안에서만 적용됩니다.">
<div style={{ display: "grid", gridTemplateColumns: "repeat(3, minmax(0, 1fr))", gap: 12 }}>
- <SWTheme style={VERIFY_THEME} data-theme-case="area-a"><SWViewerHint>영역 A — 검증 글꼴(Dotum)</SWViewerHint></SWTheme>
- <SWTheme data-theme-case="area-b"><SWViewerHint>영역 B — 기본(Noto Sans KR)</SWViewerHint></SWTheme>
+ <SWTheme style={VERIFY_THEME} data-theme-case="area-a"><SWViewerHint>영역 A — 검증 글꼴(Noto Sans KR)</SWViewerHint></SWTheme>
+ <SWTheme data-theme-case="area-b"><SWViewerHint>영역 B — 기본(Dotum)</SWViewerHint></SWTheme>
<SWTheme style={VERIFY_THEME} data-theme-case="area-c">
- <SWViewerHint>영역 C 바깥 — Dotum</SWViewerHint>
+ <SWViewerHint>영역 C 바깥 — Noto Sans KR</SWViewerHint>
<SWTheme style={NESTED_THEME} data-theme-case="area-c-nested"><SWViewerHint>영역 C 안쪽 — Malgun Gothic</SWViewerHint></SWTheme>
</SWTheme>
</div>
@@ -0,0 +1,58 @@
// Installed Firefox (WebDriver BiDi) — real SW consumer: Dotum resolution, viewer chrome fonts, DWG load, menu/panel,
// Escape, responsive overflow. Usage: node viewer-firefox.mjs <base> <out-dir>
import { spawn } from 'node:child_process'
import { mkdir, writeFile, rm } from 'node:fs/promises'
import path from 'node:path'
import os from 'node:os'
const [base = 'http://127.0.0.1:5391', outArg = 'viewer-verify-out'] = process.argv.slice(2)
const out = path.resolve(outArg); await mkdir(out, { recursive: true })
const sleep = ms => new Promise(r => setTimeout(r, ms))
const results = [], errors = []
const check = (name, ok, data) => { results.push({ name, result: ok ? 'PASS' : 'FAIL', data }); console.log(ok ? 'PASS' : 'FAIL', name, data === undefined ? '' : JSON.stringify(data)) }
let version
for (const [width, height] of [[1400, 1000], [500, 800]]) {
const port = 9300 + Math.floor(Math.random() * 500)
const profile = path.join(os.tmpdir(), `sw-viewer-ff-${process.pid}-${width}`)
await mkdir(profile, { recursive: true })
const ff = spawn('C:/Program Files/Mozilla Firefox/firefox.exe', ['--headless', '--no-remote', '--profile', profile, `--remote-debugging-port=${port}`], { stdio: 'ignore', env: { ...process.env, MOZ_HEADLESS_WIDTH: String(width), MOZ_HEADLESS_HEIGHT: String(height) } })
let ws
for (let i = 0; i < 60 && !ws; i++) { await sleep(250); try { ws = await new Promise((res, rej) => { const s = new WebSocket(`ws://127.0.0.1:${port}/session`); s.onopen = () => res(s); s.onerror = rej }) } catch { ws = undefined } }
if (!ws) { check(`Firefox ${width}: BiDi session`, false); ff.kill(); continue }
let id = 0; const pending = new Map()
ws.onmessage = e => { const m = JSON.parse(e.data); if (m.id && pending.has(m.id)) { const { res, rej } = pending.get(m.id); pending.delete(m.id); m.type === 'error' ? rej(Error(m.message)) : res(m.result) } else if (m.method === 'log.entryAdded' && m.params.level === 'error') errors.push(`${width}: ${m.params.text}`) }
const send = (method, params = {}) => new Promise((res, rej) => { const n = ++id; pending.set(n, { res, rej }); ws.send(JSON.stringify({ id: n, method, params })) })
try {
const session = await send('session.new', { capabilities: {} }); version = session.capabilities.browserVersion
await send('session.subscribe', { events: ['log.entryAdded'] })
const context = (await send('browsingContext.getTree')).contexts[0].context
const ev = async expr => { const r = await send('script.evaluate', { expression: `JSON.stringify(${expr})`, target: { context }, awaitPromise: true }); if (r.type === 'exception') throw Error(r.exceptionDetails.text); return JSON.parse(r.result.value) }
const key = v => send('input.performActions', { context, actions: [{ type: 'key', id: 'k', actions: [{ type: 'keyDown', value: v }, { type: 'keyUp', value: v }] }] })
await send('browsingContext.navigate', { context, url: `${base}/?model=${encodeURIComponent('/samples/civil.dwg')}`, wait: 'complete' })
let st; for (let i = 0; i < 120; i++) { st = await ev('document.querySelector(".hm-sw-viewer-status")?.getAttribute("data-state")'); if (st && st !== 'loading' && st !== 'idle') break; await sleep(250) }
await sleep(800)
check(`Firefox ${width}: civil.dwg loads (status)`, st === 'ready', st)
const dotum = await ev(`(() => { const c = document.createElement('canvas').getContext('2d'); const t = '그리기모드 Standard 1.00'; c.font = '14px Dotum'; const a = c.measureText(t).width; c.font = '14px "Malgun Gothic"'; const b = c.measureText(t).width; c.font = '14px monospace'; const m = c.measureText(t).width; return { dotum: +a.toFixed(1), malgun: +b.toFixed(1), mono: +m.toFixed(1) } })()`)
check(`Firefox ${width}: Dotum resolves to an installed face (width differs from fallbacks)`, dotum.dotum !== dotum.malgun && dotum.dotum !== dotum.mono, dotum)
const fonts = await ev(`(() => { const m = {}; for (const e of document.querySelectorAll('.hm-sw-viewer-header *')) { if (![...e.childNodes].some(n => n.nodeType === 3 && n.textContent.trim())) continue; const f = getComputedStyle(e).fontFamily.split(',')[0].replace(/"/g, ''); m[f] = (m[f] ?? 0) + 1 } return m })()`)
check(`Firefox ${width}: SWViewerHeader computed font = Dotum`, Object.keys(fonts).length > 0 && Object.keys(fonts).every(f => f === 'Dotum'), fonts)
const layout = await ev(`(() => { const h = document.querySelector('.hm-sw-viewer-header'); return { header: h.scrollWidth - h.clientWidth, page: document.documentElement.scrollWidth - innerWidth, more: !!document.querySelector('.hm-sw-viewer-header__more'), h: h.getBoundingClientRect().height } })()`)
check(`Firefox ${width}: no horizontal overflow`, layout.header <= 1 && layout.page <= 1, layout)
// Open a header menu (샘플, or More at narrow widths) and close with Escape.
await ev(`(() => { const b = [...document.querySelectorAll('.hm-sw-viewer-header button')].find(e => e.textContent.trim() === '샘플') ?? document.querySelector('.hm-sw-viewer-header__more'); b.click(); return !!b })()`); await sleep(200)
const menu = await ev(`(() => { const m = document.querySelector('.hm-sw-viewer-menu'); return m ? { items: m.querySelectorAll('button').length, font: getComputedStyle(m.querySelector('button')).fontFamily.split(',')[0] } : null })()`)
check(`Firefox ${width}: header menu opens (Dotum)`, !!menu && menu.items > 0 && menu.font === 'Dotum', menu)
await key('\uE00C'); await sleep(200)
check(`Firefox ${width}: Escape closes the menu`, await ev('!document.querySelector(".hm-sw-viewer-menu")'))
// Options panel (via the header toggle, or More when collapsed).
const opened = await ev(`(() => { const t = [...document.querySelectorAll('.hm-sw-viewer-header button')].find(e => e.textContent.trim() === '설정'); if (t && t.getClientRects().length) { t.click(); return 'toggle' } document.querySelector('.hm-sw-viewer-header__more')?.click(); return 'more' })()`); await sleep(250)
if (opened === 'more') { await ev(`(() => { const i = [...document.querySelectorAll('.hm-sw-viewer-menu [role^=menuitem]')].find(e => e.textContent.includes('설정')); i?.click(); return !!i })()`); await sleep(250) }
const panel = await ev(`(() => { const p = [...document.querySelectorAll('.hm-sw-viewer-panel')].find(e => e.textContent.includes('옵션')); if (!p) return null; const b = p.querySelector('.hm-sw-property__body'); const r = p.getBoundingClientRect(); const clipped = [...p.querySelectorAll('*')].filter(e => { if (![...e.childNodes].some(n => n.nodeType === 3 && n.textContent.trim())) return false; const cs = getComputedStyle(e); if (cs.overflowX === 'visible' && cs.textOverflow !== 'ellipsis') return false; const g = document.createRange(); g.selectNodeContents(e); return g.getBoundingClientRect().width > e.clientWidth - parseFloat(cs.paddingLeft) - parseFloat(cs.paddingRight) + 0.5 }).length; return { w: Math.round(r.width), h: Math.round(r.height), font: getComputedStyle(p).fontFamily.split(',')[0], scroll: b.scrollHeight > b.clientHeight, clipped, inView: r.right <= innerWidth + 1 } })()`)
check(`Firefox ${width}: options SWViewerPanel opens, Dotum, scrollable body, no clipped text`, !!panel && panel.font === 'Dotum' && panel.clipped === 0, { opened, panel })
await writeFile(path.join(out, `firefox-${width}.png`), Buffer.from((await send('browsingContext.captureScreenshot', { context })).data, 'base64'))
await send('session.end')
} catch (error) { check(`Firefox ${width}: suite completes`, false, error.message) }
ws.close(); ff.kill(); await sleep(400); await rm(profile, { recursive: true, force: true }).catch(() => {})
}
check('Firefox: no console errors (favicon 404 excluded)', errors.filter(e => !/favicon/i.test(e)).length === 0, errors.slice(0, 5))
await writeFile(path.join(out, 'firefox-result.json'), JSON.stringify({ base, version, results, errors }, null, 2))
console.log(`Firefox ${version}: ${results.filter(r => r.result === 'PASS').length}/${results.length} PASS`)
@@ -0,0 +1,150 @@
// Real SW consumer (HMDesignSwTest-viewer, isolated copy) — Dotum font, SW viewer chrome, DWG/DXF load, zoom/pan,
// panels (open/close/Escape/drag/resize/scroll/slider/switch), header menus/More, responsive. Chrome (+ Firefox basic).
// Usage: node viewer-verify-run.mjs <base-url> <out-dir> [chromium|firefox]
import { createRequire } from 'node:module'
import path from 'node:path'
import { mkdir, writeFile } from 'node:fs/promises'
const require = createRequire(path.join('C:/Users/user/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules', 'index.js'))
const pw = require('playwright')
const { PNG } = require('pngjs')
const [base = 'http://127.0.0.1:5391', outArg = 'viewer-verify-out', engine = 'chromium'] = process.argv.slice(2)
const out = path.resolve(outArg); await mkdir(out, { recursive: true })
const results = []; const errors = []; const missingFavicon = []
const check = (name, pass, detail = '') => { results.push({ name, result: pass ? 'PASS' : 'FAIL', detail }); console.log(`${pass ? 'PASS' : 'FAIL'} ${name}${detail !== '' ? ` — ${typeof detail === 'string' ? detail : JSON.stringify(detail)}` : ''}`) }
const browser = engine === 'firefox' ? await pw.firefox.launch({ headless: true }) : await pw.chromium.launch({ headless: true, executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe' })
const newPage = async (width = 1600, height = 1000) => {
const page = await browser.newPage({ viewport: { width, height } })
page.on('pageerror', e => errors.push(`pageerror ${e.message}`))
page.on('console', m => { if (m.type() === 'error' && !/favicon|Failed to load resource/.test(m.text())) errors.push(`console ${m.text()}`) })
page.on('response', r => { if (r.status() >= 400) (r.url().endsWith('/favicon.ico') ? missingFavicon : errors).push(`HTTP ${r.status()} ${r.url()}`) })
return page
}
const status = page => page.evaluate(() => document.querySelector('.hm-sw-viewer-status')?.getAttribute('data-state'))
const waitLoaded = async (page, timeout = 60000) => { await page.waitForFunction(() => { const s = document.querySelector('.hm-sw-viewer-status')?.getAttribute('data-state'); return s && s !== 'loading' && s !== 'idle' }, null, { timeout }).catch(() => {}); await page.waitForTimeout(800); return status(page) }
const canvasStats = async page => { const buf = await page.locator('.viewer-canvas').screenshot(); const png = PNG.sync.read(buf); const seen = new Map(); let n = 0; for (let i = 0; i < png.data.length; i += 16) { const k = (png.data[i] >> 4) << 8 | (png.data[i + 1] >> 4) << 4 | png.data[i + 2] >> 4; seen.set(k, (seen.get(k) ?? 0) + 1); n++ } const top = Math.max(...seen.values()); return { colors: seen.size, nonBg: +(1 - top / n).toFixed(4), buf } }
const diffRatio = (a, b) => { const A = PNG.sync.read(a), B = PNG.sync.read(b); if (A.width !== B.width || A.height !== B.height) return 1; let d = 0; for (let i = 0; i < A.data.length; i += 4) if (Math.abs(A.data[i] - B.data[i]) + Math.abs(A.data[i + 1] - B.data[i + 1]) + Math.abs(A.data[i + 2] - B.data[i + 2]) > 30) d++; return d / (A.data.length / 4) }
const fontsOf = (page, sel) => page.evaluate(sel => { const m = {}; for (const r of document.querySelectorAll(sel)) for (const e of [r, ...r.querySelectorAll('*')]) { if (e.closest('svg')) continue; if (![...e.childNodes].some(n => n.nodeType === 3 && n.textContent.trim()) && !/^(BUTTON|INPUT)$/.test(e.tagName)) continue; const f = getComputedStyle(e).fontFamily.split(',')[0].replace(/"/g, ''); m[f] = (m[f] ?? 0) + 1 } return m }, sel)
const page = await newPage()
await page.goto(base); await page.waitForSelector('.hm-sw-viewer-header'); await page.evaluate(() => document.fonts.ready); await page.waitForTimeout(500)
// --- Font / theme
const headerFonts = await fontsOf(page, '.hm-sw-viewer-header')
check('Font: SWViewerHeader text = Dotum (SW default)', Object.keys(headerFonts).length > 0 && Object.keys(headerFonts).every(f => f === 'Dotum' || f === 'ui-monospace'), headerFonts)
if (engine === 'chromium') {
const cdp = await page.context().newCDPSession(page); await cdp.send('DOM.enable'); await cdp.send('CSS.enable')
const { root } = await cdp.send('DOM.getDocument', { depth: -1 }); const { nodeIds } = await cdp.send('DOM.querySelectorAll', { nodeId: root.nodeId, selector: '.hm-sw-viewer-header *' })
const agg = {}; for (const id of nodeIds) { const { fonts } = await cdp.send('CSS.getPlatformFontsForNode', { nodeId: id }); for (const f of fonts) agg[f.familyName] = (agg[f.familyName] ?? 0) + f.glyphCount }
check('Font: rendered platform font in header = Dotum (installed, no fallback)', Object.keys(agg).length > 0 && Object.keys(agg).every(f => f === 'Dotum'), agg)
}
const tokens = await page.evaluate(() => { const s = getComputedStyle(document.querySelector('.hm-sw-viewer-header')); return { font: s.getPropertyValue('--hm-sw-header-font-family').trim(), bg: s.getPropertyValue('--hm-sw-viewer-header-background').trim() || s.backgroundColor } })
check('Theme: SW token --hm-sw-header-font-family = Dotum stack', tokens.font.startsWith('Dotum'), tokens)
const webFont = await page.evaluate(() => getComputedStyle(document.documentElement).getPropertyValue('--hm-font-family-base').trim())
check('Web UI token --hm-font-family-base unchanged (Noto Sans KR)', webFont.startsWith('"Noto Sans KR"'), webFont)
await page.screenshot({ path: path.join(out, `${engine}-01-initial.png`) })
// --- DXF / DWG loading via the app's own ?model= path and the header sample menu
const loads = {}
for (const [label, url] of [['simple.dxf', '/samples/simple.dxf'], ['BasicSample.dwg', '/samples/BasicSample.dwg'], ['civil.dwg', '/samples/civil.dwg']]) {
const p = await newPage()
const t0 = Date.now(); await p.goto(`${base}/?model=${encodeURIComponent(url)}`); await p.waitForSelector('.hm-sw-viewer-header')
const st = await waitLoaded(p, 120000); const stats = await canvasStats(p)
const name = await p.evaluate(() => document.querySelector('.hm-sw-viewer-header__document-name')?.textContent?.trim() ?? '')
const tabs = await p.locator('.hm-sw-viewer-header__tab').count()
loads[label] = { status: st, ms: Date.now() - t0, colors: stats.colors, nonBg: stats.nonBg, name, tabs }
check(`Load ${label}: status ready + drawing pixels`, st && !/error/i.test(st) && stats.nonBg > 0.002, loads[label])
await p.screenshot({ path: path.join(out, `${engine}-02-load-${label}.png`) })
await p.close()
}
// --- Sample menu (header dropdown) + Escape, then interactions on civil.dwg
await page.goto(`${base}/?model=${encodeURIComponent('/samples/civil.dwg')}`); await waitLoaded(page, 120000)
const before = await canvasStats(page)
// zoom (wheel) and pan (drag) on the canvas
const box = await page.locator('.viewer-canvas').boundingBox()
await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2); await page.mouse.wheel(0, -600); await page.waitForTimeout(600)
const zoomed = await canvasStats(page)
check('Viewer: wheel zoom changes the drawing', diffRatio(before.buf, zoomed.buf) > 0.01, diffRatio(before.buf, zoomed.buf).toFixed(3))
await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2); await page.mouse.down({ button: 'middle' }); await page.mouse.move(box.x + box.width / 2 + 150, box.y + box.height / 2 + 80, { steps: 8 }); await page.mouse.up({ button: 'middle' }); await page.waitForTimeout(400)
let panned = await canvasStats(page)
if (diffRatio(zoomed.buf, panned.buf) <= 0.01) { await page.mouse.move(box.x + 300, box.y + 300); await page.mouse.down(); await page.mouse.move(box.x + 450, box.y + 380, { steps: 8 }); await page.mouse.up(); await page.waitForTimeout(400); panned = await canvasStats(page) }
check('Viewer: drag pan changes the view', diffRatio(zoomed.buf, panned.buf) > 0.01, diffRatio(zoomed.buf, panned.buf).toFixed(3))
await page.keyboard.press('f'); await page.waitForTimeout(500)
const fitted = await canvasStats(page)
check('Viewer: F (fit) restores the full view', diffRatio(before.buf, fitted.buf) < diffRatio(before.buf, panned.buf), `${diffRatio(before.buf, fitted.buf).toFixed(3)} < ${diffRatio(before.buf, panned.buf).toFixed(3)}`)
// space tabs (model / layouts)
const tabCount = await page.locator('.hm-sw-viewer-header__tab').count()
if (tabCount > 1) { const other = page.locator('.hm-sw-viewer-header__tab:not([data-state="active"])').first(); const label = (await other.textContent()).trim(); await other.click(); await page.waitForTimeout(1500); const s2 = await canvasStats(page); const active = await page.locator('.hm-sw-viewer-header__tab[data-state="active"]').textContent(); check('Header: space tab switch (inactive → active) re-renders the canvas', active.trim() === label && diffRatio(fitted.buf, s2.buf) > 0.01, `${tabCount} tabs, now ${active.trim()}`); await page.locator('.hm-sw-viewer-header__tab:not([data-state="active"])').first().click(); await page.waitForTimeout(1000) }
else check('Header: space tabs (only one space in civil.dwg)', true, `${tabCount} tab`)
// Header menu: 샘플 dropdown
await page.getByRole('button', { name: /샘플/ }).first().click()
const menuOpen = await page.locator('.hm-sw-viewer-menu').count()
const menuFonts = await fontsOf(page, '.hm-sw-viewer-menu')
check('Header: 샘플 dropdown opens (SWViewerMenu) with Dotum', menuOpen > 0 && Object.keys(menuFonts).every(f => f === 'Dotum'), menuFonts)
await page.screenshot({ path: path.join(out, `${engine}-03-sample-menu.png`) })
await page.keyboard.press('Escape'); await page.waitForTimeout(200)
check('Header: Escape closes the dropdown', (await page.locator('.hm-sw-viewer-menu').count()) === 0)
// load simple.dxf from the menu
await page.getByRole('button', { name: /샘플/ }).first().click(); await page.getByRole('menuitem', { name: 'simple.dxf' }).click()
const st2 = await waitLoaded(page)
const name2 = await page.evaluate(() => document.querySelector('.hm-sw-viewer-header__document-name')?.textContent?.trim())
check('Header: sample menu loads simple.dxf', /simple\.dxf/.test(name2 ?? '') && !/error/i.test(st2 ?? ''), `${name2} / ${st2}`)
// 2.5D switch
const s25 = page.getByRole('switch', { name: '2.5D' }).first()
if (await s25.count()) { const a = await canvasStats(page); await s25.click(); await page.waitForTimeout(800); const b = await canvasStats(page); check('Viewer: 2.5D switch toggles and re-renders', (await s25.getAttribute('aria-checked')) === 'true' && diffRatio(a.buf, b.buf) > 0.002, diffRatio(a.buf, b.buf).toFixed(4)); await s25.click(); await page.waitForTimeout(500) }
// Panels: 설정 (options) — open, fonts, slider, switch, drag, resize, scroll, Escape/close
await page.getByRole('button', { name: '설정' }).first().click(); await page.waitForTimeout(300)
const panel = page.locator('.hm-sw-viewer-panel').filter({ hasText: '옵션' }).first()
check('Panel: 설정 opens SWViewerPanel', await panel.isVisible())
const pf = await fontsOf(page, '.hm-sw-viewer-panel')
check('Panel: text = Dotum (program list cells keep their monospace)', Object.keys(pf).every(f => f === 'Dotum' || f === 'ui-monospace'), pf)
const slider = panel.locator('input[type="range"]').nth(1)
const v0 = await slider.inputValue(); await slider.focus(); await page.keyboard.press('ArrowRight'); await page.keyboard.press('ArrowRight'); await page.waitForTimeout(150)
const v1 = await slider.inputValue(); const num = await panel.locator('input[type="number"]').nth(1).inputValue()
check('Panel: SWViewerSlider changes value and syncs the number input', Number(v1) > Number(v0) && Number(num) === Number(v1), `${v0} → ${v1}, input ${num}`)
const sw = panel.getByRole('switch').nth(1); const c0 = await sw.getAttribute('aria-checked'); await sw.click(); const c1 = await sw.getAttribute('aria-checked'); await sw.click()
check('Panel: SWViewerSwitch toggles (그리드)', c0 !== c1, `${c0} → ${c1}`)
const pb0 = await panel.boundingBox(); const title = panel.locator('.hm-sw-property__title').first()
const tb = await title.boundingBox(); await page.mouse.move(tb.x + 40, tb.y + tb.height / 2); await page.mouse.down(); await page.mouse.move(tb.x - 160, tb.y + 120, { steps: 10 }); await page.mouse.up(); await page.waitForTimeout(200)
const pb1 = await panel.boundingBox()
check('Panel: title drag moves the panel', Math.abs(pb1.x - pb0.x) > 100 && Math.abs(pb1.y - pb0.y) > 60, `(${Math.round(pb0.x)},${Math.round(pb0.y)}) → (${Math.round(pb1.x)},${Math.round(pb1.y)})`)
const grip = panel.locator('.hm-sw-viewer-panel__resize')
if (await grip.count()) { const gb = await grip.boundingBox(); await page.mouse.move(gb.x + gb.width / 2, gb.y + gb.height / 2); await page.mouse.down(); await page.mouse.move(gb.x + 80, gb.y - 160, { steps: 10 }); await page.mouse.up(); await page.waitForTimeout(200); const pb2 = await panel.boundingBox(); check('Panel: resize grip changes size', Math.round(pb2.width - pb1.width) > 40 && Math.round(pb1.height - pb2.height) > 80, `${Math.round(pb1.width)}×${Math.round(pb1.height)} → ${Math.round(pb2.width)}×${Math.round(pb2.height)}`) }
else check('Panel: resize grip (not resizable in this program)', true, 'resizable=false')
const body = panel.locator('.hm-sw-property__body')
const sc = await body.evaluate(e => { const before = e.scrollTop; e.scrollTop = 9999; return { scrollable: e.scrollHeight > e.clientHeight, before, after: e.scrollTop, overflowX: e.scrollWidth > e.clientWidth + 1 } })
check('Panel: body scrolls vertically, no horizontal overflow', sc.scrollable && sc.after > sc.before && !sc.overflowX, sc)
const clipped = await panel.evaluate(p => [...p.querySelectorAll('*')].filter(e => { const own = [...e.childNodes].some(n => n.nodeType === 3 && n.textContent.trim()); if (!own) return false; const cs = getComputedStyle(e); if (cs.overflowX === 'visible' && cs.textOverflow !== 'ellipsis') return false; const r = document.createRange(); r.selectNodeContents(e); return r.getBoundingClientRect().width > e.clientWidth - parseFloat(cs.paddingLeft) - parseFloat(cs.paddingRight) + 0.5 }).map(e => e.textContent.trim().slice(0, 30)))
check('Panel: no clipped text after Dotum', clipped.length === 0, clipped)
await page.screenshot({ path: path.join(out, `${engine}-04-options-panel.png`) })
await panel.locator('input[type="number"]').first().focus(); await page.keyboard.press('Escape'); await page.waitForTimeout(200)
const afterEsc = await panel.isVisible().catch(() => false)
if (afterEsc) { await panel.getByRole('button', { name: /닫기/ }).first().click(); await page.waitForTimeout(200) }
check(`Panel: closes (${afterEsc ? 'close button — Escape is not wired by the program for non-modal panels' : 'Escape'})`, !(await panel.isVisible().catch(() => false)))
// 레이어 / 속성 panels + 정보(modal) Escape
await page.getByRole('button', { name: '레이어' }).first().click(); await page.waitForTimeout(300)
const lp = page.locator('.hm-sw-viewer-panel').filter({ hasText: '레이어' }).first()
check('Panel: 레이어 opens with layer rows', (await lp.isVisible()) && (await lp.locator('li').count()) > 0, `${await lp.locator('li').count()} rows`)
await page.getByRole('button', { name: '레이어' }).first().click(); await page.waitForTimeout(200)
await page.getByRole('button', { name: '정보 및 라이선스' }).click(); await page.waitForTimeout(300)
const about = page.locator('.hm-sw-viewer-panel[data-modal]').first()
const aboutOpen = await about.isVisible().catch(() => false)
await page.keyboard.press('Escape'); await page.waitForTimeout(200)
check('Panel: 정보 (modal) opens and Escape closes it', aboutOpen && !(await about.isVisible().catch(() => false)), `open=${aboutOpen}`)
// Responsive header: More at narrow widths, no horizontal overflow
for (const w of [1920, 1180, 900, 560, 375]) {
await page.setViewportSize({ width: w, height: 900 }); await page.waitForTimeout(400)
const r = await page.evaluate(() => { const h = document.querySelector('.hm-sw-viewer-header'); return { overflow: h.scrollWidth > h.clientWidth + 1, doc: document.documentElement.scrollWidth > innerWidth + 1, more: !!document.querySelector('.hm-sw-viewer-header__more') } })
check(`Responsive ${w}: header/page no horizontal overflow${r.more ? ' (More shown)' : ''}`, !r.overflow && !r.doc, r)
if (w === 900 || w === 375) {
await page.screenshot({ path: path.join(out, `${engine}-05-${w}.png`) })
if (r.more) { await page.locator('.hm-sw-viewer-header__more').click(); await page.waitForTimeout(200); const items = await page.locator('.hm-sw-viewer-menu [role="menuitem"], .hm-sw-viewer-menu [role="menuitemcheckbox"], .hm-sw-viewer-menu button').count(); check(`Responsive ${w}: More opens with collapsed items`, items > 0, `${items} items`); await page.screenshot({ path: path.join(out, `${engine}-06-more-${w}.png`) }); await page.keyboard.press('Escape') }
}
}
check('Console / page / HTTP errors: none (favicon.ico 404 = program has no icon, pre-existing)', errors.length === 0, { errors: errors.slice(0, 6), favicon404: missingFavicon.length })
await browser.close()
await writeFile(path.join(out, `${engine}-result.json`), JSON.stringify({ base, engine, loads, results, errors }, null, 2))
console.log(`${results.filter(r => r.result === 'PASS').length}/${results.length} PASS`)
File diff suppressed because it is too large. Load diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

File diff suppressed because it is too large. Load diff
@@ -0,0 +1,787 @@
{
"before": [
{
"type": "story",
"subtype": "story",
"id": "sw-header--detail-buttons",
"name": "Detail Buttons (Shared States)",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest",
"verification"
],
"exportName": "DetailButtons"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--overview",
"name": "Overview",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "Overview"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--interactive-states",
"name": "Interactive States",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "InteractiveStates"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--window-move-motion",
"name": "Window Move Motion",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "WindowMoveMotion"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--composed-controls",
"name": "Composed Controls",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "ComposedControls"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--logo-slot",
"name": "Logo Slot",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "LogoSlot"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--document-dropdown",
"name": "Document Dropdown",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "DocumentDropdown"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--layer-dropdown",
"name": "Layer Dropdown",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "LayerDropdown"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--color-dropdown",
"name": "Color Dropdown",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "ColorDropdown"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--line-style-dropdown",
"name": "Line Style Dropdown",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "LineStyleDropdown"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--text-dimension-style-dropdown",
"name": "Text · Dimension Style Dropdown",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "TextDimensionStyleDropdown"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--responsive-more",
"name": "Responsive More",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "ResponsiveMore"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--layer-detail-input",
"name": "Layer Detail · Input",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "LayerDetailInput"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--property-panel",
"name": "Property Panel",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "PropertyPanel"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--property-panel-variants",
"name": "Property Panel Variants",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "PropertyPanelVariants"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--k-guide",
"name": "K Guide",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "KGuide"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--additional-hover",
"name": "Additional Hover",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "AdditionalHover"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--property-bar",
"name": "Property Bar",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "PropertyBar"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--dynamic-controls",
"name": "Dynamic Controls",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "DynamicControls"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--colorize",
"name": "Colorize",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "Colorize"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--composition",
"name": "Composition (Visibility · Order)",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "Composition"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--property-panel-none",
"name": "Property Panel · 선택 없음",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "PropertyPanelNone"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--property-panel-all",
"name": "Property Panel · 전체 선택",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "PropertyPanelAll"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--property-panel-circle",
"name": "Property Panel · 원 1개",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "PropertyPanelCircle"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--property-panel-expanded",
"name": "Property Panel · 모두 펼침",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "PropertyPanelExpanded"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--property-panel-compare",
"name": "Property Panel · 4개 비교",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "PropertyPanelCompare"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--property-shape-slot",
"name": "Property Panel · 형상 Slot",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "PropertyShapeSlot"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--property-fields",
"name": "Property Panel · 필드 13개",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "PropertyFields"
}
],
"after": [
{
"type": "story",
"subtype": "story",
"id": "sw-header--composed-controls",
"name": "Dropdown",
"title": "SW/Header",
"importPath": "./src/sw/sw-header-dropdown.stories.tsx",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "ComposedControls"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--home-menu",
"name": "Home Menu",
"title": "SW/Header",
"importPath": "./src/sw/sw-header-home-menu.stories.tsx",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "HomeMenu"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--home-menu-capture-default",
"name": "Home Menu · 비교 캔버스 · Default",
"title": "SW/Header",
"importPath": "./src/sw/sw-header-home-menu.stories.tsx",
"tags": [
"dev",
"test",
"manifest",
"verification"
],
"exportName": "HomeMenuCaptureDefault"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--home-menu-header-composition",
"name": "Home Menu · Header 조합 · 로고 클릭",
"title": "SW/Header",
"importPath": "./src/sw/sw-header-home-menu.stories.tsx",
"tags": [
"dev",
"test",
"manifest",
"verification"
],
"exportName": "HomeMenuHeaderComposition"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--home-menu-dynamic-data",
"name": "Home Menu · Props · 데이터 변경",
"title": "SW/Header",
"importPath": "./src/sw/sw-header-home-menu.stories.tsx",
"tags": [
"dev",
"test",
"manifest",
"verification"
],
"exportName": "HomeMenuDynamicData"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--home-menu-standalone",
"name": "Home Menu · 단독 사용 · 조합형",
"title": "SW/Header",
"importPath": "./src/sw/sw-header-home-menu.stories.tsx",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "HomeMenuStandalone"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--home-menu-property-bar-check",
"name": "Home Menu · 속성Bar 비교 (26:10492)",
"title": "SW/Header",
"importPath": "./src/sw/sw-header-home-menu.stories.tsx",
"tags": [
"dev",
"test",
"manifest",
"verification"
],
"exportName": "HomeMenuPropertyBarCheck"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--home-menu-capture-property-bar",
"name": "Home Menu · 비교 캔버스 · 속성Bar",
"title": "SW/Header",
"importPath": "./src/sw/sw-header-home-menu.stories.tsx",
"tags": [
"dev",
"test",
"manifest",
"verification"
],
"exportName": "HomeMenuCapturePropertyBar"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--home-menu-integration",
"name": "Home Menu · 통합 · Popup · Escape",
"title": "SW/Header",
"importPath": "./src/sw/sw-header-home-menu.stories.tsx",
"tags": [
"dev",
"test",
"manifest",
"verification"
],
"exportName": "HomeMenuIntegration"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--home-menu-capture-responsive",
"name": "Home Menu · 비교 캔버스 · 반응형",
"title": "SW/Header",
"importPath": "./src/sw/sw-header-home-menu.stories.tsx",
"tags": [
"dev",
"test",
"manifest",
"verification"
],
"exportName": "HomeMenuCaptureResponsive"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--document-open",
"name": "Document Open",
"title": "SW/Header",
"importPath": "./src/sw/sw-header-open.stories.tsx",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "DocumentOpen"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--hidden-sub-controls",
"name": "Hidden Sub Controls",
"title": "SW/Header",
"importPath": "./src/sw/sw-header-open.stories.tsx",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "HiddenSubControls"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--detail-buttons",
"name": "Detail Buttons (Shared States)",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest",
"verification"
],
"exportName": "DetailButtons"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--overview",
"name": "Overview",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "Overview"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--interactive-states",
"name": "Interactive States",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "InteractiveStates"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--window-move-motion",
"name": "Window Move Motion",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest",
"verification"
],
"exportName": "WindowMoveMotion"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--logo-slot",
"name": "Logo Slot",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "LogoSlot"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--document-dropdown",
"name": "Document Dropdown",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "DocumentDropdown"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--responsive-more",
"name": "Responsive More",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "ResponsiveMore"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--k-guide",
"name": "K Guide",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest",
"verification"
],
"exportName": "KGuide"
}
],
"removed": [
{
"type": "story",
"subtype": "story",
"id": "sw-header--layer-dropdown",
"name": "Layer Dropdown",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "LayerDropdown"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--color-dropdown",
"name": "Color Dropdown",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "ColorDropdown"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--line-style-dropdown",
"name": "Line Style Dropdown",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "LineStyleDropdown"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--text-dimension-style-dropdown",
"name": "Text · Dimension Style Dropdown",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "TextDimensionStyleDropdown"
}
]
}
@@ -0,0 +1,593 @@
{
"sw-header--composed-controls@1920": {
"newWithCurrent": {
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-header--home-menu@1920": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0",
"hm-sw-home-menu__label \"Display...\"": "77.6>72.0",
"hm-sw-recent-files__name \"001-연결종합 계획평면도22222222.dwg\"": "309.6>299.0",
"hm-sw-recent-files__name \"00.시공상세도 분석 및 목차_20240416.gr\"": "330.3>299.0"
},
"onlyWithNoto": []
},
"sw-header--home-menu-capture-default@1920": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0",
"hm-sw-home-menu__label \"Display...\"": "77.6>72.0"
},
"onlyWithNoto": []
},
"sw-header--home-menu-header-composition@1920": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0"
},
"onlyWithNoto": []
},
"sw-header--home-menu-dynamic-data@1920": {
"newWithCurrent": {
"hm-sw-home-menu__label \"Display...\"": "77.6>72.0"
},
"onlyWithNoto": []
},
"sw-header--home-menu-integration@1920": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0"
},
"onlyWithNoto": []
},
"sw-header--home-menu-capture-responsive@1920": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0",
"hm-sw-home-menu__label \"Display...\"": "77.6>72.0"
},
"onlyWithNoto": []
},
"sw-header--document-open@1920": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-header--hidden-sub-controls@1920": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__document-item-name \"C0020101-006-평면및종단면도(06)\"": "281.5>257.0",
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0"
},
"onlyWithNoto": []
},
"sw-header--overview@1920": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0"
},
"onlyWithNoto": []
},
"sw-header--interactive-states@1920": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-header--logo-slot@1920": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-header--document-dropdown@1920": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-header--responsive-more@1920": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-header--k-guide@1920": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0"
},
"onlyWithNoto": []
},
"sw-footer--full-footer@1920": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-viewer--states@1920": {
"newWithCurrent": {
"hm-sw-viewer-header__document-name \"상태 확인용.dwg\"": "106.0>100.0"
},
"onlyWithNoto": []
},
"sw-viewer--variable-size@1920": {
"newWithCurrent": {
"hm-sw-property__title \"250 × auto (최소 폭)\"": "168.5>167.0"
},
"onlyWithNoto": []
},
"sw-viewer--compare-with-sw-header@1920": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0"
},
"onlyWithNoto": []
},
"sw-theme--theme-inheritance@1920": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0"
},
"onlyWithNoto": []
},
"sw-header--composed-controls@1280": {
"newWithCurrent": {
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-header--home-menu@1280": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0",
"hm-sw-home-menu__label \"Display...\"": "77.6>72.0",
"hm-sw-recent-files__name \"001-연결종합 계획평면도22222222.dwg\"": "309.6>299.0",
"hm-sw-recent-files__name \"00.시공상세도 분석 및 목차_20240416.gr\"": "330.3>299.0"
},
"onlyWithNoto": []
},
"sw-header--home-menu-capture-default@1280": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0",
"hm-sw-home-menu__label \"Display...\"": "77.6>72.0"
},
"onlyWithNoto": []
},
"sw-header--home-menu-header-composition@1280": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0"
},
"onlyWithNoto": []
},
"sw-header--home-menu-dynamic-data@1280": {
"newWithCurrent": {
"hm-sw-home-menu__label \"Display...\"": "77.6>72.0"
},
"onlyWithNoto": []
},
"sw-header--home-menu-integration@1280": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0"
},
"onlyWithNoto": []
},
"sw-header--home-menu-capture-responsive@1280": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0",
"hm-sw-home-menu__label \"Display...\"": "77.6>72.0"
},
"onlyWithNoto": []
},
"sw-header--document-open@1280": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-header--hidden-sub-controls@1280": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__document-item-name \"C0020101-006-평면및종단면도(06)\"": "281.5>257.0",
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0"
},
"onlyWithNoto": []
},
"sw-header--overview@1280": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0"
},
"onlyWithNoto": []
},
"sw-header--interactive-states@1280": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-header--logo-slot@1280": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-header--document-dropdown@1280": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-header--responsive-more@1280": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-header--k-guide@1280": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0"
},
"onlyWithNoto": []
},
"sw-footer--full-footer@1280": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-viewer--states@1280": {
"newWithCurrent": {
"hm-sw-viewer-header__document-name \"상태 확인용.dwg\"": "106.0>100.0"
},
"onlyWithNoto": []
},
"sw-viewer--variable-size@1280": {
"newWithCurrent": {
"hm-sw-property__title \"250 × auto (최소 폭)\"": "168.5>167.0"
},
"onlyWithNoto": []
},
"sw-viewer--compare-with-sw-header@1280": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0"
},
"onlyWithNoto": []
},
"sw-theme--theme-inheritance@1280": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0"
},
"onlyWithNoto": []
},
"sw-header--composed-controls@900": {
"newWithCurrent": {
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-header--home-menu@900": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0",
"hm-sw-home-menu__label \"Display...\"": "77.6>72.0",
"hm-sw-recent-files__name \"001-연결종합 계획평면도22222222.dwg\"": "309.6>299.0",
"hm-sw-recent-files__name \"00.시공상세도 분석 및 목차_20240416.gr\"": "330.3>299.0"
},
"onlyWithNoto": []
},
"sw-header--home-menu-capture-default@900": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0",
"hm-sw-home-menu__label \"Display...\"": "77.6>72.0"
},
"onlyWithNoto": []
},
"sw-header--home-menu-header-composition@900": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0"
},
"onlyWithNoto": []
},
"sw-header--home-menu-dynamic-data@900": {
"newWithCurrent": {
"hm-sw-home-menu__label \"Display...\"": "77.6>72.0"
},
"onlyWithNoto": []
},
"sw-header--home-menu-integration@900": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0"
},
"onlyWithNoto": []
},
"sw-header--home-menu-capture-responsive@900": {
"newWithCurrent": {
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0",
"hm-sw-home-menu__label \"Display...\"": "77.6>72.0"
},
"onlyWithNoto": []
},
"sw-header--document-open@900": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-header--hidden-sub-controls@900": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__document-item-name \"C0020101-006-평면및종단면도(06)\"": "281.5>257.0",
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0"
},
"onlyWithNoto": []
},
"sw-header--overview@900": {
"newWithCurrent": {
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0"
},
"onlyWithNoto": []
},
"sw-header--interactive-states@900": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-header--logo-slot@900": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-header--document-dropdown@900": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-header--responsive-more@900": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-header--k-guide@900": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0"
},
"onlyWithNoto": []
},
"sw-footer--full-footer@900": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-viewer--states@900": {
"newWithCurrent": {
"hm-sw-viewer-header__document-name \"상태 확인용.dwg\"": "106.0>100.0"
},
"onlyWithNoto": []
},
"sw-viewer--variable-size@900": {
"newWithCurrent": {
"hm-sw-property__title \"250 × auto (최소 폭)\"": "168.5>167.0"
},
"onlyWithNoto": []
},
"sw-viewer--compare-with-sw-header@900": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__document-name \"C0060202-001-평면및종단면도.dwg\"": "289.2>270.0"
},
"onlyWithNoto": []
},
"sw-theme--theme-inheritance@900": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0"
},
"onlyWithNoto": []
},
"sw-header--composed-controls@640": {
"newWithCurrent": {
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-header--home-menu@640": {
"newWithCurrent": {
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0",
"hm-sw-home-menu__label \"Display...\"": "77.6>72.0",
"hm-sw-recent-files__name \"001-연결종합 계획평면도22222222.dwg\"": "309.6>299.0",
"hm-sw-recent-files__name \"00.시공상세도 분석 및 목차_20240416.gr\"": "330.3>299.0"
},
"onlyWithNoto": []
},
"sw-header--home-menu-capture-default@640": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0",
"hm-sw-home-menu__label \"Display...\"": "77.6>72.0"
},
"onlyWithNoto": []
},
"sw-header--home-menu-header-composition@640": {
"newWithCurrent": {
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0"
},
"onlyWithNoto": []
},
"sw-header--home-menu-dynamic-data@640": {
"newWithCurrent": {
"hm-sw-home-menu__label \"Display...\"": "77.6>72.0"
},
"onlyWithNoto": []
},
"sw-header--home-menu-integration@640": {
"newWithCurrent": {
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0"
},
"onlyWithNoto": []
},
"sw-header--home-menu-capture-responsive@640": {
"newWithCurrent": {
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0",
"hm-sw-home-menu__label \"Display...\"": "77.6>72.0"
},
"onlyWithNoto": []
},
"sw-header--document-open@640": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-header--hidden-sub-controls@640": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__document-item-name \"C0020101-006-평면및종단면도(06)\"": "281.5>257.0",
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0"
},
"onlyWithNoto": []
},
"sw-header--overview@640": {
"newWithCurrent": {
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0"
},
"onlyWithNoto": []
},
"sw-header--interactive-states@640": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-header--logo-slot@640": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-header--document-dropdown@640": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-header--responsive-more@640": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-header--k-guide@640": {
"newWithCurrent": {
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0"
},
"onlyWithNoto": []
},
"sw-footer--full-footer@640": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"Standard\"": "70.5>69.0"
},
"onlyWithNoto": []
},
"sw-viewer--states@640": {
"newWithCurrent": {
"hm-sw-viewer-header__document-name \"상태 확인용.dwg\"": "106.0>100.0"
},
"onlyWithNoto": []
},
"sw-viewer--variable-size@640": {
"newWithCurrent": {
"hm-sw-property__title \"250 × auto (최소 폭)\"": "168.5>167.0"
},
"onlyWithNoto": []
},
"sw-viewer--compare-with-sw-header@640": {
"newWithCurrent": {
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0"
},
"onlyWithNoto": []
},
"sw-theme--theme-inheritance@640": {
"newWithCurrent": {
"hm-sw-header__document-name \"C0020101-006-평면및종단면도(06)\"": "288.2>270.0",
"hm-sw-header__mode \"그리기모드\"": "77.8>74.0",
"hm-sw-header__field-value \"0_Layer_Cludmark\"": "143.0>142.0"
},
"onlyWithNoto": []
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

File diff suppressed because it is too large. Load diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

File diff suppressed because it is too large. Load diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 454 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

@@ -0,0 +1,782 @@
{
"date": "2026-10-20T07:16:17.568Z",
"checks": [
{
"n": "Footer: 기본 Footer / States removed, full-footer + figma-variants kept",
"ok": true,
"d": [
"sw-footer--full-footer",
"sw-footer--tool-groups",
"sw-footer--figma-variants",
"sw-footer--custom-content",
"sw-footer--responsive",
"sw-footer--parts"
]
},
{
"n": "Footer: full-footer keeps only 실제 Footer 조합 (3 sections removed)",
"ok": true,
"d": {
"sections": [
"실제 Footer 조합 (동작)"
],
"errors": []
}
},
{
"n": "Footer: one live footer, no Figma / reference image",
"ok": true,
"d": 1
},
{
"n": "Footer: category change keeps the command slot position",
"ok": true,
"d": {
"before": [
1389,
817,
12
],
"after": [
1389,
817,
12
]
}
},
{
"n": "Footer: 보조기능 전체보기 hover = both lines accent + orange ring, 74 × 71",
"ok": true,
"d": {
"title": "rgb(255, 92, 0)",
"sub": "rgb(255, 92, 0)",
"ring": "1",
"w": 74,
"h": 71
}
},
{
"n": "Footer: 명령어 전체보기 hover = both lines accent + orange ring, 74 × 71",
"ok": true,
"d": {
"title": "rgb(255, 92, 0)",
"sub": "rgb(255, 92, 0)",
"ring": "1",
"w": 74,
"h": 71
}
},
{
"n": "Footer: side button default unchanged (subtitle #F6F4F2, no ring)",
"ok": true,
"d": [
"rgb(246, 244, 242)",
"0"
]
},
{
"n": "Footer: category + hover = orange + (menu-add-hover, #FF5C00), 28px",
"ok": true,
"d": "url(\"data:image/svg+xml,%3csvg%20preserveAspectRatio='none'%20overflow='visible'"
},
{
"n": "Footer: Layout + hover = gra-border-orange surface with the +, 24px",
"ok": true,
"d": "url(\"data:image/svg+xml,%3csvg%20preserveAspectRatio='none'%20overflow='visible'%20style='display:%20block;'%20width='28'%20height='12'%20viewBox='0%200%2028%20"
},
{
"n": "Footer: Model (selected) = gra-border-orange surface, black #161410 text without outline, 73 × 22",
"ok": true,
"d": {
"bg": "none",
"before": "linear-gradient(rgb(218, 104, 19) 8.52%, rgb(255, 187, 137) 37.93%, rgb(229, 105, 13) 71.85%, rgb(174, 54, 7) 92.77%)",
"color": "rgb(22, 20, 16)",
"size": "12px",
"weight": "400",
"shadow": "none",
"text": "220,40",
"w": 73,
"h": 22
}
},
{
"n": "Footer: Layout 02 hover = Model surface; text identical to Default (black, size, weight, place, box)",
"ok": true,
"d": {
"l02": {
"bg": "linear-gradient(rgb(218, 104, 19) 8.52%, rgb(255, 187, 137) 37.93%, rgb(229, 105, 13) 71.85%, rgb(174, 54, 7) 92.77%)",
"before": "none",
"color": "rgb(22, 20, 16)",
"size": "12px",
"weight": "400",
"shadow": "none",
"text": "80,40",
"w": 85,
"h": 22
},
"l02d": {
"bg": "none",
"before": "none",
"color": "rgb(22, 20, 16)",
"size": "12px",
"weight": "400",
"shadow": "none",
"text": "80,40",
"w": 85,
"h": 22
}
}
},
{
"n": "Footer: Layout 01 hover = Model surface (slanted); text identical to Default",
"ok": true,
"d": {
"l01": {
"bg": "none",
"before": "linear-gradient(rgb(218, 104, 19) 8.52%, rgb(255, 187, 137) 37.93%, rgb(229, 105, 13) 71.85%, rgb(174, 54, 7) 92.77%)",
"color": "rgb(22, 20, 16)",
"size": "12px",
"weight": "400",
"shadow": "none",
"text": "80,40",
"w": 97,
"h": 22
},
"l01d": {
"bg": "none",
"before": "url(\"data:image/svg+xml,%3csvg%20preserveAspectRatio='none'%20overflow='visible'%20style='display:%20block;'%20width='97'%20height='22'%20viewBox='0%200%2097%2022'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20id='bg'%3e%3cg%20filter='url(%23filter0_i_0_83)'%3e%3cpath%20d='M13.6039%203.29463C15.1093%201.22467%2017.5143%200%2020.0738%200H93C95.2091%200%2097%201.79086%2097%204V22H0L13.6039%203.29463Z'%20fill='%23C3B79E'/%3e%3c/g%3e%3cpath%20d='M20.0742%200.5H93C94.933%200.5%2096.5%202.067%2096.5%204V21.5H0.981445L14.0078%203.58887C15.4191%201.64829%2017.6747%200.5%2020.0742%200.5Z'%20stroke='url(%23paint0_linear_0_83)'/%3e%3c/g%3e%3cdefs%3e%3cfilter%20id='filter0_i_0_83'%20x='0'%20y='-3'%20width='97'%20height='25'%20filterUnits='userSpaceOnUse'%20color-interpolation-filters='sRGB'%3e%3cfeFlood%20flood-opacity='0'%20result='BackgroundImageFix'/%3e%3cfeBlend%20mode='normal'%20in='SourceGraphic'%20in2='BackgroundImageFix'%20result='shape'/%3e%3cfeColorMatrix%20in='SourceAlpha'%20type='matrix'%20values='0%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%20127%200'%20result='hardAlpha'/%3e%3cfeOffset%20dy='-3'/%3e%3cfeGaussianBlur%20stdDeviation='2'/%3e%3cfeComposite%20in2='hardAlpha'%20operator='arithmetic'%20k2='-1'%20k3='1'/%3e%3cfeColorMatrix%20type='matrix'%20values='0%200%200%200%200.219608%200%200%200%200%200.188235%200%200%200%200%200.121569%200%200%200%200.25%200'/%3e%3cfeBlend%20mode='multiply'%20in2='shape'%20result='effect1_innerShadow_0_83'/%3e%3c/filter%3e%3clinearGradient%20id='paint0_linear_0_83'%20x1='56'%20y1='0'%20x2='56'%20y2='22'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20stop-opacity='0.05'/%3e%3cstop%20offset='1'%20stop-opacity='0.3'/%3e%3c/linearGradient%3e%3c/defs%3e%3c/svg%3e\")",
"color": "rgb(22, 20, 16)",
"size": "12px",
"weight": "400",
"shadow": "none",
"text": "80,40",
"w": 97,
"h": 22
}
}
},
{
"n": "Footer: Layout tabs return to their default look after hover",
"ok": true,
"d": {
"bg": "none",
"before": "url(\"data:image/svg+xml,%3csvg%20preserveAspectRatio='none'%20overflow='visible'%20style='display:%20block;'%20width='97'%20height='22'%20viewBox='0%200%2097%2022'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20id='bg'%3e%3cg%20filter='url(%23filter0_i_0_83)'%3e%3cpath%20d='M13.6039%203.29463C15.1093%201.22467%2017.5143%200%2020.0738%200H93C95.2091%200%2097%201.79086%2097%204V22H0L13.6039%203.29463Z'%20fill='%23C3B79E'/%3e%3c/g%3e%3cpath%20d='M20.0742%200.5H93C94.933%200.5%2096.5%202.067%2096.5%204V21.5H0.981445L14.0078%203.58887C15.4191%201.64829%2017.6747%200.5%2020.0742%200.5Z'%20stroke='url(%23paint0_linear_0_83)'/%3e%3c/g%3e%3cdefs%3e%3cfilter%20id='filter0_i_0_83'%20x='0'%20y='-3'%20width='97'%20height='25'%20filterUnits='userSpaceOnUse'%20color-interpolation-filters='sRGB'%3e%3cfeFlood%20flood-opacity='0'%20result='BackgroundImageFix'/%3e%3cfeBlend%20mode='normal'%20in='SourceGraphic'%20in2='BackgroundImageFix'%20result='shape'/%3e%3cfeColorMatrix%20in='SourceAlpha'%20type='matrix'%20values='0%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%20127%200'%20result='hardAlpha'/%3e%3cfeOffset%20dy='-3'/%3e%3cfeGaussianBlur%20stdDeviation='2'/%3e%3cfeComposite%20in2='hardAlpha'%20operator='arithmetic'%20k2='-1'%20k3='1'/%3e%3cfeColorMatrix%20type='matrix'%20values='0%200%200%200%200.219608%200%200%200%200%200.188235%200%200%200%200%200.121569%200%200%200%200.25%200'/%3e%3cfeBlend%20mode='multiply'%20in2='shape'%20result='effect1_innerShadow_0_83'/%3e%3c/filter%3e%3clinearGradient%20id='paint0_linear_0_83'%20x1='56'%20y1='0'%20x2='56'%20y2='22'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20stop-opacity='0.05'/%3e%3cstop%20offset='1'%20stop-opacity='0.3'/%3e%3c/linearGradient%3e%3c/defs%3e%3c/svg%3e\")",
"color": "rgb(22, 20, 16)",
"size": "12px",
"weight": "400",
"shadow": "none",
"text": "80,40",
"w": 97,
"h": 22
}
},
{
"n": "Footer: category pocket surface is the same across the whole tab for 1st · 2nd · 3rd · 4th tab",
"ok": true,
"d": [
[
"도형",
"hm-sw-footer__group",
"hm-sw-footer__group",
"hm-sw-footer__group"
],
[
"수정",
"hm-sw-footer__group",
"hm-sw-footer__group",
"hm-sw-footer__group"
],
[
"편집",
"hm-sw-footer__group",
"hm-sw-footer__group",
"hm-sw-footer__group"
],
[
"문자",
"hm-sw-footer__group",
"hm-sw-footer__group",
"hm-sw-footer__group"
]
]
},
{
"n": "Footer: vacant surface covers the slot row only (46px)",
"ok": true,
"d": 46
},
{
"n": "Footer: a selected Layout keeps its own (brown) selected surface, distinct from hover",
"ok": true,
"d": [
"on",
"linear-gradient(0deg, rgb(124, 108, 76) 0.48%, rgb(124, 108, 76) 85.07%, rgb(166, 148, 111) 100%)"
]
},
{
"n": "Footer: aux Figma comparison lives in figma-variants (6 rows)",
"ok": true,
"d": []
},
{
"n": "Footer: responsive 860px row renders with an overflow ▲ control",
"ok": true,
"d": {
"panelOrder": "명령 더보기 (7개)",
"errors": []
}
},
{
"n": "Footer: 화면 폭 변화 keeps the 6 widths, 참고 좁은 화면 + Figma 기본 구성 removed",
"ok": true,
"d": [
"실제 조합 (바 안 명령창, command)"
]
},
{
"n": "Header: layer field keeps the header design (#F6F4F2, 38px, value 700)",
"ok": true,
"d": "rgb(246, 244, 242)|38px|rgb(246, 244, 242)|700"
},
{
"n": "Popup: 도면 설정 layer = 속성창 layer picker (value, trigger, label computed look)",
"ok": true,
"d": {
"a": "rgb(0, 0, 0),rgba(0, 0, 0, 0),none,rgba(0, 0, 0, 0),28px,14px,400,none / rgb(230, 4, 3),rgba(0, 0, 0, 0),none,rgb(230, 4, 3),26px,14px,400,none / rgb(0, 0, 0),rgba(0, 0, 0, 0),none,rgb(154, 146, 132),16px,14px,700,none / layer",
"b": "rgb(0, 0, 0),rgba(0, 0, 0, 0),none,rgba(0, 0, 0, 0),28px,14px,400,none / rgb(230, 4, 3),rgba(0, 0, 0, 0),none,rgb(230, 4, 3),26px,14px,400,none / rgb(0, 0, 0),rgba(0, 0, 0, 0),none,rgb(154, 146, 132),16px,14px,700,none / layer"
}
},
{
"n": "Popup: 도면 설정 color = 속성창 color picker (value, trigger, label computed look)",
"ok": true,
"d": {
"a": "rgb(0, 0, 0),rgba(0, 0, 0, 0),none,rgba(0, 0, 0, 0),28px,14px,400,none / rgb(230, 4, 3),rgba(0, 0, 0, 0),none,rgb(230, 4, 3),26px,14px,500,none / rgb(0, 0, 0),rgba(0, 0, 0, 0),none,rgb(154, 146, 132),16px,14px,700,none / color",
"b": "rgb(0, 0, 0),rgba(0, 0, 0, 0),none,rgba(0, 0, 0, 0),28px,14px,400,none / rgb(230, 4, 3),rgba(0, 0, 0, 0),none,rgb(230, 4, 3),26px,14px,500,none / rgb(0, 0, 0),rgba(0, 0, 0, 0),none,rgb(154, 146, 132),16px,14px,700,none / color"
}
},
{
"n": "Popup: no SWHeader field dropdown inside any popup",
"ok": true
},
{
"n": "Popup: layer picker opens (fixed overlay), selects and closes",
"ok": true,
"d": "Callback: layer=hatch"
},
{
"n": "Popup: color picker chip commits the RGB value",
"ok": true,
"d": "Callback: layer=hatch → color=0,0,255"
},
{
"n": "Popup: frame / title / close unchanged (3 popups in the main section)",
"ok": true
},
{
"n": "Slider: A = panel (18px, no property paint), B = property (16px, property paint), same fill",
"ok": true,
"d": [
{
"look": "panel",
"h": 18,
"fill": "0.4",
"paint": false,
"range": "#266651"
},
{
"look": "property",
"h": 16,
"fill": "0.4",
"paint": true,
"range": "#266651"
},
{
"look": "panel",
"h": 18,
"fill": "0.4",
"paint": false,
"range": "#266651"
}
]
},
{
"n": "Slider: one shared value; keyboard change on B commits through onValueCommit",
"ok": true,
"d": {
"log": "Callback: layer=hatch → color=0,0,255 → opacity(property)=50",
"afterB": [
"50",
"50",
"50"
]
}
},
{
"n": "Slider: appearance selection switches the look only",
"ok": true,
"d": "property"
},
{
"n": "Slider: disabled 40%",
"ok": true,
"d": {
"d": true,
"o": "0.4"
}
},
{
"n": "Slider: property window gauge keeps 86 × 16 and its paint",
"ok": true,
"d": [
86,
16,
true
]
},
{
"n": "Select: Popup 도면 설정 단위 = Viewer 축척 지정 단위 (default · hover · focus computed look)",
"ok": true,
"d": {
"ps": {
"d": "appearance=auto;height=28px;paddingLeft=8px;paddingRight=8px;borderTopWidth=1px;borderTopColor=rgb(148, 136, 113);borderTopStyle=solid;borderRadius=4px;backgroundColor=rgb(241, 236, 225);color=rgb(0, 0, 0);fontSize=12px;fontWeight=400;lineHeight=normal;outlineStyle=none;outlineColor=oklab(0.462622 -0.0726663 0.0150061 / 0.5);outlineWidth=3px;opacity=1;cursor=default;class=hm-sw-select;tag=SELECT",
"h": "appearance=auto;height=28px;paddingLeft=8px;paddingRight=8px;borderTopWidth=1px;borderTopColor=rgb(148, 136, 113);borderTopStyle=solid;borderRadius=4px;backgroundColor=rgb(241, 236, 225);color=rgb(0, 0, 0);fontSize=12px;fontWeight=400;lineHeight=normal;outlineStyle=none;outlineColor=oklab(0.462622 -0.0726663 0.0150061 / 0.5);outlineWidth=3px;opacity=1;cursor=default;class=hm-sw-select;tag=SELECT",
"f": "appearance=auto;height=28px;paddingLeft=8px;paddingRight=8px;borderTopWidth=1px;borderTopColor=rgb(148, 136, 113);borderTopStyle=solid;borderRadius=4px;backgroundColor=rgb(241, 236, 225);color=rgb(0, 0, 0);fontSize=12px;fontWeight=400;lineHeight=normal;outlineStyle=solid;outlineColor=rgb(166, 125, 3);outlineWidth=2px;opacity=1;cursor=default;class=hm-sw-select;tag=SELECT"
},
"vs": {
"d": "appearance=auto;height=28px;paddingLeft=8px;paddingRight=8px;borderTopWidth=1px;borderTopColor=rgb(148, 136, 113);borderTopStyle=solid;borderRadius=4px;backgroundColor=rgb(241, 236, 225);color=rgb(0, 0, 0);fontSize=12px;fontWeight=400;lineHeight=normal;outlineStyle=none;outlineColor=oklab(0.462622 -0.0726663 0.0150061 / 0.5);outlineWidth=3px;opacity=1;cursor=default;class=hm-sw-select;tag=SELECT",
"h": "appearance=auto;height=28px;paddingLeft=8px;paddingRight=8px;borderTopWidth=1px;borderTopColor=rgb(148, 136, 113);borderTopStyle=solid;borderRadius=4px;backgroundColor=rgb(241, 236, 225);color=rgb(0, 0, 0);fontSize=12px;fontWeight=400;lineHeight=normal;outlineStyle=none;outlineColor=oklab(0.462622 -0.0726663 0.0150061 / 0.5);outlineWidth=3px;opacity=1;cursor=default;class=hm-sw-select;tag=SELECT",
"f": "appearance=auto;height=28px;paddingLeft=8px;paddingRight=8px;borderTopWidth=1px;borderTopColor=rgb(148, 136, 113);borderTopStyle=solid;borderRadius=4px;backgroundColor=rgb(241, 236, 225);color=rgb(0, 0, 0);fontSize=12px;fontWeight=400;lineHeight=normal;outlineStyle=solid;outlineColor=rgb(166, 125, 3);outlineWidth=2px;opacity=1;cursor=default;class=hm-sw-select;tag=SELECT"
}
}
},
{
"n": "Select: options and selection kept (Popup mm/cm/m, Viewer mm/m), change events",
"ok": true,
"d": {
"popupOptions": [
"mm",
"cm",
"m"
],
"viewerOptions": [
"mm",
"m"
],
"popupPicked": [
true,
"m"
]
}
},
{
"n": "Header: Open returns once while growing 520 → 1080 and stays",
"ok": true,
"d": [
[
520,
0,
""
],
[
560,
0,
""
],
[
600,
1,
""
],
[
640,
1,
"actions"
],
[
680,
1,
"actions"
],
[
720,
1,
""
],
[
760,
1,
""
],
[
820,
1,
""
],
[
900,
1,
"color"
],
[
1080,
1,
"color"
]
]
},
{
"n": "Header: at 1920 every part is back and Open is shown",
"ok": true,
"d": [
[
1440,
1,
""
],
[
1920,
1,
""
]
]
},
{
"n": "Header: shrinking, Open moves into More first (1800) and stays there",
"ok": true,
"d": [
[
1800,
0,
"dimensionStyle"
],
[
1440,
0,
""
],
[
1080,
0,
""
],
[
900,
0,
""
],
[
640,
0,
""
],
[
520,
0,
""
]
]
},
{
"n": "Header: regrowing after a shrink, Open returns once and stays",
"ok": true,
"d": [
[
560,
0,
""
],
[
600,
1,
""
],
[
640,
1,
"actions"
],
[
680,
1,
"actions"
],
[
720,
1,
""
],
[
900,
1,
"color"
],
[
1080,
1,
"color"
],
[
1920,
1,
""
]
]
},
{
"n": "Popup B: same frame as Popup A",
"ok": true,
"d": [
"314|rgb(228, 219, 201)|rgb(166, 125, 3)|rgb(255, 198, 0)|700",
"314|rgb(228, 219, 201)|rgb(166, 125, 3)|rgb(255, 198, 0)|700"
]
},
{
"n": "Popup B: popup layer picker (no SWHeader field)",
"ok": true
},
{
"n": "Popup B: layer selection callback and field value",
"ok": true,
"d": "Callback: b.layer=dim"
},
{
"n": "Popup B: 375px, no page overflow and the popup inside the viewport",
"ok": true,
"d": {
"sw": 375,
"vw": 375,
"b": [
32,
343
]
}
},
{
"n": "Viewer: 250 × auto title art keeps 308px and paints from the left edge (no gap)",
"ok": true,
"d": {
"w": 250,
"h": 142,
"artW": 308,
"gap": 0
}
},
{
"n": "Viewer: 320 / 480 popups unchanged (no gap)",
"ok": true,
"d": [
{
"w": 250,
"h": 142,
"artW": 308,
"gap": 0
},
{
"w": 320,
"h": 420,
"artW": 308,
"gap": 0
},
{
"w": 480,
"h": 300,
"artW": 308,
"gap": 0
}
]
},
{
"n": "Viewer: 250 × auto collapses to the title bar and expands back to auto height",
"ok": true,
"d": {
"h0": 142,
"h1": 32
}
},
{
"n": "Viewer: 250 × auto drags by its title bar",
"ok": true,
"d": {
"dx": 60,
"dy": 30
}
},
{
"n": "Viewer: content variants (incl. 300px) title art has no gap",
"ok": true,
"d": [
{
"w": 314,
"h": 420,
"artW": 308,
"gap": 0
},
{
"w": 314,
"h": 420,
"artW": 308,
"gap": 0
},
{
"w": 300,
"h": 239,
"artW": 308,
"gap": 0
}
]
},
{
"n": "Viewer: SWViewerSlider = SWSlider panel with viewer tokens (#266651 / #e4dbc9)",
"ok": true,
"d": {
"cls": "hm-sw-slider hm-sw-viewer-slider",
"look": "panel",
"h": 18,
"range": "#266651",
"track": "#e4dbc9"
}
}
],
"report": {
"header": {
"grow": [
[
520,
0,
""
],
[
560,
0,
""
],
[
600,
1,
""
],
[
640,
1,
"actions"
],
[
680,
1,
"actions"
],
[
720,
1,
""
],
[
760,
1,
""
],
[
820,
1,
""
],
[
900,
1,
"color"
],
[
1080,
1,
"color"
]
],
"wide": [
[
1440,
1,
""
],
[
1920,
1,
""
]
],
"shrink": [
[
1800,
0,
"dimensionStyle"
],
[
1440,
0,
""
],
[
1080,
0,
""
],
[
900,
0,
""
],
[
640,
0,
""
],
[
520,
0,
""
]
],
"regrow": [
[
560,
0,
""
],
[
600,
1,
""
],
[
640,
1,
"actions"
],
[
680,
1,
"actions"
],
[
720,
1,
""
],
[
900,
1,
"color"
],
[
1080,
1,
"color"
],
[
1920,
1,
""
]
]
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

@@ -0,0 +1,477 @@
{
"browser": "155.0.8059.80",
"checks": [
{
"name": "Storybook SW titles: Header, Popup, Viewer (SW/Tool removed, SW/Home Menu merged into SW/Header 2026-10-19); no SW/Header/Options; sw-header--home-menu listed",
"status": "PASS",
"data": [
"SW/Footer",
"SW/Header",
"SW/Popup",
"SW/Theme",
"SW/Viewer"
]
},
{
"name": "menu at Figma x 375, width 1305, height 77 (measured, no fixed x); header stays 49",
"status": "PASS",
"data": {
"left": 375,
"width": 1305,
"height": 77,
"headerHeight": 49,
"sections": [
340,
260,
180,
260,
261
],
"tiles": 15,
"tileSizes": [
"80x46"
],
"titles": 5,
"badgeInlined": true,
"icons": 30,
"iconsLoaded": 30
}
},
{
"name": "5 sections 340/260/180/260/261, 15 tiles 80x46, 5 titles",
"status": "PASS",
"data": {
"left": 375,
"width": 1305,
"height": 77,
"headerHeight": 49,
"sections": [
340,
260,
180,
260,
261
],
"tiles": 15,
"tileSizes": [
"80x46"
],
"titles": 5,
"badgeInlined": true,
"icons": 30,
"iconsLoaded": 30
}
},
{
"name": "title badge SVG and 30 tile icons render",
"status": "PASS",
"data": {
"left": 375,
"width": 1305,
"height": 77,
"headerHeight": 49,
"sections": [
340,
260,
180,
260,
261
],
"tiles": 15,
"tileSizes": [
"80x46"
],
"titles": 5,
"badgeInlined": true,
"icons": 30,
"iconsLoaded": 30
}
},
{
"name": "hidden by default (not in DOM), logo aria-expanded=false",
"status": "PASS"
},
{
"name": "logo click opens, aria-expanded=true, aria-controls → menu id",
"status": "PASS"
},
{
"name": "tile Hover: label #FF5C00",
"status": "PASS",
"data": "rgb(255, 92, 0)"
},
{
"name": "action tile click: onItemSelect, no Active / aria-pressed / ring after the click",
"status": "PASS",
"data": {
"pressed": null,
"active": null,
"ring": "0"
}
},
{
"name": "logo re-click closes; onHomeClick never called while homeMenu is set",
"status": "PASS",
"data": "onHomeMenuOpenChange(false, home)\nonItemSelect(working / save, active=false)\nonHomeMenuOpenChange(true, home)"
},
{
"name": "Escape inside closes the menu and returns focus to the logo",
"status": "PASS"
},
{
"name": "click on the menu background closes it (Figma CLOSE)",
"status": "PASS"
},
{
"name": "recent panel opens (outline accent); Escape closes the panel, then the menu",
"status": "PASS",
"data": {
"panelOpen": true,
"panelFirst": true
}
},
{
"name": "opening the document dropdown closes the menu (reason document); New / Open stay in the dropdown",
"status": "PASS",
"data": "C0020101-006-평면및종단면도(06)\nC0020101-007-횡단면도\n+ New\nOpen"
},
{
"name": "opening the menu closes the document dropdown",
"status": "PASS"
},
{
"name": "no separate Open button next to the logo (documentOpenPlacement=\"menu\")",
"status": "PASS"
},
{
"name": "focus outside: Escape closes the most recent (menu), then the popup",
"status": "PASS",
"data": {
"step1": {
"menu": 0,
"popup": 1
},
"step2": {
"menu": 0,
"popup": 0
}
}
},
{
"name": "popup opened after the menu: Escape outside closes the popup first, menu stays",
"status": "PASS",
"data": {
"menu": 1,
"popup": 0
}
},
{
"name": "Escape inside the popup closes only the popup",
"status": "PASS",
"data": {
"menu": 1,
"popup": 0
}
},
{
"name": "Escape inside the menu closes only the menu (popup stays), focus → logo",
"status": "PASS",
"data": {
"menu": 0,
"popup": 1,
"focusHome": true
}
},
{
"name": "every width: menu starts at object area −2px, ends at the window area, covers neither logo nor file name, header 49, no page scroll",
"status": "PASS",
"data": [
{
"width": 1920,
"headerHeight": 49,
"start": 0,
"endGap": 0,
"coversHome": false,
"coversDocument": false,
"menuWidth": 1305,
"scrolls": false,
"pageScroll": false,
"rowSections": 5,
"moved": 0
},
{
"width": 1440,
"headerHeight": 49,
"start": 0,
"endGap": 0,
"coversHome": false,
"coversDocument": false,
"menuWidth": 825,
"scrolls": false,
"pageScroll": false,
"rowSections": 2,
"moved": 3
},
{
"width": 1080,
"headerHeight": 49,
"start": 0,
"endGap": 0,
"coversHome": false,
"coversDocument": false,
"menuWidth": 639,
"scrolls": false,
"pageScroll": false,
"rowSections": 1,
"moved": 4
},
{
"width": 768,
"headerHeight": 49,
"start": 0,
"endGap": 0,
"coversHome": false,
"coversDocument": false,
"menuWidth": 288,
"scrolls": false,
"pageScroll": false,
"rowSections": 0,
"moved": 5
},
{
"width": 520,
"headerHeight": 49,
"start": 0,
"endGap": 0,
"coversHome": false,
"coversDocument": false,
"menuWidth": 288,
"scrolls": false,
"pageScroll": false,
"rowSections": 0,
"moved": 5
},
{
"width": 390,
"headerHeight": 49,
"start": 0,
"endGap": 0,
"coversHome": false,
"coversDocument": false,
"menuWidth": 165,
"scrolls": false,
"pageScroll": false,
"rowSections": 0,
"moved": 5
}
]
},
{
"name": "every width: no horizontal scroll in the menu; 5 sections = row + More (1920: all in the row)",
"status": "PASS",
"data": [
{
"width": 1920,
"headerHeight": 49,
"start": 0,
"endGap": 0,
"coversHome": false,
"coversDocument": false,
"menuWidth": 1305,
"scrolls": false,
"pageScroll": false,
"rowSections": 5,
"moved": 0
},
{
"width": 1440,
"headerHeight": 49,
"start": 0,
"endGap": 0,
"coversHome": false,
"coversDocument": false,
"menuWidth": 825,
"scrolls": false,
"pageScroll": false,
"rowSections": 2,
"moved": 3
},
{
"width": 1080,
"headerHeight": 49,
"start": 0,
"endGap": 0,
"coversHome": false,
"coversDocument": false,
"menuWidth": 639,
"scrolls": false,
"pageScroll": false,
"rowSections": 1,
"moved": 4
},
{
"width": 768,
"headerHeight": 49,
"start": 0,
"endGap": 0,
"coversHome": false,
"coversDocument": false,
"menuWidth": 288,
"scrolls": false,
"pageScroll": false,
"rowSections": 0,
"moved": 5
},
{
"width": 520,
"headerHeight": 49,
"start": 0,
"endGap": 0,
"coversHome": false,
"coversDocument": false,
"menuWidth": 288,
"scrolls": false,
"pageScroll": false,
"rowSections": 0,
"moved": 5
},
{
"width": 390,
"headerHeight": 49,
"start": 0,
"endGap": 0,
"coversHome": false,
"coversDocument": false,
"menuWidth": 165,
"scrolls": false,
"pageScroll": false,
"rowSections": 0,
"moved": 5
}
]
},
{
"name": "without homeMenu: logo click calls onHomeClick, renders no menu, no aria-expanded",
"status": "FAIL",
"data": [
"[SWHeader Overview] homeMenuOpen(true, home)"
]
},
{
"name": "no page / console errors",
"status": "PASS",
"data": []
}
],
"errors": [],
"data": {
"titles": [
"SW/Footer",
"SW/Header",
"SW/Popup",
"SW/Theme",
"SW/Viewer"
],
"geometry": {
"left": 375,
"width": 1305,
"height": 77,
"headerHeight": 49,
"sections": [
340,
260,
180,
260,
261
],
"tiles": 15,
"tileSizes": [
"80x46"
],
"titles": 5,
"badgeInlined": true,
"icons": 30,
"iconsLoaded": 30
},
"responsive": [
{
"width": 1920,
"headerHeight": 49,
"start": 0,
"endGap": 0,
"coversHome": false,
"coversDocument": false,
"menuWidth": 1305,
"scrolls": false,
"pageScroll": false,
"rowSections": 5,
"moved": 0
},
{
"width": 1440,
"headerHeight": 49,
"start": 0,
"endGap": 0,
"coversHome": false,
"coversDocument": false,
"menuWidth": 825,
"scrolls": false,
"pageScroll": false,
"rowSections": 2,
"moved": 3
},
{
"width": 1080,
"headerHeight": 49,
"start": 0,
"endGap": 0,
"coversHome": false,
"coversDocument": false,
"menuWidth": 639,
"scrolls": false,
"pageScroll": false,
"rowSections": 1,
"moved": 4
},
{
"width": 768,
"headerHeight": 49,
"start": 0,
"endGap": 0,
"coversHome": false,
"coversDocument": false,
"menuWidth": 288,
"scrolls": false,
"pageScroll": false,
"rowSections": 0,
"moved": 5
},
{
"width": 520,
"headerHeight": 49,
"start": 0,
"endGap": 0,
"coversHome": false,
"coversDocument": false,
"menuWidth": 288,
"scrolls": false,
"pageScroll": false,
"rowSections": 0,
"moved": 5
},
{
"width": 390,
"headerHeight": 49,
"start": 0,
"endGap": 0,
"coversHome": false,
"coversDocument": false,
"menuWidth": 165,
"scrolls": false,
"pageScroll": false,
"rowSections": 0,
"moved": 5
}
]
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

File diff suppressed because it is too large. Load diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

@@ -0,0 +1,90 @@
{
"checks": [
{
"name": "Firefox 1400: 16:9 in Inner and Header 49",
"status": "PASS",
"data": {
"width": 1200,
"height": 675,
"slotWidth": 1200,
"slotHeight": 702.5,
"headerHeight": 49,
"viewportWidth": 1400,
"viewportHeight": 915
}
},
{
"name": "Firefox 1400: full original popup 314x754",
"status": "PASS",
"data": {
"width": 314,
"height": 754,
"focus": true
}
},
{
"name": "Firefox 1400: popup bottom reachable and focusable",
"status": "PASS",
"data": {
"top": 156,
"visible": true
}
},
{
"name": "Firefox 1400: Escape closes popup and restores focus",
"status": "PASS"
},
{
"name": "Firefox 500: 16:9 in Inner and Header 49",
"status": "PASS",
"data": {
"width": 468,
"height": 263.25,
"slotWidth": 468,
"slotHeight": 500.5,
"headerHeight": 49,
"viewportWidth": 500,
"viewportHeight": 715
}
},
{
"name": "Firefox 500: full original popup 314x754",
"status": "PASS",
"data": {
"width": 314,
"height": 754,
"focus": true
}
},
{
"name": "Firefox 500: popup bottom reachable and focusable",
"status": "PASS",
"data": {
"top": 567.75,
"visible": true
}
},
{
"name": "Firefox 500: Escape closes popup and restores focus",
"status": "PASS"
},
{
"name": "Firefox SW runtime errors absent; known Storybook font warnings recorded separately",
"status": "PASS",
"data": {
"errors": [],
"warnings": [
"downloadable font: download failed (font-family: \"Nunito Sans\" style:normal weight:400 width:100 src index:0): status=2147746065 source: http://127.0.0.1:5657/sb-common-assets/nunito-sans-regular.woff2",
"downloadable font: download failed (font-family: \"Nunito Sans\" style:normal weight:400 width:100 src index:0): status=2147746065 source: http://127.0.0.1:5657/sb-common-assets/nunito-sans-regular.woff2"
]
}
}
],
"errors": [],
"infrastructureWarnings": [
"downloadable font: download failed (font-family: \"Nunito Sans\" style:normal weight:400 width:100 src index:0): status=2147746065 source: http://127.0.0.1:5657/sb-common-assets/nunito-sans-regular.woff2",
"downloadable font: download failed (font-family: \"Nunito Sans\" style:normal weight:400 width:100 src index:0): status=2147746065 source: http://127.0.0.1:5657/sb-common-assets/nunito-sans-regular.woff2"
],
"version": "158.0",
"status": "PASS"
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

@@ -0,0 +1,300 @@
[
{
"type": "story",
"subtype": "story",
"id": "sw-header--composed-controls",
"name": "Dropdown",
"title": "SW/Header",
"importPath": "./src/sw/sw-header-dropdown.stories.tsx",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "ComposedControls"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--home-menu",
"name": "Home Menu",
"title": "SW/Header",
"importPath": "./src/sw/sw-header-home-menu.stories.tsx",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "HomeMenu"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--home-menu-capture-default",
"name": "Home Menu · 비교 캔버스 · Default",
"title": "SW/Header",
"importPath": "./src/sw/sw-header-home-menu.stories.tsx",
"tags": [
"dev",
"test",
"manifest",
"verification"
],
"exportName": "HomeMenuCaptureDefault"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--home-menu-header-composition",
"name": "Home Menu · Header 조합 · 로고 클릭",
"title": "SW/Header",
"importPath": "./src/sw/sw-header-home-menu.stories.tsx",
"tags": [
"dev",
"test",
"manifest",
"verification"
],
"exportName": "HomeMenuHeaderComposition"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--home-menu-dynamic-data",
"name": "Home Menu · Props · 데이터 변경",
"title": "SW/Header",
"importPath": "./src/sw/sw-header-home-menu.stories.tsx",
"tags": [
"dev",
"test",
"manifest",
"verification"
],
"exportName": "HomeMenuDynamicData"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--home-menu-standalone",
"name": "Home Menu · 단독 사용 · 조합형",
"title": "SW/Header",
"importPath": "./src/sw/sw-header-home-menu.stories.tsx",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "HomeMenuStandalone"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--home-menu-property-bar-check",
"name": "Home Menu · 속성Bar 비교 (26:10492)",
"title": "SW/Header",
"importPath": "./src/sw/sw-header-home-menu.stories.tsx",
"tags": [
"dev",
"test",
"manifest",
"verification"
],
"exportName": "HomeMenuPropertyBarCheck"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--home-menu-capture-property-bar",
"name": "Home Menu · 비교 캔버스 · 속성Bar",
"title": "SW/Header",
"importPath": "./src/sw/sw-header-home-menu.stories.tsx",
"tags": [
"dev",
"test",
"manifest",
"verification"
],
"exportName": "HomeMenuCapturePropertyBar"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--home-menu-integration",
"name": "Home Menu · 통합 · Popup · Escape",
"title": "SW/Header",
"importPath": "./src/sw/sw-header-home-menu.stories.tsx",
"tags": [
"dev",
"test",
"manifest",
"verification"
],
"exportName": "HomeMenuIntegration"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--home-menu-capture-responsive",
"name": "Home Menu · 비교 캔버스 · 반응형",
"title": "SW/Header",
"importPath": "./src/sw/sw-header-home-menu.stories.tsx",
"tags": [
"dev",
"test",
"manifest",
"verification"
],
"exportName": "HomeMenuCaptureResponsive"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--document-open",
"name": "Document Open",
"title": "SW/Header",
"importPath": "./src/sw/sw-header-open.stories.tsx",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "DocumentOpen"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--hidden-sub-controls",
"name": "Hidden Sub Controls",
"title": "SW/Header",
"importPath": "./src/sw/sw-header-open.stories.tsx",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "HiddenSubControls"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--detail-buttons",
"name": "Detail Buttons (Shared States)",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest",
"verification"
],
"exportName": "DetailButtons"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--overview",
"name": "Overview",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "Overview"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--interactive-states",
"name": "Interactive States",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "InteractiveStates"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--window-move-motion",
"name": "Window Move Motion",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest",
"verification"
],
"exportName": "WindowMoveMotion"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--logo-slot",
"name": "Logo Slot",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "LogoSlot"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--document-dropdown",
"name": "Document Dropdown",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "DocumentDropdown"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--responsive-more",
"name": "Responsive More",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "ResponsiveMore"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--k-guide",
"name": "K Guide",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest",
"verification"
],
"exportName": "KGuide"
}
]
@@ -0,0 +1,423 @@
[
{
"type": "story",
"subtype": "story",
"id": "sw-header--detail-buttons",
"name": "Detail Buttons (Shared States)",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest",
"verification"
],
"exportName": "DetailButtons"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--overview",
"name": "Overview",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "Overview"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--interactive-states",
"name": "Interactive States",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "InteractiveStates"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--window-move-motion",
"name": "Window Move Motion",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "WindowMoveMotion"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--composed-controls",
"name": "Composed Controls",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "ComposedControls"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--logo-slot",
"name": "Logo Slot",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "LogoSlot"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--document-dropdown",
"name": "Document Dropdown",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "DocumentDropdown"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--layer-dropdown",
"name": "Layer Dropdown",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "LayerDropdown"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--color-dropdown",
"name": "Color Dropdown",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "ColorDropdown"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--line-style-dropdown",
"name": "Line Style Dropdown",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "LineStyleDropdown"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--text-dimension-style-dropdown",
"name": "Text · Dimension Style Dropdown",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "TextDimensionStyleDropdown"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--responsive-more",
"name": "Responsive More",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "ResponsiveMore"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--layer-detail-input",
"name": "Layer Detail · Input",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "LayerDetailInput"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--property-panel",
"name": "Property Panel",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "PropertyPanel"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--property-panel-variants",
"name": "Property Panel Variants",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "PropertyPanelVariants"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--k-guide",
"name": "K Guide",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "KGuide"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--additional-hover",
"name": "Additional Hover",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "AdditionalHover"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--property-bar",
"name": "Property Bar",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "PropertyBar"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--dynamic-controls",
"name": "Dynamic Controls",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "DynamicControls"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--colorize",
"name": "Colorize",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "Colorize"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--composition",
"name": "Composition (Visibility · Order)",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "Composition"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--property-panel-none",
"name": "Property Panel · 선택 없음",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "PropertyPanelNone"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--property-panel-all",
"name": "Property Panel · 전체 선택",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "PropertyPanelAll"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--property-panel-circle",
"name": "Property Panel · 원 1개",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "PropertyPanelCircle"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--property-panel-expanded",
"name": "Property Panel · 모두 펼침",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "PropertyPanelExpanded"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--property-panel-compare",
"name": "Property Panel · 4개 비교",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "PropertyPanelCompare"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--property-shape-slot",
"name": "Property Panel · 형상 Slot",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "PropertyShapeSlot"
},
{
"type": "story",
"subtype": "story",
"id": "sw-header--property-fields",
"name": "Property Panel · 필드 13개",
"title": "SW/Header",
"importPath": "./src/sw/sw-header.stories.tsx",
"componentPath": "./packages/sw/dist/index.js",
"tags": [
"dev",
"test",
"manifest"
],
"exportName": "PropertyFields"
}
]
@@ -0,0 +1,733 @@
{
"baseCommit": "50bf5bda8e956a4973b923d64131f2f2285bd38c",
"checks": [
{
"name": "24 retained Story IDs, names and tags; only approved Dropdown retirements",
"status": "FAIL"
},
{
"name": "retained non-Overview declarations byte-identical; relocated composition separately verified",
"status": "FAIL"
},
{
"name": "retired Dropdown IDs absent",
"status": "PASS"
},
{
"name": "package production source untouched except the integrated-improvement files",
"status": "FAIL",
"data": [
"packages/sw/src/components/sw-footer/SWFooter.tsx",
"packages/sw/src/components/sw-footer/SWFooterCommandLine.tsx",
"packages/sw/src/components/sw-footer/SWFooterLayoutTabs.tsx",
"packages/sw/src/components/sw-footer/SWFooterParts.tsx",
"packages/sw/src/components/sw-footer/assets/arrow-down-hover.svg",
"packages/sw/src/components/sw-footer/assets/arrow-down.svg",
"packages/sw/src/components/sw-footer/assets/arrow-up-hover.svg",
"packages/sw/src/components/sw-footer/assets/arrow-up.svg",
"packages/sw/src/components/sw-footer/assets/aux-grid-snap.svg",
"packages/sw/src/components/sw-footer/assets/aux-grid.svg",
"packages/sw/src/components/sw-footer/assets/aux-lineweight.svg",
"packages/sw/src/components/sw-footer/assets/aux-object-snap.svg",
"packages/sw/src/components/sw-footer/assets/aux-orthogonal.svg",
"packages/sw/src/components/sw-footer/assets/aux-selection.svg",
"packages/sw/src/components/sw-footer/assets/menu-add-hover.svg",
"packages/sw/src/components/sw-footer/assets/menu-add.svg",
"packages/sw/src/components/sw-footer/assets/side-bg.svg",
"packages/sw/src/components/sw-footer/assets/slot-add-hover.svg",
"packages/sw/src/components/sw-footer/assets/slot-add.svg",
"packages/sw/src/components/sw-footer/assets/tab-add-hover.svg",
"packages/sw/src/components/sw-footer/assets/tab-add.svg",
"packages/sw/src/components/sw-footer/assets/tab-close-hover.svg",
"packages/sw/src/components/sw-footer/assets/tab-close.svg",
"packages/sw/src/components/sw-footer/assets/tab-delete-hover.svg",
"packages/sw/src/components/sw-footer/assets/tab-delete.svg",
"packages/sw/src/components/sw-footer/assets/tab-model-on.svg",
"packages/sw/src/components/sw-footer/assets/tab-model.svg",
"packages/sw/src/components/sw-footer/assets/tab-slant-editing-fill.svg",
"packages/sw/src/components/sw-footer/assets/tab-slant-editing.svg",
"packages/sw/src/components/sw-footer/assets/tab-slant-hover.svg",
"packages/sw/src/components/sw-footer/assets/tab-slant-on.svg",
"packages/sw/src/components/sw-footer/assets/tab-slant-ring.svg",
"packages/sw/src/components/sw-footer/assets/tab-slant.svg",
"packages/sw/src/components/sw-footer/assets/tool-arc-on.svg",
"packages/sw/src/components/sw-footer/assets/tool-arc.svg",
"packages/sw/src/components/sw-footer/assets/tool-circle-on.svg",
"packages/sw/src/components/sw-footer/assets/tool-circle.svg",
"packages/sw/src/components/sw-footer/assets/tool-ellipse-on.svg",
"packages/sw/src/components/sw-footer/assets/tool-ellipse.svg",
"packages/sw/src/components/sw-footer/assets/tool-hatch-on.svg",
"packages/sw/src/components/sw-footer/assets/tool-hatch.svg",
"packages/sw/src/components/sw-footer/assets/tool-line-on.svg",
"packages/sw/src/components/sw-footer/assets/tool-line.svg",
"packages/sw/src/components/sw-footer/assets/tool-ncopy-on.svg",
"packages/sw/src/components/sw-footer/assets/tool-ncopy.svg",
"packages/sw/src/components/sw-footer/assets/tool-pline-on.svg",
"packages/sw/src/components/sw-footer/assets/tool-pline.svg",
"packages/sw/src/components/sw-footer/assets/tool-point-on.svg",
"packages/sw/src/components/sw-footer/assets/tool-point.svg",
"packages/sw/src/components/sw-footer/assets/tool-poly-on.svg",
"packages/sw/src/components/sw-footer/assets/tool-poly.svg",
"packages/sw/src/components/sw-footer/assets/tool-rect-on.svg",
"packages/sw/src/components/sw-footer/assets/tool-rect.svg",
"packages/sw/src/components/sw-footer/icons.tsx",
"packages/sw/src/components/sw-footer/index.ts",
"packages/sw/src/components/sw-footer/types.ts",
"packages/sw/src/components/sw-header/components/SWHeaderHome.tsx",
"packages/sw/src/components/sw-home-menu/SWHomeMenu.tsx",
"packages/sw/src/components/sw-home-menu/SWRecentFiles.tsx",
"packages/sw/src/components/sw-home-menu/assets/title-badge.svg",
"packages/sw/src/components/sw-home-menu/index.ts",
"packages/sw/src/components/sw-home-menu/types.ts",
"packages/sw/src/components/sw-select/SWSelect.tsx",
"packages/sw/src/components/sw-slider/SWSlider.tsx",
"packages/sw/src/components/sw-viewer/SWViewerControls.tsx",
"packages/sw/src/components/sw-viewer/SWViewerHeader.tsx",
"packages/sw/src/components/sw-viewer/SWViewerIcon.tsx",
"packages/sw/src/components/sw-viewer/SWViewerMenu.tsx",
"packages/sw/src/components/sw-viewer/SWViewerPanel.tsx",
"packages/sw/src/components/sw-viewer/index.ts",
"packages/sw/src/components/sw-viewer/types.ts",
"packages/sw/src/theme/sw-footer.css",
"packages/sw/src/theme/sw-home-menu.css",
"packages/sw/src/theme/sw-viewer.css"
]
},
{
"name": "16:9 fitted to both Inner dimensions at 1920x1080",
"status": "PASS",
"data": {
"stage": {
"x": 360,
"y": 264.25,
"w": 1200,
"h": 675,
"right": 1560,
"bottom": 939.25
},
"slot": {
"x": 360,
"y": 169.5,
"w": 1200,
"h": 864.5,
"right": 1560,
"bottom": 1034
},
"header": {
"x": 360,
"y": 264.25,
"w": 1200,
"h": 49,
"right": 1560,
"bottom": 313.25
},
"viewport": {
"w": 1920,
"h": 1080
},
"overflow": 0
}
},
{
"name": "16:9 fitted to both Inner dimensions at 1440x900",
"status": "PASS",
"data": {
"stage": {
"x": 120,
"y": 174.25,
"w": 1200,
"h": 675,
"right": 1320,
"bottom": 849.25
},
"slot": {
"x": 120,
"y": 169.5,
"w": 1200,
"h": 684.5,
"right": 1320,
"bottom": 854
},
"header": {
"x": 120,
"y": 174.25,
"w": 1200,
"h": 49,
"right": 1320,
"bottom": 223.25
},
"viewport": {
"w": 1440,
"h": 900
},
"overflow": 0
}
},
{
"name": "16:9 fitted to both Inner dimensions at 1280x720",
"status": "PASS",
"data": {
"stage": {
"x": 191.5625,
"y": 169.5,
"w": 896.875,
"h": 504.5,
"right": 1088.4375,
"bottom": 674
},
"slot": {
"x": 38.40625,
"y": 169.5,
"w": 1203.1875,
"h": 504.5,
"right": 1241.59375,
"bottom": 674
},
"header": {
"x": 191.5625,
"y": 169.5,
"w": 896.875,
"h": 49,
"right": 1088.4375,
"bottom": 218.5
},
"viewport": {
"w": 1280,
"h": 720
},
"overflow": 0
}
},
{
"name": "16:9 fitted to both Inner dimensions at 768x600",
"status": "PASS",
"data": {
"stage": {
"x": 42.21875,
"y": 169.5,
"w": 683.546875,
"h": 384.5,
"right": 725.765625,
"bottom": 554
},
"slot": {
"x": 23.046875,
"y": 169.5,
"w": 721.90625,
"h": 384.5,
"right": 744.953125,
"bottom": 554
},
"header": {
"x": 42.21875,
"y": 169.5,
"w": 683.546875,
"h": 49,
"right": 725.765625,
"bottom": 218.5
},
"viewport": {
"w": 768,
"h": 600
},
"overflow": 0
}
},
{
"name": "16:9 fitted to both Inner dimensions at 390x844",
"status": "PASS",
"data": {
"stage": {
"x": 16,
"y": 383.0625,
"w": 358,
"h": 201.375,
"right": 374,
"bottom": 584.4375
},
"slot": {
"x": 16,
"y": 169.5,
"w": 358,
"h": 628.5,
"right": 374,
"bottom": 798
},
"header": {
"x": 16,
"y": 383.0625,
"w": 390,
"h": 49,
"right": 406,
"bottom": 432.0625
},
"viewport": {
"w": 390,
"h": 844
},
"overflow": 0
}
},
{
"name": "16:9 fitted to both Inner dimensions at 1000x500",
"status": "PASS",
"data": {
"stage": {
"x": 247.109375,
"y": 169.5,
"w": 505.765625,
"h": 284.5,
"right": 752.875,
"bottom": 454
},
"slot": {
"x": 30,
"y": 169.5,
"w": 940,
"h": 284.5,
"right": 970,
"bottom": 454
},
"header": {
"x": 247.109375,
"y": 169.5,
"w": 505.765625,
"h": 49,
"right": 752.875,
"bottom": 218.5
},
"viewport": {
"w": 1000,
"h": 500
},
"overflow": 0
}
},
{
"name": "one Header and no duplicate fixed Figma specimen",
"status": "PASS"
},
{
"name": "document selection updates Header and Callback",
"status": "PASS",
"data": "onDocumentClick → documentOpen(true) → onDocumentSelect(doc-2) → documentOpen(false)"
},
{
"name": "layer selection updates shared data",
"status": "PASS",
"data": "onDocumentClick → documentOpen(true) → onDocumentSelect(doc-2) → documentOpen(false) → onLayerOpen → onLayerSelect(layer, CC-D GNL)"
},
{
"name": "existing layer Detail callback closes list",
"status": "PASS"
},
{
"name": "color selection invokes host callback",
"status": "PASS",
"data": "onLayerOpen → onLayerSelect(layer, CC-D GNL) → onLayerOpen → onLayerDetail → onColorOpen → onColorSelect(color, 255,255,255)"
},
{
"name": "line selection updates Header",
"status": "PASS",
"data": "onLayerOpen → onLayerDetail → onColorOpen → onColorSelect(color, 255,255,255) → onLineStyleOpen → onLineTypeSelect(line, CENTER)"
},
{
"name": "ByLayer weight mode does not turn numeric property into a mode string",
"status": "PASS"
},
{
"name": "text style selection updates Header",
"status": "PASS",
"data": "onColorSelect(color, 255,255,255) → onLineStyleOpen → onLineTypeSelect(line, CENTER) → onLineWeightSelect(w-bylayer) → onTextStyleOpen → onTextStyleSelect(dotum)"
},
{
"name": "dimension style selection updates Header",
"status": "PASS",
"data": "onLineTypeSelect(line, CENTER) → onLineWeightSelect(w-bylayer) → onTextStyleOpen → onTextStyleSelect(dotum) → onDimensionStyleOpen → onDimensionStyleSelect(iso-25)"
},
{
"name": "opening another dropdown closes the previous one",
"status": "PASS"
},
{
"name": "Escape closes Header dropdown",
"status": "PASS"
},
{
"name": "outside click closes Header dropdown",
"status": "PASS"
},
{
"name": "Bar Enter commits state",
"status": "PASS"
},
{
"name": "Bar validates min=0",
"status": "PASS"
},
{
"name": "Bar Escape cancels edit",
"status": "PASS"
},
{
"name": "Header opens panel with same Bar value",
"status": "PASS"
},
{
"name": "numeric weight property remains numeric after ByLayer mode",
"status": "PASS"
},
{
"name": "Header layer value shared with panel",
"status": "PASS"
},
{
"name": "panel edit updates the Bar",
"status": "PASS"
},
{
"name": "panel number validation rejects negative radius",
"status": "PASS"
},
{
"name": "panel Layer dropdown updates Header shared value",
"status": "PASS"
},
{
"name": "panel line dropdown updates Header shared value",
"status": "PASS"
},
{
"name": "panel color dropdown updates Header shared value",
"status": "PASS"
},
{
"name": "panel RGB validation rejects out-of-range value",
"status": "PASS"
},
{
"name": "gauge keyboard editing commits host state",
"status": "PASS"
},
{
"name": "first Escape cancels draft and retains panel",
"status": "PASS"
},
{
"name": "next Escape closes panel and restores Header focus",
"status": "PASS"
},
{
"name": "panel Close button restores focus",
"status": "PASS"
},
{
"name": "external Props update Bar",
"status": "PASS"
},
{
"name": "Bar ReadOnly",
"status": "PASS"
},
{
"name": "Bar Disabled",
"status": "PASS"
},
{
"name": "dynamic Bar field added",
"status": "PASS"
},
{
"name": "dynamic field shared with panel",
"status": "PASS"
},
{
"name": "dynamic field removed from both",
"status": "PASS"
},
{
"name": "shape Slot can be empty without changing panel structure",
"status": "PASS"
},
{
"name": "original panel size none:314x256",
"status": "PASS",
"data": {
"x": 1000,
"y": 301.25,
"width": 314,
"height": 256
}
},
{
"name": "original panel size all:314x361",
"status": "PASS",
"data": {
"x": 1000,
"y": 301.25,
"width": 314,
"height": 361
}
},
{
"name": "original panel size circle:314x658",
"status": "PASS",
"data": {
"x": 1000,
"y": 301.25,
"width": 314,
"height": 658
}
},
{
"name": "original panel size expanded:314x754",
"status": "PASS",
"data": {
"x": 1000,
"y": 301.25,
"width": 314,
"height": 754
}
},
{
"name": "expanded popup bottom accessible through internal scroll",
"status": "PASS"
},
{
"name": "small Inner reaches full popup bottom with native Header and popup dimensions",
"status": "PASS",
"data": {
"top": 630,
"left": 16,
"height": 201,
"scrollHeight": 831,
"width": 358,
"scrollWidth": 390
}
},
{
"name": "narrow popup Escape restores More focus",
"status": "PASS"
},
{
"name": "actual Storybook manager iframe fits its own Inner",
"status": "PASS",
"data": {
"width": 1071.59375,
"height": 602.765625,
"slotWidth": 1071.59375,
"slotHeight": 744.5,
"viewportWidth": 1140,
"viewportHeight": 960
}
},
{
"name": "no browser errors",
"status": "PASS",
"data": []
}
],
"errors": [],
"sizes": [
{
"stage": {
"x": 360,
"y": 264.25,
"w": 1200,
"h": 675,
"right": 1560,
"bottom": 939.25
},
"slot": {
"x": 360,
"y": 169.5,
"w": 1200,
"h": 864.5,
"right": 1560,
"bottom": 1034
},
"header": {
"x": 360,
"y": 264.25,
"w": 1200,
"h": 49,
"right": 1560,
"bottom": 313.25
},
"viewport": {
"w": 1920,
"h": 1080
},
"overflow": 0
},
{
"stage": {
"x": 120,
"y": 174.25,
"w": 1200,
"h": 675,
"right": 1320,
"bottom": 849.25
},
"slot": {
"x": 120,
"y": 169.5,
"w": 1200,
"h": 684.5,
"right": 1320,
"bottom": 854
},
"header": {
"x": 120,
"y": 174.25,
"w": 1200,
"h": 49,
"right": 1320,
"bottom": 223.25
},
"viewport": {
"w": 1440,
"h": 900
},
"overflow": 0
},
{
"stage": {
"x": 191.5625,
"y": 169.5,
"w": 896.875,
"h": 504.5,
"right": 1088.4375,
"bottom": 674
},
"slot": {
"x": 38.40625,
"y": 169.5,
"w": 1203.1875,
"h": 504.5,
"right": 1241.59375,
"bottom": 674
},
"header": {
"x": 191.5625,
"y": 169.5,
"w": 896.875,
"h": 49,
"right": 1088.4375,
"bottom": 218.5
},
"viewport": {
"w": 1280,
"h": 720
},
"overflow": 0
},
{
"stage": {
"x": 42.21875,
"y": 169.5,
"w": 683.546875,
"h": 384.5,
"right": 725.765625,
"bottom": 554
},
"slot": {
"x": 23.046875,
"y": 169.5,
"w": 721.90625,
"h": 384.5,
"right": 744.953125,
"bottom": 554
},
"header": {
"x": 42.21875,
"y": 169.5,
"w": 683.546875,
"h": 49,
"right": 725.765625,
"bottom": 218.5
},
"viewport": {
"w": 768,
"h": 600
},
"overflow": 0
},
{
"stage": {
"x": 16,
"y": 383.0625,
"w": 358,
"h": 201.375,
"right": 374,
"bottom": 584.4375
},
"slot": {
"x": 16,
"y": 169.5,
"w": 358,
"h": 628.5,
"right": 374,
"bottom": 798
},
"header": {
"x": 16,
"y": 383.0625,
"w": 390,
"h": 49,
"right": 406,
"bottom": 432.0625
},
"viewport": {
"w": 390,
"h": 844
},
"overflow": 0
},
{
"stage": {
"x": 247.109375,
"y": 169.5,
"w": 505.765625,
"h": 284.5,
"right": 752.875,
"bottom": 454
},
"slot": {
"x": 30,
"y": 169.5,
"w": 940,
"h": 284.5,
"right": 970,
"bottom": 454
},
"header": {
"x": 247.109375,
"y": 169.5,
"w": 505.765625,
"h": 49,
"right": 752.875,
"bottom": 218.5
},
"viewport": {
"w": 1000,
"h": 500
},
"overflow": 0
}
],
"browser": "155.0.8059.80",
"managerOrder": [
"sw-header--composed-controls",
"sw-header--home-menu",
"sw-header--home-menu-standalone",
"sw-header--document-open",
"sw-header--hidden-sub-controls",
"sw-header--overview",
"sw-header--interactive-states",
"sw-header--logo-slot",
"sw-header--document-dropdown",
"sw-header--responsive-more"
],
"status": "FAIL"
}
@@ -0,0 +1,12 @@
[
"sw-header--composed-controls",
"sw-header--home-menu",
"sw-header--home-menu-standalone",
"sw-header--document-open",
"sw-header--hidden-sub-controls",
"sw-header--overview",
"sw-header--interactive-states",
"sw-header--logo-slot",
"sw-header--document-dropdown",
"sw-header--responsive-more"
]
Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

+19
View File
@@ -0,0 +1,19 @@
=== footer-popup-viewer-refinement
exit 0 pass=47 fail=0
=== integrated-improvement
exit 0 pass=89 fail=0
=== theme-inheritance
exit 0 pass=23 fail=0
=== viewer
exit 0 pass=70 fail=0
=== storybook-simplification
exit 0 pass=9 fail=0
=== home-menu-integration
exit 1 pass=22 fail=1
=== storybook-unused-removal
exit 1 pass=0 fail=5
=== overview
exit 1 pass=0 fail=0
=== dropdown-consolidation
exit 1 pass=223 fail=5
DONE
Loaded 100 of 149 files, more files were not shown because too many files have changed in this diff. Show more