feat(sw): add step header with multi-step and split layout support
This commit is contained in:
1 parent
6ca92c5d55
commit
adbb034cb1
28 files changed
+2477
-7
No files matched your search
@@ -0,0 +1,327 @@
|
||||
# SW Step Header 디자인 명세 (`SWProcessHeader`)
|
||||
|
||||
> 상태: `@hm-design/sw` 1차 구현 기준(2026-11-03). 코드: `packages/sw/src/components/sw-process-header/`, CSS: `packages/sw/src/theme/sw-process-header.css`, Story: `SW / Step Header`(2026-11-03 표시 명칭 변경, 컴포넌트·공개 API 이름 `SWProcessHeader`·`SWProcessBar` 등은 유지).
|
||||
> 원본: Strana Main Header — `D:\Strana\Git_StranaDevDesign` HEAD `edda3cc`(Header 7173e82 + 분할 버튼 b7f412c)의 `HeaderStyles.xaml`, `HeaderBrushes.xaml`, `MainProcessBar.xaml`, `MainWorkspaceWindowView.xaml`, Hanmac `Colors.xaml`. Strana 저장소는 읽기 전용 참고이며 수정하지 않습니다.
|
||||
> 승인: 2026-11-03 사용자 승인(방안 B · 설계 계획서 7절 9개 항목 권장안).
|
||||
|
||||
## 1. 개요
|
||||
|
||||
SW 일반 모드의 **독립 Header**입니다. `SWHeader`(편집 메뉴 Header), `SWViewerHeader`(뷰어 모드)와 같은 층위이며 한 화면에는 Header를 하나만 둡니다. `SWHeader`·`SWViewerHeader`·`sw.css`는 바꾸지 않았습니다.
|
||||
|
||||
| 공개 컴포넌트 | 역할 |
|
||||
|---|---|
|
||||
| `SWProcessHeader` | 49px Header 프레임: 로고 → 파일명 → 가운데(프로세스 · Layer 면) → 창 영역(도구 pill · 창 이동 · 최소화 · 최대화/복원 · 종료) |
|
||||
| `SWProcessBar` | 프로세스 단계 영역(그룹 번호·이름, 단계 탭, 그룹 사이 화살표, 활성 그룹 발광). Header 밖에서는 `SWTheme` 안에서 씁니다 |
|
||||
| `SWProcessSplitButton` | `tools` pill 안 화면 분할 도구(버튼 + 6칸 선택 패널, §11.3) |
|
||||
|
||||
## 2. 구조와 재사용
|
||||
|
||||
```
|
||||
SWProcessHeader <header class="hm-sw-theme hm-sw-process-header"> 49px (면 48 + 아래 1px 배경)
|
||||
├─ SWHeaderHome 재사용 — 9-slice 홈 도형(Strana HomeFace/HomeBorder/HomeShadow와 같은 경로·gradient·그림자)
|
||||
├─ SWHeaderDocumentTitle 재사용 — 파일명 면(DocFace / DocBorder = SW 문서 토큰과 같은 값)
|
||||
├─ __center
|
||||
│ ├─ SWProcessBar 신규
|
||||
│ └─ __layer 면 SW 객체 면 토큰(ObjFace / LayerFaceBorder와 같은 값)
|
||||
│ └─ Layer 필드 신규 내부 — 전구는 SWHeaderLayerToggle(내부) 재사용, Strana 전구와 같은 그림
|
||||
└─ __window DocFace 면 + DocBorder 1px
|
||||
├─ SWToolGroup pill 재사용(`tools` 슬롯을 감쌈) — 테두리·면만 Strana 값으로 범위 안에서 조정
|
||||
├─ 창 이동 재사용 — SWHeaderWindowControls(창 이동만): 줄무늬 · 아이콘 · 1.4s Hover Motion · 툴팁
|
||||
└─ 캡션 버튼 3개 신규 내부 — 최소화 · 최대화/복원 · 종료
|
||||
```
|
||||
|
||||
`SWHeaderLayerControl`·`SWHomeMenu`는 쓰지 않습니다(빈 20px 칸, 2단 타일 메뉴가 Strana와 달라서). `SWHeaderWindowControls`는 창 이동만 쓰고(`showMinimize`·`showClose` false), 최소화·최대화/복원·종료는 이 Header의 캡션 버튼입니다(2026-11-03 변경, §10).
|
||||
|
||||
## 3. 레이아웃·반응형
|
||||
|
||||
Strana Grid의 별 비율을 CSS flex 비율로 옮겼습니다. 숨김 단계·More는 없습니다(Strana와 같음). 보장 폭은 1100px 이상이며 그보다 좁으면 Header 안에서 잘립니다.
|
||||
|
||||
| 영역 | Strana | 구현 |
|
||||
|---|---|---|
|
||||
| 홈 | 106 × 48, 오른쪽 17px이 파일명 위로 겹침 | **SWHeader 우선(2026-11-03):** `SWHeaderHome` 그대로 = 12 + 로고 칸(높이 17, 로고 비율 폭) + 36, 32 × 17 로고 → 80. 오른쪽 15px이 파일명과 겹친 뒤 2px 간격(SWHeader bar gap, `margin-right: -15px`). `logoText`는 18px 700, 58px 칸(→ 106) |
|
||||
| 파일명 | `286*`, 최소 100, 최대 286, 글자 시작 22 | 폭만 Strana: `flex: 286 1 0`, `min-width: 100px`, `max-width: 286px`. 글자는 SWHeader 그대로(x 65 시작, padding 5 / 12 → 글자 x 70, 14px 700·자간 0.84px·SW 외곽선·세로 가운데), SW 화살표 숨김 |
|
||||
| 가운데 | `1260*` | `flex: 1260 1 0` |
|
||||
| 프로세스 | `1003*` | `flex: 1003 1 0` |
|
||||
| Layer 면 | `257*`, 최소 152, 최대 257, 양옆 1 | `flex: 257 1 0`, 칸 152 ~ 257, 면은 칸 안 양옆 1px(150 ~ 255, 가상 요소), 높이 48, radius 6 |
|
||||
| Layer 필드 | 면 안 양옆 8, 최대 234 × 38, padding 12 / 10 | 같음(가운데 정렬) |
|
||||
| 창 영역 | Auto: pill(위·왼쪽 3, 높이 42) + 창 이동 88 + 버튼 32 × 3 | 같음(약 313px, 도구 3개 기준) |
|
||||
| 프로세스 그룹 | 자연 폭까지, 좁아지면 자연 폭 비율로 함께 줄어듦, 양옆 남는 폭은 같게 | 그룹 `flex: 0 1 auto`(flex-shrink가 기본 폭에 비례), 양옆 `flex: 1 1 0` |
|
||||
| 단계 탭 | UniformGrid, 넓을 때 127 + 간격 1, 좁으면 0까지 | flex 한 줄 `flex: 1 1 0`(같은 폭), 크기 기준 요소 127px, 선택 탭도 함께 축소(§11.1) |
|
||||
|
||||
## 4. 프로세스 영역 규칙
|
||||
|
||||
| 요소 | 규칙 |
|
||||
|---|---|
|
||||
| 바탕 | ProcessBase 세로 gradient, DocBorder 1px, 위 모서리 6 |
|
||||
| 비활성 덮개 | 비활성 그룹 위 `--hm-sw-process-dim`. 왼쪽 남는 폭 = 첫 그룹, 오른쪽 남는 폭 = 마지막 그룹 밝기. 화살표 칸: 꼭지(앞 그룹 비활성) / 홈(뒤 그룹 비활성) |
|
||||
| 활성 그룹 면 | 기운 왼쪽 변 + 둥근 아래 모서리 도형(ProcessGlowLeft), 화살표 쪽으로 사라짐, 발광 Halo + 가장자리 빛. 첫 그룹은 왼쪽 40px, 마지막 그룹은 좌우 반전·오른쪽 44px 밖으로 |
|
||||
| 비활성 그룹 면 | ProcessIdleLeft 도형, Blur + 어두운 Halo + 테두리 빛, 바깥쪽에서 안쪽으로 사라짐(첫 그룹 79.8 → 198.4, 마지막 그룹 236.7 → 273.1) |
|
||||
| 사다리꼴 배치(확정 2026-11-03) | 그룹 면(사다리꼴)은 프로세스 영역의 **시작(첫 그룹)과 끝(마지막 그룹)에만** 둡니다. 그 그룹이 켜져 있으면 발광 면, 아니면 비활성 면. 가운데 그룹에는 켜져 있어도 도형이 없고 밝은 바탕(덮개 없음)만 보입니다(Figma 873:17421). 그룹 수와 관계없이 같으며 `default`·`multi` 공통. 화살표·비활성 덮개·선택 상태는 그대로 |
|
||||
| 화살표 | 16 × 48, 앞 그룹 활성 = On(채움 #27D9A5), 아니면 Dim(채움 25%, 선 50%) |
|
||||
| 번호 / 이름 | 12px, 줄 높이 14. 번호 500 `#69C2A6`. 이름 최대 56px 줄바꿈, 활성 700 흰색 / 비활성 500 `#C3EBDF`, 폭은 늘 700 기준. 위 여백 10.67(한 줄) / 8.67(두 줄) |
|
||||
| 탭 | 높이 32, padding 0 12 2.67, 16px 700 `#F0F7F5`. 모서리: 단독 16, 첫 탭 16 4 4 16, 마지막 탭 4 16 16 4, 가운데 4 |
|
||||
| 탭 상태 | 기본 층 Opacity 0.7. Hover = 글자 `#FFC600`. Checked = 층 1, 바탕·그늘·광택 교체, 위 5 · 왼쪽 6 안쪽 그림자 0.75, 테두리 2px 0.25, 글자 `#FFC600`. Disabled = 층 0.5, 글자 `#64A491` |
|
||||
|
||||
Strana의 2그룹(01 Modeling: Structure · Loads / 02 Analysis Result: Results)이 확정 디자인입니다. 1그룹·3그룹 이상은 렌더링되지만 디자인 미확정입니다.
|
||||
|
||||
## 5. HM 규칙 적용으로 바뀐 점 (원본 대비 변경)
|
||||
|
||||
| 항목 | Strana 원본 | 구현 | 근거 |
|
||||
|---|---|---|---|
|
||||
| 파일명 | TextBox(말줄임 없음, 편집 가능하나 반영 안 됨) | 버튼 + 말줄임, `title`로 전체 이름 | 승인 7 |
|
||||
| Focus | 표시 없음(FocusVisual null) | SW 2px `#F0F7F5` outline | 승인 7 |
|
||||
| 글자 외곽선 | DropShadow Blur 2 | SW `--hm-sw-header-text-outline`(14·16·18px) / `--hm-sw-header-label-outline`(10·12px). `multi`도 같음(Figma에는 Stroke 없음) | 승인 7, 2026-11-03 요청 |
|
||||
| 창 이동 | 정적 장식(Motion 없음) | SWHeader 창 이동 Motion(1.4s 반복, Hover 해제 즉시 복원, 툴팁 `창 이동`, Drag 중 정지, Reduced Motion 정적) | 2026-11-03 요청(이전 승인 5의 "Motion 없음"을 대체) |
|
||||
| 파일명 자간 | 0 | 0.06em(재사용한 SW 파일명 면) | 재사용 부품 |
|
||||
| Layer 필드 | ToggleButton 안에 전구 ToggleButton 중첩 | 형제 button 2개(전구 · 필드), 보이는 모양 같음 | HTML은 버튼 중첩 불가 |
|
||||
| 탭 3개 이상 가운데 탭 | 정의 없음(첫 탭 외 모두 오른쪽 모서리) | 모서리 4 | 일반화 |
|
||||
| 테마 | 4개(Hanmac · Dark · Light · HighContrast) | Hanmac 값만 기본값, 나머지는 §7 Override | 승인 4, Light/Dark preset 금지 |
|
||||
| 로고 메뉴 · Layer Popup | 있음 | 1차 범위 제외(버튼 상태·Callback만) | 승인 6 |
|
||||
| 화면 분할 버튼 · 선택 Popup | 있음 | `SWProcessSplitButton`으로 추가(2026-11-03, §11). 버튼 아래 연장을 Header 끝까지 늘려 패널이 Header 아래에서 시작(Strana는 3px — 창 버튼 아래 끝을 가림) | 2026-11-03 요청 |
|
||||
| 도구 아이콘 | DesignSystem Geometry | Storybook fixture(`src/sw/sw-process-header-fixture.tsx`)의 TSX 아이콘, 패키지는 `tools` 슬롯. 상태 색은 `currentColor` | 승인 8 |
|
||||
| 좁은 폭의 탭 글자 · Layer 이름 | 잘림(Clip) | `…` 말줄임 | HM 말줄임 규칙(승인 7과 같은 기준) |
|
||||
| 그림 자산 | XAML Geometry · DrawingBrush | 파일 대신 인라인 SVG(TSX)와 CSS — 색을 토큰으로 바꿀 수 있게 | 승인 4(토큰 Override) |
|
||||
| 도구 버튼 눌림 | 노란 링 + 아이콘 `#FFC600` | 같음. `SWToolButton` pill에는 눌림 모양이 없어 이 Header 범위 안에서만 더함(`SWHeader`의 pill은 그대로) | 원본 재현 |
|
||||
| 발광 · Blur | WPF DropShadow 30 / 15, Blur 10 / 8 / 2 | CSS `drop-shadow` 30 / 15px, `blur` 5 / 4 / 1px(반경 → 표준편차) | 근사값 — 1920 캡처 비교로 확인 |
|
||||
|
||||
## 6. 토큰
|
||||
|
||||
새 토큰은 `--hm-sw-process-*`이며 `sw-process-header.css`의 가장 바깥 SW 범위(`sw-footer.css`와 같은 규칙)에 선언합니다. 값이 SW 토큰과 같은 곳은 SW 토큰을 그대로 읽습니다(파일명 면·테두리, 객체 면·테두리, 속성 필드 면·그림자, Hover gradient, 선택 `#FFC600`, 제목·글자, 창 이동 줄무늬, 창 버튼 글리프·Hover 배경).
|
||||
|
||||
전체 목록과 Strana 원본 키는 §7 표의 왼쪽 두 열을 봅니다.
|
||||
|
||||
## 7. Strana 테마 → 토큰 Override 대응표
|
||||
|
||||
Hanmac 열이 기본값입니다. 다른 테마는 Header의 `style`(가장 바깥 SW 범위)에 같은 토큰을 지정합니다. 예: `style={{ "--hm-sw-header-selected-color": "#FFC833" }}`. Strana ARGB `#AARRGGBB`는 CSS `rgba()`로 바꿉니다. 아래 표는 Strana `Styles/Theme/*/Colors.xaml`(HEAD `edda3cc`)에서 생성했습니다.
|
||||
|
||||
<!-- theme-table:start -->
|
||||
| 토큰 | Strana `Color.Header.*` | Hanmac(기본값) | Dark | Light | HighContrast |
|
||||
|---|---|---|---|---|---|
|
||||
| `--hm-sw-header-background` | Background | `#060606` | `#0b0d11` | `#b9c7d7` | `#000000` |
|
||||
| `--hm-sw-header-text-color` | Text | `#f6f4f2` | `#f4f7fa` | `#1c2430` | `#ffffff` |
|
||||
| `--hm-sw-header-title-color · --hm-sw-process-tab-text` | Title | `#f0f7f5` | `#f4f7fa` | `#1c2430` | `#ffffff` |
|
||||
| `--hm-sw-header-selected-color` | Selected | `#ffc600` | `#ffc833` | `#0e54c6` | `#ffff00` |
|
||||
| `--hm-sw-header-text-outline-color` | TextOutline | `#000000` | `#000000` | `#ffffff` | `#000000` |
|
||||
| `--hm-sw-header-hover-border-gradient` | HoverBorderDark | `#a67d03` | `#a67d03` | `#2f5faf` | `#ffff00` |
|
||||
| ″ | HoverBorder | `#f2cc0f` | `#f2cc0f` | `#5c88d6` | `#ffff00` |
|
||||
| ″ | HoverBorderLight | `#fadd4f` | `#fadd4f` | `#8fb0e8` | `#ffff00` |
|
||||
| ″ | HoverBorderDeep | `#926e03` | `#926e03` | `#2f5faf` | `#ffff00` |
|
||||
| `--hm-sw-header-document-background` | DocFaceEdge | `#081813` | `#12151a` | `#c6d4e3` | `#000000` |
|
||||
| ″ | DocFaceDeep | `#09271e` | `#181c23` | `#d0dce8` | `#000000` |
|
||||
| ″ | DocFaceMid | `#0b3227` | `#1e232b` | `#d9e3ef` | `#000000` |
|
||||
| ″ | DocFaceLight | `#0e3d2f` | `#262c36` | `#e3ebf4` | `#000000` |
|
||||
| ″ | DocFaceLow | `#0a2b21` | `#1a1e25` | `#cfdae6` | `#000000` |
|
||||
| `--hm-sw-header-document-border-gradient · --hm-sw-process-base-border-gradient` | DocBorderTop | `#0e4c3a` | `#3a4250` | `#ffffff` | `#ffffff` |
|
||||
| ″ | DocBorderDark | `#041611` | `#0b0d11` | `#afbecd` | `#ffffff` |
|
||||
| ″ | DocBorderBottom | `#18503f` | `#3f4856` | `#9daec0` | `#ffffff` |
|
||||
| `--hm-sw-header-document-border-color` | DocBorderTop | `#0e4c3a` | `#3a4250` | `#ffffff` | `#ffffff` |
|
||||
| `--hm-sw-header-object-background` | ObjFaceEdge | `#144838` | `#1c2027` | `#d3dce6` | `#000000` |
|
||||
| ″ | ObjFaceLow | `#1a4536` | `#20252d` | `#dae2eb` | `#000000` |
|
||||
| ″ | ObjFaceMid | `#1f4134` | `#22272f` | `#dde5ed` | `#000000` |
|
||||
| ″ | ObjFaceDeep | `#10392d` | `#1a1e25` | `#d3dce6` | `#000000` |
|
||||
| ″ | ObjFaceLight | `#296b55` | `#353d48` | `#f0f4f8` | `#000000` |
|
||||
| ″ | ObjFaceUpper | `#1f5a47` | `#2a3039` | `#e7edf3` | `#000000` |
|
||||
| ″ | ObjFaceTop | `#124133` | `#1e232b` | `#d8e0ea` | `#000000` |
|
||||
| `--hm-sw-header-object-border-gradient` | ObjBorderTop | `#135643` | `#313843` | `#c3cfdb` | `#ffffff` |
|
||||
| ″ | ObjBorderDeep | `#0e3d2f` | `#1e232b` | `#afbecd` | `#ffffff` |
|
||||
| ″ | ObjBorderHighlight | `#34daaa` | `#74c4b4` | `#5c88d6` | `#ffffff` |
|
||||
| ″ | ObjBorderDark | `#08241c` | `#12151a` | `#afbecd` | `#ffffff` |
|
||||
| ″ | ObjBorderBottom | `#1f5e4b` | `#2e353f` | `#c3cfdb` | `#ffffff` |
|
||||
| `--hm-sw-header-property-background` | PropertyFace | `rgba(0, 0, 0, 0.451)` | `rgba(0, 0, 0, 0.451)` | `rgba(255, 255, 255, 0.349)` | `rgba(0, 0, 0, 1)` |
|
||||
| ″ | PropertyFaceLight | `rgba(0, 0, 0, 0.4)` | `rgba(0, 0, 0, 0.4)` | `rgba(255, 255, 255, 0.302)` | `rgba(0, 0, 0, 1)` |
|
||||
| `--hm-sw-header-property-shadow` | PropertyShadow | `#09271e` | `#000000` | `#5a6878` | `#000000` |
|
||||
| `--hm-sw-header-stripe-color` | Stripe | `rgba(28, 106, 81, 0.322)` | `rgba(63, 72, 86, 0.322)` | `rgba(47, 95, 175, 0.239)` | `rgba(0, 0, 0, 0)` |
|
||||
| `--hm-sw-header-window-icon-color` | WindowIcon | `#adb0af` | `#adb0af` | `#4a5868` | `#ffffff` |
|
||||
| `--hm-sw-header-window-icon-hover-color` | WindowIconHover | `#ffffff` | `#ffffff` | `#1c2430` | `#000000` |
|
||||
| `--hm-sw-header-window-button-hover-background` | WindowButtonHover | `rgba(0, 0, 0, 0.2)` | `rgba(0, 0, 0, 0.2)` | `rgba(0, 0, 0, 0.122)` | `#ffff00` |
|
||||
| `--hm-sw-header-layer-icon-hover-background` | LayerIconHover | `rgba(0, 0, 0, 0.251)` | `rgba(0, 0, 0, 0.251)` | `rgba(0, 0, 0, 0.149)` | `rgba(255, 255, 255, 0.251)` |
|
||||
| `--hm-sw-process-base-background` | ProcessBaseEdge | `#0c5941` | `#1c2027` | `#c6d4e3` | `#000000` |
|
||||
| ″ | ProcessBaseLight | `#19bf8d` | `#4a5260` | `#f0f4f8` | `#000000` |
|
||||
| ″ | ProcessBaseMid | `#109069` | `#313843` | `#d9e3ef` | `#000000` |
|
||||
| `--hm-sw-process-dim` | ProcessDim | `rgba(0, 68, 48, 0.902)` | `rgba(11, 13, 17, 0.902)` | `rgba(207, 218, 230, 0.902)` | `rgba(0, 0, 0, 0)` |
|
||||
| `--hm-sw-process-number-color` | ProcessNumber | `#69c2a6` | `#74c4b4` | `#2c5a88` | `#ffffff` |
|
||||
| `--hm-sw-process-group-color` | ProcessGroupText | `#c3ebdf` | `#c9d3de` | `#4a5868` | `#ffffff` |
|
||||
| `--hm-sw-process-group-active-color` | ProcessGroupActive | `#ffffff` | `#ffffff` | `#1c2430` | `#ffff00` |
|
||||
| `--hm-sw-process-glow-face-base` | ProcessGlowFaceTop | `#063b2b` | `#1a1e25` | `#e3ebf4` | `rgba(0, 0, 0, 0)` |
|
||||
| ″ | ProcessGlowFaceFade | `rgba(13, 101, 74, 0.051)` | `rgba(42, 48, 57, 0.051)` | `rgba(217, 227, 239, 0.051)` | `rgba(0, 0, 0, 0)` |
|
||||
| ″ | ProcessGlowInner | `rgba(24, 134, 101, 0.702)` | `rgba(63, 111, 104, 0.702)` | `rgba(92, 136, 214, 0.702)` | `rgba(0, 0, 0, 0)` |
|
||||
| ″ | ProcessGlowInnerFade | `rgba(24, 134, 101, 0)` | `rgba(63, 111, 104, 0)` | `rgba(92, 136, 214, 0)` | `rgba(0, 0, 0, 0)` |
|
||||
| `--hm-sw-process-glow-face-rim` | ProcessGlowRim | `#247a60` | `#3f6f68` | `#5c88d6` | `rgba(0, 0, 0, 0)` |
|
||||
| ″ | ProcessGlowFaceFade | `rgba(13, 101, 74, 0.051)` | `rgba(42, 48, 57, 0.051)` | `rgba(217, 227, 239, 0.051)` | `rgba(0, 0, 0, 0)` |
|
||||
| `--hm-sw-process-glow-face-sheen` | ProcessGlowSheenTop | `#20322c` | `#1e232b` | `#ffffff` | `rgba(0, 0, 0, 0)` |
|
||||
| ″ | ProcessGlowSheen | `#3dc79d` | `#74c4b4` | `#8fb0e6` | `rgba(0, 0, 0, 0)` |
|
||||
| ″ | ProcessGlowSheenFade | `rgba(61, 199, 157, 0.051)` | `rgba(116, 196, 180, 0.051)` | `rgba(143, 176, 230, 0.051)` | `rgba(0, 0, 0, 0)` |
|
||||
| ″ | ProcessGlowTint | `rgba(0, 95, 66, 0.251)` | `rgba(42, 48, 57, 0.251)` | `rgba(92, 136, 214, 0.251)` | `rgba(0, 0, 0, 0)` |
|
||||
| `--hm-sw-process-glow-halo (× 0.85)` | ProcessGlowHalo | `#58b599` | `#74c4b4` | `#5c88d6` | `#000000` |
|
||||
| `--hm-sw-process-glow-edge (× 0.65)` | ProcessGlowEdge | `#58b599` | `#74c4b4` | `#5c88d6` | `rgba(0, 0, 0, 0)` |
|
||||
| `--hm-sw-process-idle-face` | ProcessIdleInset | `rgba(0, 0, 0, 0.502)` | `rgba(0, 0, 0, 0.502)` | `rgba(0, 0, 0, 0.149)` | `rgba(0, 0, 0, 0)` |
|
||||
| ″ | ProcessIdleInsetFade | `rgba(0, 0, 0, 0)` | `rgba(0, 0, 0, 0)` | `rgba(0, 0, 0, 0)` | `rgba(0, 0, 0, 0)` |
|
||||
| ″ | ProcessIdleShade | `rgba(23, 42, 26, 0.251)` | `rgba(0, 0, 0, 0.2)` | `rgba(47, 74, 110, 0.078)` | `rgba(0, 0, 0, 0)` |
|
||||
| `--hm-sw-process-idle-halo (× 0.8)` | ProcessIdleHalo | `#11694f` | `#3a4656` | `#8fb0e6` | `rgba(0, 0, 0, 0)` |
|
||||
| `--hm-sw-process-idle-rim` | ProcessIdleRim | `rgba(4, 128, 90, 0.322)` | `rgba(116, 196, 180, 0.302)` | `rgba(255, 255, 255, 0.4)` | `rgba(0, 0, 0, 0)` |
|
||||
| `--hm-sw-process-arrow-fill` | ProcessArrowFill | `#27d9a5` | `#74c4b4` | `#5c88d6` | `rgba(0, 0, 0, 0)` |
|
||||
| `--hm-sw-process-arrow-dim-fill` | ProcessArrowDimFill | `#abc7bf` | `#c9d3de` | `#8fa3b8` | `rgba(0, 0, 0, 0)` |
|
||||
| `--hm-sw-process-arrow-fill-fade` | ProcessArrowFillFade | `rgba(16, 109, 81, 0)` | `rgba(42, 48, 57, 0)` | `rgba(217, 227, 239, 0)` | `rgba(0, 0, 0, 0)` |
|
||||
| `--hm-sw-process-arrow-edge` | ProcessArrowEdge | `#00432e` | `#1a1e25` | `#afbecd` | `#ffffff` |
|
||||
| `--hm-sw-process-arrow-mid` | ProcessArrowMid | `#1c6a51` | `#4a5260` | `#5c88d6` | `#ffffff` |
|
||||
| `--hm-sw-process-arrow-light` | ProcessArrowLight | `#3d9c7e` | `#5e8f87` | `#8fb0e6` | `#ffffff` |
|
||||
| `--hm-sw-process-arrow-shadow` | ProcessArrowShadow | `rgba(0, 0, 0, 0.502)` | `rgba(0, 0, 0, 0.502)` | `rgba(255, 255, 255, 0.502)` | `rgba(0, 0, 0, 0)` |
|
||||
| `--hm-sw-process-shade · -shade-mid · -shade-fade` | ProcessShade | `rgba(4, 34, 25, 0.878)` | `rgba(11, 13, 17, 0.878)` | `rgba(175, 190, 205, 0.878)` | `rgba(0, 0, 0, 0)` |
|
||||
| ″ | ProcessShadeMid | `rgba(4, 34, 25, 0.706)` | `rgba(11, 13, 17, 0.706)` | `rgba(175, 190, 205, 0.706)` | `rgba(0, 0, 0, 0)` |
|
||||
| ″ | ProcessShadeFade | `rgba(4, 34, 25, 0)` | `rgba(11, 13, 17, 0)` | `rgba(175, 190, 205, 0)` | `rgba(0, 0, 0, 0)` |
|
||||
| `--hm-sw-process-tab-glow` | TabGlow | `rgba(31, 148, 113, 0.702)` | `rgba(74, 82, 96, 0.702)` | `rgba(255, 255, 255, 0.702)` | `rgba(0, 0, 0, 0)` |
|
||||
| `--hm-sw-process-tab-depth` | TabDepthFade | `rgba(0, 61, 41, 0)` | `rgba(26, 30, 37, 0)` | `rgba(198, 212, 227, 0)` | `rgba(0, 0, 0, 1)` |
|
||||
| ″ | TabDepth | `rgba(0, 61, 41, 0.8)` | `rgba(26, 30, 37, 0.8)` | `rgba(198, 212, 227, 0.8)` | `rgba(0, 0, 0, 1)` |
|
||||
| `--hm-sw-process-tab-shade` | TabShade | `rgba(0, 0, 0, 0.4)` | `rgba(0, 0, 0, 0.4)` | `rgba(0, 0, 0, 0.149)` | `rgba(0, 0, 0, 0)` |
|
||||
| ″ | TabShadeFade | `rgba(0, 0, 0, 0)` | `rgba(0, 0, 0, 0)` | `rgba(0, 0, 0, 0)` | `rgba(0, 0, 0, 0)` |
|
||||
| `--hm-sw-process-tab-sheen` | TabSheen | `rgba(74, 255, 196, 0.502)` | `rgba(116, 196, 180, 0.502)` | `rgba(255, 255, 255, 0.502)` | `rgba(0, 0, 0, 0)` |
|
||||
| ″ | TabSheenFade | `rgba(74, 255, 196, 0)` | `rgba(116, 196, 180, 0)` | `rgba(255, 255, 255, 0)` | `rgba(0, 0, 0, 0)` |
|
||||
| `--hm-sw-process-tab-border-gradient` | TabBorder | `#001e15` | `#0b0d11` | `#9daec0` | `#ffffff` |
|
||||
| ″ | TabStrokeHighlight | `#17a77b` | `#4a5260` | `#ffffff` | `#ffffff` |
|
||||
| ″ | TabStrokeLow | `#0b533d` | `#262c36` | `#9daec0` | `#ffffff` |
|
||||
| `--hm-sw-process-tab-ring` | TabRing | `rgba(0, 0, 0, 0.251)` | `rgba(0, 0, 0, 0.251)` | `rgba(255, 255, 255, 0.251)` | `rgba(0, 0, 0, 0)` |
|
||||
| `--hm-sw-process-tab-active-base` | TabActiveBase | `rgba(0, 0, 0, 0.4)` | `rgba(0, 0, 0, 0.4)` | `rgba(255, 255, 255, 0.4)` | `rgba(0, 0, 0, 1)` |
|
||||
| ″ | TabActiveBaseDeep | `rgba(0, 0, 0, 0.451)` | `rgba(0, 0, 0, 0.451)` | `rgba(255, 255, 255, 0.451)` | `rgba(0, 0, 0, 1)` |
|
||||
| `--hm-sw-process-tab-active-shade` | TabActiveShade | `rgba(0, 0, 0, 0.6)` | `rgba(0, 0, 0, 0.6)` | `rgba(92, 136, 214, 0.2)` | `rgba(0, 0, 0, 0)` |
|
||||
| ″ | TabShadeFade | `rgba(0, 0, 0, 0)` | `rgba(0, 0, 0, 0)` | `rgba(0, 0, 0, 0)` | `rgba(0, 0, 0, 0)` |
|
||||
| `--hm-sw-process-tab-active-sheen` | TabActiveSheenFade | `rgba(122, 206, 179, 0)` | `rgba(116, 196, 180, 0)` | `rgba(92, 136, 214, 0)` | `rgba(0, 0, 0, 0)` |
|
||||
| ″ | TabActiveSheen | `rgba(122, 206, 179, 0.102)` | `rgba(116, 196, 180, 0.102)` | `rgba(92, 136, 214, 0.102)` | `rgba(0, 0, 0, 0)` |
|
||||
| `--hm-sw-process-tab-inset (끝은 투명)` | TabInset | `rgba(0, 0, 0, 0.659)` | `rgba(11, 13, 17, 0.659)` | `rgba(175, 190, 205, 0.659)` | `rgba(0, 0, 0, 0)` |
|
||||
| ″ | TabInsetFade | `rgba(0, 0, 0, 0)` | `rgba(11, 13, 17, 0)` | `rgba(175, 190, 205, 0)` | `rgba(0, 0, 0, 0)` |
|
||||
| `--hm-sw-process-tab-disabled-shade` | TabShadeFade | `rgba(0, 0, 0, 0)` | `rgba(0, 0, 0, 0)` | `rgba(0, 0, 0, 0)` | `rgba(0, 0, 0, 0)` |
|
||||
| ″ | TabDisabledShade | `rgba(0, 0, 0, 0.8)` | `rgba(0, 0, 0, 0.8)` | `rgba(0, 0, 0, 0.2)` | `rgba(0, 0, 0, 0)` |
|
||||
| `--hm-sw-process-tab-disabled-sheen` | TabDisabledSheen | `rgba(130, 181, 164, 0.502)` | `rgba(128, 142, 156, 0.502)` | `rgba(255, 255, 255, 0.502)` | `rgba(0, 0, 0, 0)` |
|
||||
| ″ | TabActiveSheenFade | `rgba(122, 206, 179, 0)` | `rgba(116, 196, 180, 0)` | `rgba(92, 136, 214, 0)` | `rgba(0, 0, 0, 0)` |
|
||||
| `--hm-sw-process-tab-disabled-text` | TabDisabledText | `#64a491` | `#6d7784` | `#8a97a6` | `#a0a0a0` |
|
||||
| `--hm-sw-process-layer-border-gradient` | PropertyBorder | `#08251c` | `#12151a` | `#afbecd` | `#ffffff` |
|
||||
| ″ | ObjBorderDeep | `#0e3d2f` | `#1e232b` | `#afbecd` | `#ffffff` |
|
||||
| ″ | LayerFieldBorderHighlight | `#1e7c60` | `#4a5260` | `#ffffff` | `#ffffff` |
|
||||
| ″ | ObjBorderDark | `#08241c` | `#12151a` | `#afbecd` | `#ffffff` |
|
||||
| ″ | ToolBorderBottom | `#051612` | `#0b0d11` | `#9daec0` | `#ffffff` |
|
||||
| `--hm-sw-process-pill-background` | PillFaceTop | `rgba(0, 0, 0, 0.851)` | `rgba(0, 0, 0, 0.851)` | `rgba(224, 228, 232, 0.851)` | `rgba(0, 0, 0, 1)` |
|
||||
| ″ | PillFace | `rgba(0, 0, 0, 0.8)` | `rgba(0, 0, 0, 0.8)` | `rgba(246, 249, 252, 0.8)` | `rgba(0, 0, 0, 1)` |
|
||||
| `--hm-sw-process-pill-border-gradient` | PillBorder | `#092920` | `#1a1e25` | `#afbecd` | `#ffffff` |
|
||||
| ″ | PillBorderBottom | `#1c6f56` | `#313843` | `#c3cfdb` | `#ffffff` |
|
||||
| `--hm-sw-process-tool-border-gradient` | PropertyBorder | `#08251c` | `#12151a` | `#afbecd` | `#ffffff` |
|
||||
| ″ | ToolBorderHighlight | `#208769` | `#4a5260` | `#ffffff` | `#ffffff` |
|
||||
| ″ | ObjBorderDark | `#08241c` | `#12151a` | `#afbecd` | `#ffffff` |
|
||||
| ″ | ToolBorderBottom | `#051612` | `#0b0d11` | `#9daec0` | `#ffffff` |
|
||||
| `--hm-sw-process-tool-icon-color` | Icon | `#b6d0c9` | `#c9d3de` | `#26303c` | `#ffffff` |
|
||||
| `--hm-sw-process-close-hover-background` | CloseHover | `#e40000` | `#e40000` | `#e40000` | `#ff0000` |
|
||||
| `--hm-sw-process-close-icon-hover` | CloseIconHover | `#ffffff` | `#ffffff` | `#ffffff` | `#ffffff` |
|
||||
| `--hm-sw-process-tool-open-background` | ToolOpenEdge | `#081813` | `#0b0d11` | `#dce4ed` | `#000000` |
|
||||
| ″ | ToolOpenMid | `#0b3227` | `#171b21` | `#e8eef5` | `#000000` |
|
||||
| ″ | ToolOpenCenter | `#0e3d2f` | `#1e232b` | `#f3f6fa` | `#000000` |
|
||||
| `--hm-sw-process-tool-open-edge` | ToolOpenEdge | `#081813` | `#0b0d11` | `#dce4ed` | `#000000` |
|
||||
| `--hm-sw-process-split-panel-background` | SplitPanelFace | `#082018` | `#14171c` | `#ffffff` | `#000000` |
|
||||
| `--hm-sw-process-split-cell-pane` | SplitCellPane | `#1b6b53` | `#3a4656` | `#e3ebf4` | `#000000` |
|
||||
| `--hm-sw-process-split-icon-pane` | IconCell | `#003425` | `#12151a` | `#afbecd` | `#000000` |
|
||||
|
||||
그라데이션 토큰은 여러 키의 조합입니다. 같은 위치(stop)에 테마 값을 넣어 토큰 전체를 지정합니다. 다음 키는 토큰이 아닙니다: `HomeFaceBottom`, `HomeFaceDeep`, `HomeFaceMid`, `HomeFaceTop`, `HomeBorderTop`, `HomeBorderLight`, `HomeBorderDark`, `HomeBorderBottom`, `HomeShadow`, `IconOutline`, `WindowMoveIcon`, `LayerBulbBase`, `LayerBulbBar`, `LayerBulbOnLight`, `LayerBulbOnMid`, `LayerBulbOnDark`, `LayerBulbOffLight`, `LayerBulbOffMid`, `LayerBulbOffDark`(SW 홈·전구·창 이동 그림 자산 — 테마 Override 대상 아님, Hanmac 그림), `IconScreen`, `IconScreenDeep`, `IconMonitorScreen`(Strana 도구 아이콘 전용 — 도구 아이콘은 소비 측이 그림).
|
||||
<!-- theme-table:end -->
|
||||
|
||||
## 8. 검증
|
||||
|
||||
2026-11-03 1차 구현(Chromium, Storybook 6024).
|
||||
|
||||
| 항목 | 결과 |
|
||||
|---|---|
|
||||
| 폭 측정(파일명 / 프로세스 / Layer 칸 / 창 영역) | 1920: 280.8 / 984.8 / 252.3 / 313 = Strana 별 비율 계산값. 1100: 129.1 / 416.9 / 152(최소) / 313. 1366: 178.3 / 625.4 / 160.3 / 313. 2560: 286(최대) / 1615 / 257(최대) / 313. 넘침 없음. 홈 80(SWHeader 기준, 2026-11-03) 이후 파일명 / 프로세스: 1100 133.7 / 437, 1366 182.9 / 641.4, 1920 285.4 / 1000.8, 2560 286 / 1639.7, 창 영역 312, 넘침 없음 |
|
||||
| Strana 캡처 비교(1.5배, 나란히) | Hanmac 1920 Modeling · Results, 1366, 1100 — 배치·면·발광·화살표·탭·Layer·도구·창 버튼 일치. 차이: 글자 외곽선 두께, 파일명 자간, 좁은 폭의 말줄임(§5) |
|
||||
| 동작 | 탭 클릭·Arrow·Home·End(비활성 건너뜀), 같은 탭 재클릭 시 Callback 없음, 전구·필드 분리, 최대화/복원 전환, 로고 열림 모양, 도구 눌림 모양, Hover(종료 `#E40000`, 최소화, Layer 링, 탭 글자), Focus outline |
|
||||
| 기존 `SWHeader` | 변경 전후 빌드에서 `SW/Header` Overview · Responsive More 출력 HTML 동일, `dist/styles.css`의 기존 내용 동일(새 규칙만 추가) |
|
||||
|
||||
Strana 비교 캡처는 `D:\Strana\_verification\header-rework-20261029\renders\Hanmac-{1100,1366,1920}-*.png`(최종 Commit 7173e82 · b7f412c 이전 렌더)입니다. 분할 버튼 변경(b7f412c) 이후 최신 캡처와 다른 테마(Dark · Light · HighContrast)의 화면 비교는 미확인입니다. Firefox · Safari는 확인하지 않았습니다.
|
||||
|
||||
## 9. `appearance="multi"` — StrAna-SW 다중 Step (2026-11-03)
|
||||
|
||||
원본: Figma StrAna-SW `4y8lTK1E1hAGYiMcYZwuNe`, 노드 `873:16481` · `873:16254` · `873:17421`(각 1920 × 49). Story: `SW / Step Header › Step Header`(Step Header 섹션 = `default` + Multi Step 섹션 = 세 시안, 노드 ID는 화면에 표시하지 않고 `data-figma-node`로만 유지), `Responsive`, 검증용(숨김) `Multi Step`(세 시안 1920) · `화면 분할` · `Fixed Widths` · `Process Bar` · `Many Groups` · `Many Steps` · `States` · `Theme Override`.
|
||||
|
||||
### 9.1 시안 비교
|
||||
|
||||
세 시안은 **같은 구조의 상태 차이**입니다. 그래서 별도 컴포넌트 없이 `SWProcessHeader` / `SWProcessBar`의 `appearance="multi"` 하나로 구현했습니다.
|
||||
|
||||
| 시안 | 파일명 면 | 켜진 그룹 · 선택 단계 | 그룹 상태 |
|
||||
|---|---|---|---|
|
||||
| 873:16481 | 파일 없음: `프로젝트 생성 전` 10px 700 `#AEDBCC` 오른쪽 위 | 01 데이터 구축 · 데이터입력 | 2·3 미진행(70%), 4·5 비활성(회색) |
|
||||
| 873:16254 | 파일명 14px 700 `#F0F7F5`, 말줄임. 위치·여백은 SWHeader 우선(글자 x 70, padding 5 / 12, 자간 0.84px) | 01 데이터 구축 · 데이터입력 | 같음 |
|
||||
| 873:17421 | 파일 없음 | 03 구조물 상세 및 계획 · 본체계획 | 1·2 진행 완료(덮개 + 밝은 탭), 4·5 비활성 |
|
||||
|
||||
### 9.2 `default`와 공유한 것 / 다른 것
|
||||
|
||||
- **사다리꼴 배치:** 시작·끝 그룹에만(§4 확정 규칙). 873:17421처럼 가운데 그룹이 켜지면 도형 없이 밝은 바탕만 보입니다(2026-11-03 수정 — 이전 구현은 켜진 가운데 그룹에도 발광 면을 그렸음).
|
||||
- **같은 구현(값 대조 일치):** 프로세스 바탕(ProcessBase gradient · DocBorder · 위 모서리 6), 비활성 덮개(`#004430` 90%, 꼭지·홈 모양 포함), 활성 발광 면·비활성 바깥 면(같은 경로), 화살표(선·채움·그늘 같은 값, Dim 25% / 50%), 홈 도형, 파일명 면 gradient, 창 이동 아이콘·줄무늬 색, 캡션 버튼 글리프, 선택·키보드·Callback.
|
||||
- **multi 전용 CSS:** 49px 면, 파일명 최대 189·단색 테두리(로고·파일명 글자는 SWHeader 기준으로 default와 공통), SW 기본 pill(41 · 40 × 37), 창 이동 위치, 그룹 내용(제목 위 · 탭 25), 탭 4상태, 발광 면 위치(왼쪽 50 / 반전 48).
|
||||
- **새로 만든 것:** 진행 완료 상태(`data-progress="done"`, multi만), `documentEmptyLabel`, `labelHidden`, `appearance`. 컴포넌트 DOM은 하나이며 multi는 탭의 층 9개 대신 면 하나만 그립니다.
|
||||
- **Figma 도구 아이콘 5개**(help · view-3d · controls · menu-list · exit-arrow)는 Story fixture(`src/sw/assets/process-header/tool-*.svg`, Figma 원본)에만 둡니다.
|
||||
|
||||
### 9.3 넘침 처리 — 확정 정책(2026-11-03 사용자 승인)
|
||||
|
||||
| 항목 | 결정 | 근거 |
|
||||
|---|---|---|
|
||||
| 그룹 폭 | 자연 폭(제목·탭 중 넓은 쪽 + 좌우 10)까지, 좁으면 자연 폭 비율로 함께 축소. 남는 폭은 양쪽에 같게 | `default`와 같은 규칙 |
|
||||
| 탭 | 글자 폭 + 25, 좁으면 선택 탭 포함 글자 폭 비율로 축소 + `…`(2026-11-03 개정) | 옆 탭이 비정상적으로 좁아지지 않게 |
|
||||
| 화살표 · 그룹 사이 36 | 고정 | Figma |
|
||||
| 실제 넘침 | 그룹 접기·좌우 스크롤·More 메뉴를 두지 않음. 더 좁으면 영역 안에서 잘림 | 확정(Figma에 정의 없음) |
|
||||
|
||||
측정(1920): 5그룹 11탭은 말줄임 없음. 1366에서는 11탭 중 10개, 8그룹 · 16탭(1920)에서는 15개가 말줄임됩니다. 겹침 · 영역 밖 탭 0. (개정 후 1366에서는 선택 탭도 다른 탭과 함께 줄어 `…`가 될 수 있습니다.)
|
||||
|
||||
### 9.4 Figma와 남은 차이
|
||||
|
||||
- 873:17421의 켜진 그룹 미선택 탭은 70% · `#0C3125` · `rgba(76,167,138,.8)`, 873:16481은 100% · `#0A5940` · `rgba(68,178,143,.8)`로 시안끼리 다릅니다. 873:16481 값으로 통일했습니다.
|
||||
- 873:17421의 선택 탭에만 있는 안쪽 2px 링(`rgba(0,0,0,.25)`)은 넣지 않았습니다(873:16481 기준).
|
||||
- 비활성 글자는 `#87AD9D`(1개 탭) / `#7D9F91`(3개 탭) 두 값 중 `#7D9F91`로 통일했습니다.
|
||||
- 873:17421의 `선형입력` 위치(599)는 873:16481(592.8)과 다릅니다. 구현은 그룹 간격 36 규칙(592)입니다.
|
||||
- Figma 로고 자리는 글자 `LOGO`이며, Story는 임시 로고 이미지입니다(로고·파일명 글자는 SWHeader와 같은 크기·위치).
|
||||
- ~~창 이동 아이콘 밝기 차이~~: SWHeader 창 이동 자산으로 바꾼 뒤 Figma와 같은 밝기(2026-11-03 해소).
|
||||
- 글자 외곽선: Figma multi 시안의 글자에는 Stroke가 없으나 SW 규칙에 맞춰 외곽선을 적용했습니다(의도된 차이, §10).
|
||||
- 장치 배율 1.5에서 1px 테두리 반올림으로 창 영역이 366.3px로 측정됩니다(Figma 367).
|
||||
|
||||
## 10. SWHeader 스타일 정합 (2026-11-03)
|
||||
|
||||
`SWHeader`의 실제 구현(sw.css)과 브라우저 렌더를 기준으로 맞췄습니다. `SWHeader`·`SWViewerHeader`·`sw.css`는 바꾸지 않았고, 모두 `default`·`multi` 공통입니다.
|
||||
|
||||
| 항목 | SWHeader | Process Header(적용 결과) | 구현 |
|
||||
|---|---|---|---|
|
||||
| 글자 Stroke | 14·16px 검정 1.3px, 12px 1px(16방향 text-shadow), 말줄임 글자는 `overflow-clip-margin` 2px | 같음: 파일명·탭(선택·비선택·비활성)·Layer 값 1.3px, 그룹 제목·번호·Layer 라벨·파일 없음 표시 1px | SW 토큰 재사용. `multi`의 `text-shadow: none` 제거, 탭·제목 말줄임 글자는 clip margin 공통 |
|
||||
| 창 이동 | 88 × 48, 줄무늬, 아이콘 → Hover 시 창·커서 1.4s 반복 + 툴팁, Drag 중 정지, 해제 즉시 복원, Reduced Motion 정적 | 같음(SWHeader 부품 그대로). `multi`만 Figma 위치로 줄무늬 82 × 39(3, 5)·아이콘 3px 위 | `SWHeaderWindowControls`(창 이동만) 재사용, 정적 그림·CSS·토큰 2개 삭제 |
|
||||
| 도구 버튼 Hover | 노란 gradient 링 + 노란 아이콘(`hoverIcon` 또는 색) | 같음. Default fixture 아이콘은 `currentColor`, Multi Figma 아이콘은 `#B6D0C9 → #FFC600` Hover 그림(SW 인쇄 버튼 방식) | SWToolButton `hoverIcon`, 눌림(pressed)도 링 + 노란 아이콘 |
|
||||
| 로고 · 파일명 · 탭 Hover | 로고 금색 테두리, 파일명 글자 `#FFC600` | 같음, 탭 글자 `#FFC600`, 비활성 탭은 변화 없음 | 재사용 |
|
||||
| Layer 필드 Hover | 필드 노란 링 + 글자 `#FFC600`, 전구는 어두운 배경 | 같음 | 재사용 |
|
||||
| 최소화 · 최대화 Hover | 배경 `rgba(0,0,0,.2)` + 흰 글리프(노랑 아님) | 같음 | SW 토큰 |
|
||||
| 종료 Hover | `#E40000` + 흰 X | 같음(유지) | 확정 디자인 |
|
||||
| Focus | 2px `#F0F7F5`, -2px | 같음(탭·도구·캡션 버튼) | SW 공통 규칙 |
|
||||
| 선택 · Disabled | — | 선택 탭 `#FFC600`(Hover와 같은 색이지만 면이 다름), Disabled는 Hover·Focus 없음 | 기존 확정 디자인 |
|
||||
|
||||
## 11. 선택 Step 표시 통일 · 아이콘 · 화면 분할 (2026-11-03)
|
||||
|
||||
### 11.1 선택 Step 폭(두 appearance 공통, 2026-11-03 개정)
|
||||
|
||||
- **개정:** 선택된 탭도 다른 탭과 같은 비율로 줄어듭니다(이전 "선택 탭 전체 이름 유지" 폐기 — 선택 탭에 폭을 먼저 주느라 옆 탭이 24 · 27px까지 좁아지던 문제). 공간이 충분하면 전체 이름, 부족하면 모든 탭이 기본 폭 비율로 줄고 `…`입니다(`default` 같은 폭, `multi` 글자 폭 비례). 선택이 바뀌어도 탭 폭은 그대로입니다.
|
||||
- 그룹 최소 폭 = 좌우 여백 + (`default`만) 이름 + 모든 탭 여백 + 간격(측정). 그 위에서는 그룹이 비례로 줄고, 아래로는 줄지 않아 겹치지 않습니다.
|
||||
- 탭 배치는 두 appearance 모두 flex 한 줄입니다(이전 `default`의 grid 대체). 넓을 때 `default` 탭은 127 균등 그대로입니다.
|
||||
- 측정(개정 후, 고정 폭, `*` = 선택): `default` 1100 `*61 61 | 45`(이전 `*98 25 | 45`), 1366 `*124 124 | 124`, 1920 · 2560 `*127 127 | 127`(변화 없음). `multi` 1100 셋째 그룹 `*34 34 37 37`(이전 `*77 25 25 25`), 1366 `*54 54 61 61`(이전 `*77 47 53 53`), 1920 · 2560 `*77 77 89 89`(변화 없음). 겹침 0. 그룹 최소 폭의 합이 프로세스 영역보다 크면 영역 끝에서 잘립니다.
|
||||
|
||||
### 11.2 도구 아이콘이 사라지던 문제
|
||||
|
||||
- 원인: `sw.css`의 `:is(.hm-sw-header__action, …):hover:not(:disabled) > .hm-sw-header__icon { visibility: hidden }`는 Hover 그림(`hoverIcon`)이 있다고 가정합니다. `hoverIcon` 없이 `currentColor` 아이콘만 준 `SWToolButton`은 Hover 순간 아이콘이 비었습니다(Default 도구 3개).
|
||||
- 해결(2026-11-03 공통 수정): `SWToolButton`(pill)이 `hm-sw-header__icon` class를 `hoverIcon`이 있을 때만 기본 아이콘에 붙입니다. `hoverIcon`이 없으면 기본 아이콘이 Hover에도 그대로 보이고 색만 `#FFC600`입니다. `SWHeader`의 `tools`도 같은 컴포넌트라 함께 해결되었고, 이 Header 범위의 보완 CSS 규칙은 삭제했습니다(`sw.css` 변경 없음). 눌림은 Hover 그림이 있을 때만 그 그림으로 바뀝니다. Disabled·열림에서도 아이콘이 유지되며 크기 24 × 24로 같습니다.
|
||||
|
||||
### 11.3 화면 분할(`SWProcessSplitButton`)
|
||||
|
||||
원본: Strana `ViewportSplitSelector.xaml`, `Styles/Controls/ViewportSplitStyles.xaml`, `HeaderStyles.xaml`(ToolMenu · ToolOpenTail · ToolMenuStep · Icon.ToolLayout), MainWorkspaceWindowView 분할 Popup(HEAD `edda3cc`).
|
||||
|
||||
| 항목 | Strana | 구현 |
|
||||
|---|---|---|
|
||||
| 버튼 | 도구 버튼 40 × 38, 아이콘 = 현재 분할 모양 | `SWToolButton` pill + 분할 아이콘(Strana Geometry, 틀은 `currentColor`) |
|
||||
| 열림 | 면 ToolOpenFace, 금색 위·양옆, 아래 열림, Hover 링 없음, 아이콘 노랑 | 같음 |
|
||||
| 연장 | 버튼 아래 3px(버튼 아래 1px 겹침) | 버튼 아래 1px 겹침, 길이는 Header 끝까지(최소 3px) — 패널이 창 버튼을 가리지 않게 |
|
||||
| 패널 | 233 × 36, 면 `#082018`, 금색 양옆·아래, radius 0 2 2 2, 그림자 0 2 4 60% | 같음, Header 바로 아래·버튼 왼쪽, 화면 밖이면 좌우만 보정(SW 필드 Dropdown 위치 훅) |
|
||||
| 위 선 | 버튼 오른쪽 끝 ~ 패널 끝 금색 | 같음 |
|
||||
| 칸 | 38 × 34 × 6(Type01~06), Hover·선택 = 창 노랑, Disabled 40% | 38.5 × 34(233 / 6), 같은 그림·상태. 틀 상자는 32 × 22 정수(Strana 31.6 × 21.73, 그림 29.6 × 19.73 그대로) |
|
||||
| 동작 | Popup StaysOpen=False(바깥 클릭 닫힘), 칸 선택 시 열린 채 | 같음 + Escape 닫고 버튼으로, Tab 이탈 닫힘, ArrowDown 열기, 방향키 선택(radiogroup) |
|
||||
|
||||
값은 Props(`value`, `open`), 동작은 Callback(`onValueChange`, `onOpenChange`)이며 창을 실제로 나누는 일은 호스트가 합니다. `tools` 안에 두므로 버튼 순서는 호스트가 정하고 `default`·`multi`가 같은 컴포넌트를 씁니다. Figma 다중 Step 시안 3개에는 화면 분할 버튼이 없어 해당 Story에는 넣지 않았습니다(`Step Header` 페이지의 Step Header 섹션과 검증용 `화면 분할` Story에서 Default·Multi Step을 확인).
|
||||
|
||||
- **Popup 하단 잘림(2026-11-03, 수정):** 재현 조건 = Popup 아래 공간이 부족한 화면(예: Storybook Canvas 높이 400px의 Multi Step). 공용 위치 훅 `useSWFixedDropdownPosition`이 아래 공간이 없으면 필드 위로 뒤집는데(`flipped`), 이 선택기는 꼬리·패널을 항상 아래쪽 모양으로 그려 Header 위에 겹치고 패널 하단이 Header에 가려졌습니다(아이콘 SVG·`viewBox`·`overflow`·세로 정렬은 정상). 수정: `SWProcessSplitButton`이 뒤집힘을 쓰지 않고 항상 버튼 아래에 붙습니다(좌우 보정은 훅 그대로). 아래 공간이 부족하면 화면 끝에서 잘리지만 페이지 스크롤에 따라 위치가 갱신되어 스크롤하면 전체가 보입니다. Default·Multi 공통(같은 컴포넌트), CSS 변경 없음.
|
||||
- **아이콘 하단 잘림(2026-11-03, 수정):** 사용자 Chrome(배율 100%, 화면 1920 × 1080, Storybook 미리보기 1620 × 871)에서 재현. Responsive 1366 · 1100 행의 Popup 첫 열림에서 6개 틀이 21줄로 그려져 판 아래 밝은 테두리가 사라짐(아래가 잘린 것처럼 보임). 원인: 틀 상자 31.6 × 21.73(소수)이 화면 픽셀로 맞춰질 때 위치에 따라 21줄 또는 22줄이 되고, SVG 판은 크기가 고정이라 21줄일 때 아래 밝은 줄이 덮임. 패널 하단 테두리(`#926E03`)는 수정 전에도 그려져 있었음. 수정: 틀 상자를 32 × 22 정수로(그림 SVG·패널·위치 변경 없음). 수정 후 같은 Chrome에서 1366 · 1100 행, Default · Multi Step, 1920 고정 폭 Header 모두 틀 22줄 · 아래 밝은 줄 표시 확인.
|
||||
Reference in new issue
Block a user