feat(sw): add step header with multi-step and split layout support

This commit is contained in:
shkim4 committed 2026-11-03 14:58:53 +09:00
1 parent 6ca92c5d55
commit adbb034cb1
28 files changed
+2477 -7

No files matched your search

+45 -1
View File
@@ -4,7 +4,7 @@
## 0. 어떤 패턴을 고를까
먼저 SW 모드를 정합니다([AI_USAGE.md](./AI_USAGE.md) §0). 1~6과 8·10은 **SW 일반 모드**, 7은 **SW 뷰어 모드**이며 한 화면에서 섞지 않습니다. 11(테마 설정)은 두 모드 공통입니다.
먼저 SW 모드를 정합니다([AI_USAGE.md](./AI_USAGE.md) §0). 1~6과 8·10·12는 **SW 일반 모드**, 7은 **SW 뷰어 모드**이며 한 화면에서 섞지 않습니다. 11(테마 설정)은 두 모드 공통입니다.
| 요청 | 모드 | 패턴 |
|---|---|---|
@@ -18,6 +18,7 @@
| 일반 모드 `SWHeader`에서 로고를 누르면 열리는 2단 메뉴(저장·내보내기·찾아열기·최근파일 등) | 일반 | 8. 로고 클릭 메뉴 |
| 화면 하단 명령 막대(Line·Arc 등 명령, 분류 탭, 보조기능 토글, 명령창), Model/Layout 탭 | 일반 | 10. Footer |
| 글꼴 등 SW 토큰을 화면 전체(Header·Dropdown·More·Panel·명령창)에 같은 값으로 바꾸기, Portal 요소 포함 | 일반·뷰어 공통 | 11. 테마(토큰) 설정 |
| 프로세스 단계(01 Modeling → 02 Analysis Result 등) 탭이 있는 Header, Strana Main Header | 일반 | 12. 프로세스 단계 Header |
## 1. 완성형 SW Header — [ExampleA-DefaultHeader.tsx](./examples/ExampleA-DefaultHeader.tsx)
@@ -248,6 +249,49 @@ const appSWTheme = { "--hm-sw-header-font-family": '"Malgun Gothic", sans-serif'
- 기본 글꼴은 Noto Sans KR입니다(2026-10-20 확정). 기본값을 쓸 때는 글꼴 토큰을 지정하지 않습니다. Web UI 글꼴 토큰(`--hm-font-family-base`)을 SW 화면에 넣지 않습니다.
- `hm-sw-*` class 선택자로 토큰을 덮거나 `!important`, 컴포넌트마다 같은 값 반복 지정을 하지 않습니다.
## 12. 프로세스 단계 Header (일반 모드)
`SWHeader` 대신 쓰는 독립 Header입니다(한 화면에 Header 하나). 상태는 모두 프로그램이 갖고 Callback으로 갱신합니다. 로고 메뉴·Layer Popup·도구 Popup은 프로그램이 직접 엽니다([COMPONENT_CATALOG.md](./COMPONENT_CATALOG.md) §11).
```tsx
const groups: SWProcessGroup[] = [
{ id: "modeling", number: "01", label: "Modeling", steps: [{ id: "structure", label: "Structure" }, { id: "loads", label: "Loads" }] },
{ id: "analysis", number: "02", label: "Analysis Result", steps: [{ id: "results", label: "Results" }] },
]
<SWProcessHeader
documentTitle={fileName} logoSrc={logoUrl} logoAlt={productName} onHomeClick={toggleFileMenu} homeMenuOpen={fileMenuOpen}
process={{ groups, activeStepId: step, onStepSelect: s => setStep(s.id) }}
layer={{ label: "Layer", value: layerName, visible: layerVisible, open: layerPopupOpen }}
onLayerClick={toggleLayerPopup} onLayerVisibilityChange={setLayerVisible}
tools={<>
{/* ViewPropertyIcon: the program's own icon (the package ships no product icons). */}
<SWToolButton appearance="pill" icon={<ViewPropertyIcon />} pressed={viewProperty} onClick={toggleViewProperty}>View Property</SWToolButton>
<SWProcessSplitButton value={split} onValueChange={setSplit} open={splitOpen} onOpenChange={setSplitOpen} />
</>}
onWindowMoveStart={startWindowDrag} maximized={maximized}
onMinimize={minimize} onMaximizeToggle={toggleMaximize} onClose={closeWindow} />
```
1. 도구 아이콘은 프로그램이 그린 24 × 24 요소입니다. 버튼 상태 색(기본 `#B6D0C9`, Hover·눌림 `#FFC600`)을 따르려면 `currentColor`로 칠하고, 색이 고정된 이미지 아이콘이면 `hoverIcon`에 `#FFC600` 그림을 함께 줍니다(SW 인쇄 버튼과 같은 방식).
2. 화면 분할은 `SWProcessSplitButton`을 `tools`의 원하는 자리에 둡니다(두 appearance 공통). 고른 값으로 실제 창을 나누는 일은 프로그램이 합니다. 분할 아이콘·선택 패널을 직접 그리지 않습니다.
3. 프로세스 영역만 다른 곳에 둘 때는 `<SWTheme>` 안에 `SWProcessBar`를 둡니다.
4. 다른 테마(Strana Dark 등)는 11처럼 가장 바깥 범위 `style`에 `--hm-sw-process-*`·`--hm-sw-header-*` 토큰을 지정합니다.
5. `SWHeader`의 메뉴(레이어·색상·선/문자/치수스타일 Dropdown)를 이 Header에 넣지 않습니다. 필요하면 `SWHeader`를 씁니다.
6. **그룹·단계가 많은 다중 Step 화면**(StrAna-SW Figma 873:16481 등)은 `appearance="multi"`입니다. 같은 `process` 데이터 구조를 쓰고, 제목이 없는 그룹은 `labelHidden`, 아직 열 수 없는 단계는 `disabled`, 문서가 없을 때는 `documentTitle=""` + `documentEmptyLabel`입니다. Figma 프레임에는 Layer 필드와 최대화 버튼이 없으므로 `layer`를 주지 않고 `hiddenControls={["maximize"]}`를 씁니다. 그룹·단계가 많아도 데이터를 줄이거나 접기·스크롤·More를 만들지 않습니다(넘침 정책: 선택 단계 포함 비례 축소 + `…`, 2026-11-03 개정).
```tsx
<SWProcessHeader appearance="multi" documentTitle={projectName ?? ""} documentEmptyLabel="프로젝트 생성 전"
logoSrc={logoUrl} logoAlt={productName} onHomeClick={toggleFileMenu}
process={{ groups: [
{ id: "data", label: "데이터 구축", steps: [{ id: "input", label: "데이터입력" }, { id: "check", label: "데이터확인" }] },
{ id: "alignment", label: "선형 입력", labelHidden: true, steps: [{ id: "alignment", label: "선형입력" }] },
{ id: "analysis", label: "해석 및 성과품", labelHidden: true, disabled: true, steps: [{ id: "model", label: "해석모델" }] },
], activeStepId: step, onStepSelect: s => setStep(s.id) }}
tools={<SWToolButton appearance="pill" icon={<img src={helpIcon} alt="" />} hoverIcon={<img src={helpIconHover} alt="" />} onClick={openHelp}>도움말</SWToolButton>}
hiddenControls={["maximize"]} onWindowMoveStart={startWindowDrag} onMinimize={minimize} onClose={closeWindow} />
```
## 9. 하지 말 것
- `hm-sw-*` class를 소비 코드에 쓰거나 CSS로 덮어쓰기(토큰 변경도 class 선택자가 아니라 가장 바깥 SW 범위의 `style` — 11)