fix(storybook): align viewer property popup card layout
Deploy Storybook / deploy (push) Successful in 1m13s

This commit is contained in:
shkim4 committed 2026-10-23 13:12:36 +09:00
1 parent e492a84f1d
commit 4551edfd82
3 files changed
+19 -14

No files matched your search

+7 -7
View File
@@ -25,13 +25,13 @@ SWViewerPanel (= SWPopup, .hm-sw-property.hm-sw-viewer-panel) ← 테두리
|---|---|---|---|---|---|---|
| Footer 위 구분선 | 스크롤 본문과 하단 버튼 영역 분리 | `.hm-sw-viewer-panel__footer` | `border-top: 1px solid var(--hm-sw-viewer-panel-inner-border)`(#948871), `padding: 7px`, `gap: 8px`, 오른쪽 정렬 | `footer` Prop이 있고 접힘(`collapsed`)이 아닐 때만 렌더링 | 공통 | `SW/Viewer › Viewer Header`의 `모듈 구성 · 라이선스 고지` modal(`AboutPanel`, `확인` 버튼). Settings Popup 3개에는 footer 없음 |
| 전체 레이어 행 아래 선 | 고정 행(검색·전체 레이어)과 레이어 목록 분리 | `.sw-viewer-story-layers .sw-viewer-story-all` | `border-bottom: 1px solid var(--hm-sw-property-table)`(#d2c8b4), `padding-bottom: 8px`(실측 `padding: 0 6px 8px 0`) | 레이어 Popup에만 해당. 검색과 전체 레이어 사이에는 선 없음 | **Storybook 전용** | Settings Popup › `레이어 (9개)` |
| 속성 행 사이 선 | 속성 키/값 행 구분 | `.sw-viewer-story-props > div` | `border-bottom: 1px solid var(--hm-sw-viewer-panel-inner-border)`(#948871), `padding: 6px 0`, `gap: 12px` | 각 그룹의 **마지막 행에도** 선이 있음(실측 9행 모두) | **Storybook 전용** | Settings Popup › `속성` |
| 속성 행 사이 선 | 속성 키/값 행 구분 | `.sw-viewer-story-props > div` | `border-bottom: 1px solid var(--hm-sw-property-table)`(#d2c8b4), `padding: 6px 0`, `gap: 12px`, 이름 왼쪽·값 오른쪽(말줄임) | 각 Card의 마지막 행에는 선 없음(2026-10-23, 뷰어 화면 기준) | **Storybook 전용** | Settings Popup › `속성` |
## 3. 선이 표시되지 않는 영역
| 영역 | 목적 | 선택자 | 실제 값 | 조건·예외 | 구분 | Storybook 예시 |
|---|---|---|---|---|---|---|
| Plain Section | 패널 본문에 카드 없이 콘텐츠를 바로 배치 | `.hm-sw-viewer-section[data-surface="plain"]` | 전용 규칙 없음 → 기본 `.hm-sw-viewer-section`만 적용: `display: flex; flex-direction: column; gap: 12px`, 테두리·배경·padding 0 | `SWViewerSection surface="plain"`을 명시했을 때 | 공통 | 레이어 Popup의 목록 Section, 속성 Popup의 `일반 정보`·`기하 속성` |
| Plain Section | 패널 본문에 카드 없이 콘텐츠를 바로 배치 | `.hm-sw-viewer-section[data-surface="plain"]` | 전용 규칙 없음 → 기본 `.hm-sw-viewer-section`만 적용: `display: flex; flex-direction: column; gap: 12px`, 테두리·배경·padding 0 | `SWViewerSection surface="plain"`을 명시했을 때 | 공통 | 레이어 Popup의 목록 Section |
| 제목줄 ↔ 본문 경계 | — | `.hm-sw-property__titlebar` / `.hm-sw-property__body` | 경계선 없음. 제목줄은 배경 그라데이션, 본문은 위쪽 inset 하이라이트(§5)로만 구분 | 모든 패널 | 공통(SWPopup) | Settings Popup 전체 |
| 검색 ↔ 전체 레이어 | 고정 행 두 개 | `.sw-viewer-story-toolbar` | 선 없음, `gap: 12px 4px` | 레이어 Popup | Storybook 전용 | `레이어 (9개)` |
| 레이어 목록 행 사이 | 레이어 항목 나열 | `.sw-viewer-story-list`, `li` | 선 없음, 목록 `gap: 4px`, 행 `padding: 4px 6px` | — | Storybook 전용 | `레이어 (9개)` |
@@ -42,7 +42,7 @@ SWViewerPanel (= SWPopup, .hm-sw-property.hm-sw-viewer-panel) ← 테두리
| 영역 | 목적 | 선택자 | Border | Background | Radius | Padding·기타 | 조건·예외 | 구분 | 예시 |
|---|---|---|---|---|---|---|---|---|---|
| 패널 프레임 | 팝업 전체 외곽 | `.hm-sw-property`(SWPopup) + `.hm-sw-viewer-panel` | `1px solid var(--hm-sw-property-border)`(#a67d03) + `box-shadow: inset 0 0 0 1px #000`(안쪽 검정 1px) | `var(--hm-sw-property-surface)`(#e4dbc9) | 4px | padding 0, `overflow: hidden` | 모든 SWViewerPanel. modal이면 뒤에 `.hm-sw-viewer-panel-backdrop`(`rgba(0,0,0,.1)`) | 공통(SWPopup 그대로) | Settings Popup 3개 |
| Card Section | 설정 그룹 묶음 | `.hm-sw-viewer-section[data-surface="card"]` | `1px solid var(--hm-sw-viewer-panel-inner-border)`(#948871) | `var(--hm-sw-viewer-panel-field-background)`(#f1ece1) | `var(--hm-sw-viewer-radius)` 4px | `padding: var(--hm-sw-viewer-panel-spacing)` 12px, `gap: 12px`, `box-shadow: inset 0 1px 0 #fff`, `margin-top: 0`(2026-10-23: 그룹 박스 사이는 본문 gap 8px만, 소비 앱 단일 class의 상단 여백 무시) | `SWViewerSection`의 **기본값**(`surface` 생략 시 card). plain Section의 상단 여백은 유지 | 공통 | `옵션`의 `선가중치`·`표시`·`2.5D` |
| Card Section | 설정 그룹 묶음 | `.hm-sw-viewer-section[data-surface="card"]` | `1px solid var(--hm-sw-viewer-panel-inner-border)`(#948871) | `var(--hm-sw-viewer-panel-field-background)`(#f1ece1) | `var(--hm-sw-viewer-radius)` 4px | `padding: var(--hm-sw-viewer-panel-spacing)` 12px, `gap: 12px`, `box-shadow: inset 0 1px 0 #fff`, `margin-top: 0`(2026-10-23: 그룹 박스 사이는 본문 gap 8px만, 소비 앱 단일 class의 상단 여백 무시) | `SWViewerSection`의 **기본값**(`surface` 생략 시 card). plain Section의 상단 여백은 유지 | 공통 | `옵션`의 `선가중치`·`표시`·`2.5D`, `속성`의 `일반 정보 (GENERAL)`·`기하 속성 (GEOMETRY)`(2026-10-23) |
| 검색 입력 | 레이어 검색 | `.hm-sw-theme .hm-sw-viewer-input[type="search"]` | `1px solid var(--hm-sw-viewer-panel-inner-border)` | field-background #f1ece1 | 4px | 80px 기본 폭, 높이 28px, `padding: 0 10px` | `type="search"`만. 값 입력(§5)과 다름 | 공통 | `레이어 (9개)` |
| 패널 버튼 outline | 보조 버튼 | `.hm-sw-theme .hm-sw-viewer-button` | `1px solid var(--hm-sw-viewer-panel-primary)`(#123328) | #fff (`primary`는 #123328) | 4px | 높이 24px, `padding: 0 8px` | 제목줄의 `variant="ghost"`는 테두리·배경 없음(26 × 26) | 공통 | `모듈 구성` modal의 `확인`(primary). Settings Popup에는 ghost만 |
@@ -54,9 +54,9 @@ SWViewerPanel (= SWPopup, .hm-sw-property.hm-sw-viewer-panel) ← 테두리
| 본문 | 스크롤 콘텐츠 영역 | `.hm-sw-property__body` + `.hm-sw-viewer-panel .hm-sw-property__body` | `padding: 7px 7px 0`, `border-bottom: 8px solid transparent`(스크롤 영역 밖 하단 여백), `gap: 8px`, `box-shadow: inset 0 2px 2px rgba(255,255,255,.6)`, 배경은 프레임 surface | 접힘이면 `display: none` | 공통(SWPopup 7px + 뷰어 하단 8px 덮어쓰기) | 전체 |
| Field | 라벨 + 컨트롤 행 | `.hm-sw-viewer-field`, `__row` | 선·배경 없음, field `gap: 6px`, row `gap: 8px`, `min-height: 20px` | disabled면 `opacity: .5` | 공통 | `옵션` |
| 값 입력·단위 칸 | 숫자 입력 | `.hm-sw-viewer-input:not([type="search"])`, `.hm-sw-viewer-field__control:has(> unit)` | 기본 **투명 테두리**(1px transparent), radius 2px, 높이 28px. Hover/편집 시에만 `--hm-sw-property-field-hover-border-color` 테두리, 편집 중 배경 `--hm-sw-property-field-editing-background` | 상태가 바뀔 때만 박스로 보임 | 공통 | `옵션`의 `표시 배율`(px/mm) |
| Badge | 개수·유형 표시 | `.hm-sw-viewer-badge` | 테두리 없음, `background: var(--hm-sw-viewer-panel-badge-background)`(#d2c8b4), radius 4px, `padding: 2px 8px` | — | 공통 | 레이어 개수, `LINE · h=2F1A` |
| Badge | 개수·유형 표시 | `.hm-sw-viewer-badge` | 테두리 없음, `background: var(--hm-sw-viewer-panel-badge-background)`(#d2c8b4), radius 4px, `padding: 2px 8px` | — | 공통 | 레이어 개수, `LINE · h=2F1A`(`속성` 맨 위, Card 밖, 자기 폭) |
| 레이어 행 Hover | 행 강조 | `.sw-viewer-story-list li:hover` | `background: rgba(154,146,132,.25)`, radius 3px | Hover일 때만. 숨긴 레이어는 `opacity: .45` | Storybook 전용 | `레이어 (9개)` |
| 속성 그룹 간격 | 두 속성 그룹 분리 | `.sw-viewer-story-props-next` | `margin-top: var(--hm-sw-viewer-panel-spacing)` 12px(본문 gap 8px과 합쳐 20px) | 두 번째 그룹 | Storybook 전용 | `속성` |
| 속성 그룹 간격 | 두 속성 그룹 분리 | Card Section 사이 | 본문 `gap` 8px만(Card `margin-top: 0`, 2026-10-23 `.sw-viewer-story-props-next` 제거) | 두 Card 사이 | Storybook 전용 | `속성` |
| Hint | 보조 설명 | `.hm-sw-viewer-hint` | 선·배경 없음, 12px | — | 공통 | `옵션` |
| 빈 상태 | 선택 없음 안내 | `.sw-viewer-story-empty` | 선·배경 없음, `padding: 40px 0`, 가운데 정렬 | `PropertiesPanel selected={false}` | Storybook 전용 | `SW/Viewer › States` 등 |
| Resize Grip | 크기 조절 | `.hm-sw-viewer-panel__resize` | 14 × 14, inner-border 색 빗금 그라데이션(선 아님) | `resizable` 이고 접힘이 아닐 때 | 공통 | 전체 |
@@ -65,8 +65,8 @@ SWViewerPanel (= SWPopup, .hm-sw-property.hm-sw-viewer-panel) ← 테두리
1. **Card가 기본값인 이유:** `SWViewerSection`의 기본 `surface`는 `card`입니다. 그러나 레이어·속성 Popup은 모두 `plain`을 명시하고, card는 `옵션` Popup만 씁니다. 어느 콘텐츠에 card/plain을 쓰는지에 대한 디자인 기준 문서는 확인되지 않았습니다.
2. **레이어 구분선 위치:** "전체 레이어 행 아래 `#d2c8b4` 1px 선, 검색과 사이에는 없음" 규칙은 `packages/sw/ai/VIEWER.md`에 소비 앱 규칙으로 적혀 있습니다. 실제 구현은 Storybook/예제의 소비 앱 CSS뿐이고 패키지 공통 스타일은 아닙니다.
3. **구분선 색 두 가지:** 레이어 구분선은 `--hm-sw-property-table`(#d2c8b4)이고, 속성 행 선·Footer 선·Card 테두리는 `--hm-sw-viewer-panel-inner-border`(#948871)입니다. 용도별로 색을 나누는 기준은 문서화되어 있지 않습니다.
4. **속성 행 마지막 선:** 각 그룹의 마지막 행에도 아래 선이 그려집니다(Storybook 전용 CSS). 의도인지 확인되지 않았습니다.
3. **구분선 색 두 가지:** 레이어 구분선·속성 행 선(2026-10-23)은 `--hm-sw-property-table`(#d2c8b4)이고, Footer 선·Card 테두리는 `--hm-sw-viewer-panel-inner-border`(#948871)입니다. 용도별로 색을 나누는 기준은 문서화되어 있지 않습니다.
4. **속성 행 마지막 선:** 2026-10-23 뷰어 화면 기준으로 각 Card의 마지막 행에는 선을 그리지 않습니다(Storybook 전용 CSS).
5. **Footer 예시 부족:** Footer 구분선은 대표 Settings Popup에 없습니다. `Viewer Header` Story의 modal에서만 보이며, 비-modal 패널 Footer의 디자인 기준 화면은 확인되지 않았습니다.
6. **입력 박스 두 형태:** 검색 입력은 항상 테두리 박스이고, 값 입력은 Hover/편집 때만 테두리가 생깁니다(2026-10-22 사용자 요청 주석). 다른 텍스트 입력(예: 검색이 아닌 일반 text)에 어느 쪽을 쓸지는 `type="search"` 여부로만 갈립니다.
7. **Card 안쪽 하이라이트:** `box-shadow: inset 0 1px 0 #fff`는 하드코드 값이고 대응 토큰이 없습니다.