When no official public icon export covers a requested icon, the AI guides now require asking the user first: approval to use the Storybook icon or an SVG asset (3-A), or an asset / replacement choice when HMDesign has none (3-B). Creating, copying, replacing or finally omitting the icon before the answer is not allowed. Consumer-project use approval is kept separate from official package export registration. AI_GUIDE shared copies synced.
286 lines
42 KiB
Markdown
286 lines
42 KiB
Markdown
# @hm-design/sw — AI 코딩 도구 사용 안내
|
|
|
|
이 폴더(`node_modules/@hm-design/sw/ai/`)는 다른 React 프로젝트에서 AI 코딩 도구가 SW 패키지를 **재사용·조합·확장**할 때 먼저 읽는 안내서입니다. 패키지 자체에는 AI 기능이 없습니다. 아래 문서는 실제 공개 API와 CSS에서 확인한 값만 적습니다.
|
|
|
|
먼저 [AI_GUIDE.md](./AI_GUIDE.md)(HMDesign 공통: 사용 유형 Web / SW 일반·뷰어 / OrgChart / 혼합 확인, 작업 1~7단계, 패키지 분리, 결과 보고)를 읽고 사용 유형이 **SW** 또는 SW가 포함된 혼합일 때 이 폴더를 씁니다.
|
|
|
|
| 문서 | 내용 |
|
|
|---|---|
|
|
| [AI_GUIDE.md](./AI_GUIDE.md) | HMDesign 공통 진입점(모든 HMDesign 패키지에 같은 사본) |
|
|
| [COMPONENT_CATALOG.md](./COMPONENT_CATALOG.md) | 공식 공개 컴포넌트(일반 모드: Header·개별 컨트롤·Popup·도구 막대·로고 클릭 메뉴 / 뷰어 모드 §9: `SWViewer*` 전체 Export)·Props·Callback·크기·CSS 의존성 |
|
|
| [DESIGN_RULES.md](./DESIGN_RULES.md) | SW 전용 토큰·Typography·간격·Hover/Focus/Selected·Overlay·Motion·반응형·Popup 외형·도구 버튼·로고 클릭 메뉴(일반 모드 §1~10·§12), 뷰어 토큰·상태값 요약(§11) |
|
|
| [COMPOSITION_PATTERNS.md](./COMPOSITION_PATTERNS.md) | 완성형·간소화·기능 중심·확장 Header, Popup(자유 콘텐츠), 일반 모드 Header + 도구 막대(1~6), 뷰어 모드 기본 조합(7) |
|
|
| [examples/](./examples) | 공개 API만 쓰는 예제 A~J(10개). **일반 모드** A~G·I: A 완성형 Header(`ExampleA-DefaultHeader.tsx`), B 간소화 Header(`ExampleB-ViewerHeader.tsx`), C 기능 중심 Header(`ExampleC-FeatureHeader.tsx`), D 신규 컨트롤 확장(`ExampleD-SearchExtension.tsx`), E 사용자 정의 Popup(`ExampleE-CustomPopup.tsx`), F 파일 열기 + 도구 막대(`ExampleF-ViewerToolbar.tsx`), G 로고 클릭 메뉴(`ExampleG-HomeMenu.tsx`), I Footer(`ExampleI-Footer.tsx`). A~F는 독립 소비 프로젝트에서 Typecheck·Build·브라우저 검증. B·F 파일명의 "Viewer"는 과거 이름이며 일반 모드 `SWHeader` 구성. **뷰어 모드** H(`ExampleH-ViewerMode.tsx`, `SWViewer*`). **두 모드 공통** J 테마 토큰 설정(`ExampleJ-Theme.tsx`, §3.1) |
|
|
| [FOOTER.md](./FOOTER.md) | **일반 모드 하단 막대**: `SWFooter`(보조기능·바 안 명령창·명령 칸·분류 탭·명령어 전체보기), `SWFooterLayoutTabs`(Model/Layout 탭), `SWFooterCommandLine`(명령창). AI 작업 순서 1~6 |
|
|
| [VIEWER.md](./VIEWER.md) | **뷰어 모드 전용**: `SWViewerHeader`(데이터 메뉴·More·외곽선·로고 규칙), `SWViewerMenu`(Dropdown·서브메뉴·우클릭), `SWViewerPanel`(팝업 프레임 + 자유 콘텐츠). 일반 SW 모드는 `SWHeader`·`SWPopup`을 그대로 씁니다 |
|
|
|
|
## 0. SW 모드 선택 — SW 일반 모드 / SW 뷰어 모드 (코드 작성 전에 결정)
|
|
|
|
SW 패키지에는 Header·Popup 계열이 두 벌 있습니다. 화면마다 **하나의 모드**를 고르고 그 모드의 컴포넌트만 씁니다. 공통 사용 유형 확인(Web / SW / OrgChart / 혼합)은 [AI_GUIDE.md](./AI_GUIDE.md)를 따르고, 사용 유형이 SW로 정해진 뒤 이 절로 모드를 정합니다.
|
|
|
|
### 0.1 판단 순서
|
|
|
|
1. **소비 프로젝트 설정:** `AGENTS.md`·`CLAUDE.md` 등에 `HMDesign 사용 유형: SW 일반` 또는 `HMDesign 사용 유형: SW 뷰어`가 있으면 그 모드를 씁니다. 혼합(영역별)이면 SW 영역에 적힌 모드를 씁니다.
|
|
2. **요청 문구:** 설정이 없거나 `SW`만 적혀 있으면 요청을 봅니다.
|
|
- **뷰어 모드 근거:** "뷰어", "DWG/DXF 보기", "도면 뷰어", "도면 보기·열람", "읽기 전용", 도면 공간(Model/Layout) 탭·전체 보기·레이어/설정 패널 토글·불러오기 상태가 중심.
|
|
- **일반 모드 근거:** "편집", "그리기"(그리기모드), "객체 수정", 레이어·색상·선스타일·문자/치수스타일 **값 편집**, 속성Bar·"속성창" 편집이 중심.
|
|
- 근거가 한쪽에만 있고 분명할 때만 그 모드로 정합니다. 양쪽 근거가 섞여 있거나 하나라도 애매하면(예: "도면 화면", "CAD 화면 상단", "레이어 보기") **추측하지 않습니다.**
|
|
3. **그래도 모르면 코드 작성 전에 그대로 묻습니다.**
|
|
|
|
> SW 화면을 어떤 모드로 만들까요?
|
|
> 1. SW 일반 모드(편집용 `SWHeader`·`SWPopup`)
|
|
> 2. SW 뷰어 모드(`SWViewerHeader`·`SWViewerMenu`·`SWViewerPanel`)
|
|
|
|
4. 설정·요청·이전 답변으로 모드가 **이미 명확하면 다시 묻지 않습니다.** 결과 보고에 정한 모드와 근거(설정 값 / 요청 문구 / 사용자 답변)를 적습니다(§4).
|
|
|
|
### 0.2 모드별 컴포넌트와 읽을 문서
|
|
|
|
| 구분 | SW 일반 모드 | SW 뷰어 모드 |
|
|
|---|---|---|
|
|
| 용도 | 설치형·도면 **편집** SW 상단: 그리기모드, 레이어·색상·선/문자/치수스타일 선택, 속성Bar·속성창 | 도면 **보기** 화면 상단: 파일 열기·샘플, 도면 공간(Model/Layout) 탭, 전체 보기, 2.5D·배경 스위치, 레이어·설정·속성 패널 토글, 불러오기 상태 |
|
|
| 기준 | Figma 이지빔 SW `26:8944`, 49px | 참고 DWG/DXF 뷰어 실측(1440px), 52px |
|
|
| Header | `SWHeader`, 또는 `<SWTheme>` 안의 개별 컨트롤(`SWHeaderHome`, `SWHeaderDocumentTitle`, `SWHeaderLayerMenu`, `SWHeaderColorMenu`, `SWHeaderLineStyleMenu`, `SWHeaderTextStyleMenu`, `SWHeaderDimensionStyleMenu`, `SWHeaderActions`, `SWHeaderWindowControls`, `SWHeaderProperties` …) | `SWViewerHeader`(`groups` 데이터 + `trailing`), 오른쪽 끝·`custom` 버튼 `SWViewerHeaderButton`, 상태 `SWViewerStatus` |
|
|
| Dropdown | 각 필드 Dropdown(`SWHeaderLayerMenu` …) | `type: "menu"` 항목, 단독·우클릭은 `SWViewerMenu` |
|
|
| 팝업·설정창 | `SWPopup`(`titleActions`, `footer`) + `SWPopupSection` / `SWPopupRow` + `SWHeaderInput`, 레이어·색상 행 `SWPopupPropertyRow`(Header 필드 Dropdown은 Header 전용), 게이지바 `SWSlider`(`appearance`), 선택 목록 `SWSelect`, 속성창 `SWHeaderPropertyPanel`, 속성Bar `SWHeaderPropertyBar` | `SWViewerPanel`(이동·크기 조절·접기·`modal`, `headerActions`, `footer`) + `SWViewerSection` / `SWViewerField` / `SWViewerSwitch` / `SWViewerInput` / `SWViewerButton` / `SWViewerBadge` / `SWViewerHint`, 옵션 패널 게이지는 `SWSlider appearance="property"`(스타일 B, `SWViewerSlider` 아님), 선택 목록 `SWSelect`(뷰어 패널 토큰으로 표시) |
|
|
| 로고(홈) 버튼 메뉴 | `SWHeader`의 `homeMenu`(`SWHomeMenu` 데이터, 최근파일 `SWRecentFiles`, Figma 26:10591). 기본 숨김 → 로고 클릭 열기 → 다시 클릭 닫기 | **사용하지 않음.** `SWViewerHeader`에는 홈 메뉴 Props가 없고 로고 클릭은 `onHomeClick`만 호출합니다. 파일 열기는 로고 오른쪽 버튼(`onDocumentOpen`·`documentOpenLabel`), 샘플 목록은 파일명 클릭 목록(`documents`·`activeDocumentId`·`onDocumentSelect`)이며 `groups` 항목으로 만들지 않습니다([VIEWER.md](./VIEWER.md) §2) |
|
|
| 하단 Footer | `SWFooter`(+ 바 안 명령창 `command={<SWFooterCommandLine />}`, 좌표 `status`, `SWFooterLayoutTabs`, 부품 `SWFooter*`), [FOOTER.md](./FOOTER.md) | **사용하지 않음.** 뷰어 화면에는 하단 명령 막대가 없습니다. 도면 공간 탭은 `SWViewerHeader`의 `tabs` 항목 |
|
|
| 버튼·탭·토글 | `SWToolButton` / `SWToolGroup` | Header 항목 `type: "button" \| "toggle" \| "tabs" \| "switch"`, 패널 안 `SWViewerButton` |
|
|
| 아이콘 | 패키지 자산(필드 안 아이콘). 시안의 도구 아이콘 선택은 §5.2 | 프로그램 아이콘 16px, 직접 그린 아이콘은 `SWViewerIcon`으로 감쌈. 시안의 도구 아이콘 선택은 §5.2 |
|
|
| 범위 | Header 밖 부품은 `<SWTheme>` 안 | `SWViewerHeader`·`SWViewerMenu`·`SWViewerPanel`은 루트에 `hm-sw-theme`이 있어 `<SWTheme>` 불필요. 패널 컨트롤은 `SWViewerPanel` 안 |
|
|
| 토큰 | `--hm-sw-header-*`, Popup 콘텐츠 `--hm-sw-property-*` | `--hm-sw-viewer-*` + 공유 `--hm-sw-header-*`(아래 0.3) |
|
|
| 읽을 문서 | [COMPONENT_CATALOG.md](./COMPONENT_CATALOG.md) §1~8·§10·§11, [DESIGN_RULES.md](./DESIGN_RULES.md) §1~10·§12·§13·§14, [COMPOSITION_PATTERNS.md](./COMPOSITION_PATTERNS.md) 1~6·8·10·12, [FOOTER.md](./FOOTER.md), 예제 A~G·I | [VIEWER.md](./VIEWER.md), [COMPONENT_CATALOG.md](./COMPONENT_CATALOG.md) §9, [DESIGN_RULES.md](./DESIGN_RULES.md) §11, [COMPOSITION_PATTERNS.md](./COMPOSITION_PATTERNS.md) 7, [예제 H](./examples/ExampleH-ViewerMode.tsx) |
|
|
|
|
- **프로세스 단계 Header**(로고 · 파일명 · 01 Modeling → 02 Analysis Result 같은 단계 탭 · Layer 필드 · 도구 pill · 최소화 · 최대화/복원 · 종료, Strana Main Header) 요청은 일반 모드의 독립 Header `SWProcessHeader`입니다(카탈로그 §11, DESIGN_RULES §14, PATTERNS 12). 그룹·단계가 많은 다중 Step 화면(StrAna-SW)은 같은 컴포넌트의 `appearance="multi"`입니다(별도 컴포넌트를 만들지 않음). `SWHeader` 대신 쓰며 같은 화면에 함께 두지 않습니다.
|
|
- **하단 명령 막대(Footer)** 요청은 일반 모드입니다: [FOOTER.md](./FOOTER.md) §1 순서로 `SWFooter`가 있는지 확인하고, 명령·분류·보조기능·문구·아이콘만 Props로 바꿉니다. Footer 외형을 새로 그리지 않습니다.
|
|
- **일반 모드 Header에 도구 막대를 더한 구성**(로고 옆 파일 열기 + Model/Layout·Fit·2.5D 버튼을 `SWHeader`에 추가)은 **일반 모드**입니다: `SWHeader`의 `documentOpenPlacement`·`leading`·`tools` + `SWToolButton` / `SWToolGroup`(PATTERNS 6, 예제 F). "뷰어"·"도면 보기" 화면을 요청받았다면 이 구성이 아니라 뷰어 모드(`SWViewer*`)를 씁니다.
|
|
- 모드 진입·종료, 파일 처리, 도면 렌더링, 메뉴 명령 실행은 어느 모드든 **프로그램 담당**입니다.
|
|
|
|
### 0.3 모드 혼합 금지
|
|
|
|
- **한 화면에 Header 하나.** `SWHeader`·`SWProcessHeader`·`SWViewerHeader` 중 둘 이상을 같은 화면에 함께 두지 않습니다. 두 모드를 오가는 프로그램은 상태를 유지한 채 Header 컴포넌트만 바꿉니다(VIEWER.md §1).
|
|
- **뷰어 화면:** `SWHeader`에 뷰어 메뉴를 넣거나 `SWHeader`·`SWPopup`을 뷰어처럼 재스타일하지 않습니다. 뷰어 팝업은 `SWViewerPanel`입니다. 예외: 창 최소화·닫기 버전은 `SWViewerHeader`의 `trailing` 맨 끝에 `SWHeaderWindowControls`(`showWindowMove={false}`)를 그대로 둡니다(VIEWER.md §2.1, 2026-10-21).
|
|
- **일반 화면:** `SWViewerHeader`·`SWViewerMenu`·`SWViewerPanel`과 패널 컨트롤(`SWViewerSection` …)을 쓰지 않습니다.
|
|
- **로고(홈) 메뉴는 SW 일반 모드 전용:** `SWHomeMenu`·`SWHomeMenuSection`·`SWHomeMenuItem`·`SWRecentFiles`·`useSWHomeMenuClose`와 `SWHeader`의 `homeMenu`·`homeMenuOpen`·`defaultHomeMenuOpen`·`onHomeMenuOpenChange`는 일반 모드 `SWHeader` 화면에서만 씁니다. 뷰어 화면에는 홈 메뉴를 만들지 않고(`SWViewerHeader` 옆·`custom` 항목·`SWViewerPanel` 안에 넣거나 비슷하게 다시 만들지 않음), 뷰어 Header와 기능은 그대로 둡니다.
|
|
- **토큰:** `--hm-sw-viewer-*` 토큰을 일반 모드 신규 UI에 쓰지 않고, 일반 모드 전용 모양(속성창 행 `SWPopupRow`, `SWToolButton`의 `pill`·`text` 모양, 일반 필드 Dropdown)을 뷰어 신규 UI에 가져오지 않습니다. 두 토큰은 같은 범위(`.hm-sw-header`, `.hm-sw-theme`)에 함께 선언되어 있어 기술적으로 읽히지만, 읽힌다는 것이 허용을 뜻하지 않습니다.
|
|
- **공유 — 모드 혼합 아님(실제 코드가 공유하는 부분):**
|
|
- `SWViewerPanel`은 내부에서 `SWPopup` 프레임(제목 막대·제목·닫기·테두리·면)을 렌더링합니다. 뷰어에서 `SWViewerPanel`을 쓰는 것은 일반 모드 혼합이 아닙니다. 단, 뷰어 화면에서 `SWPopup`을 직접 쓰지는 않습니다.
|
|
- 두 Header는 사용자 확정 면 토큰 `--hm-sw-header-document-*`·`--hm-sw-header-object-*`·`--hm-sw-header-property-*`와 외곽선 토큰 `--hm-sw-header-text-outline*`·`--hm-sw-header-label-outline`을 공유합니다(바꾸면 두 Header가 함께 바뀜).
|
|
- 뷰어 패널 콘텐츠 토큰 일부(`--hm-sw-viewer-panel-background`·`-field-background`·`-inner-border`·`-text`·`-badge-background`, `--hm-sw-viewer-panel-switch-off`)는 `--hm-sw-property-*` 값을 참조합니다. 뷰어 신규 UI는 `--hm-sw-viewer-panel-*` 이름으로 읽습니다.
|
|
|
|
### 0.4 없는 컴포넌트 처리 (모드별 3단계)
|
|
|
|
공통 원칙은 [AI_GUIDE.md](./AI_GUIDE.md)를 따르고, SW에서는 아래 값을 씁니다.
|
|
|
|
| 단계 | SW 일반 모드 | SW 뷰어 모드 |
|
|
|---|---|---|
|
|
| ① 기존 재사용 | `SWHeader` Props(`hiddenControls`·`menuOrder`·`controls`·`documentOpenPlacement`·`leading`·`tools`) → 개별 컨트롤 조합 → `SWPopup` children → `SWToolButton` / `SWToolGroup` | `SWViewerHeader`의 `groups` 항목(`button`·`toggle`·`menu`·`tabs`·`switch`·`custom`)과 `trailing` → `SWViewerMenu` → `SWViewerPanel` children·`footer`·`headerActions` + 패널 컨트롤 |
|
|
| ② 소비 프로젝트에 신규 | 토큰 `--hm-sw-header-*`, Popup 안은 `--hm-sw-property-*`. 상태 표현은 [DESIGN_RULES.md](./DESIGN_RULES.md) §4(테두리형 gradient 링, 텍스트형 글자만 `#FFC600`). 안쪽 입력은 `SWHeaderInput` 재사용(예제 D) | 토큰 `--hm-sw-viewer-*` + 공유 `--hm-sw-header-*`(면·외곽선). 상태 표현은 [DESIGN_RULES.md](./DESIGN_RULES.md) §11 / VIEWER.md §2(Hover·Active·Pressed = 배경 변경 없이 글자·아이콘만 `#FFC600`, Focus 2px `#FFC600`). 안쪽은 뷰어 공개 컴포넌트 재사용(예: 새 패널 콘텐츠 = `SWViewerField` + `SWViewerInput`, 새 Header 도구 = `custom` 항목 안 `SWViewerHeaderButton`, 아이콘 = `SWViewerIcon`) |
|
|
| ③ 참고 값 없음 | 기존 HMDesign SW 규칙과 조화: Font Weight 400/500/700만, Light/Dark 없음, 전역 CSS(`html`·`body`·`*`) 금지, SW 공통 토큰 우선. 토큰에 없는 값은 결과 보고에 **"AI 구성 값 — 디자인 확인 필요"**로 표시 | 같음 |
|
|
|
|
- 뷰어 패널 안에 `@hm-design/ui` 컨트롤을 넣는 것은 `SWViewerPanel` `children`이 `ReactNode`라 가능하지만, `SWViewer*` 컨트롤로 안 될 때만 씁니다(별도 설치·외형 확인 필요, [VIEWER.md](./VIEWER.md) `SWViewerPanel` 절).
|
|
- 어느 단계에서도 패키지 원본(`node_modules/@hm-design/sw`) 수정, `hm-sw-*` class 재사용·재정의, `dist` 코드·CSS 복사를 하지 않습니다. 새 class는 소비 프로젝트 접두사(예: `app-`)를 씁니다.
|
|
|
|
## 1. 작업 순서 (필수)
|
|
|
|
1. **먼저 검색한다.** §0에서 모드를 정하고, 요청 기능을 [COMPONENT_CATALOG.md](./COMPONENT_CATALOG.md)의 공개 컴포넌트(뷰어 모드는 §9와 [VIEWER.md](./VIEWER.md))에서 찾는다.
|
|
2. **있으면 재사용한다(1순위).** 뷰어 모드는 `SWViewerHeader`·`SWViewerMenu`·`SWViewerPanel`이다(VIEWER.md). 일반 모드에서 완성형 Header가 필요하면 `SWHeader` 하나만 쓴다. 기존 Props(`hiddenControls`, `menuOrder`, `controls`, `documentOpenPlacement`, `leading`, `tools`, 각 데이터 배열·Callback)로 해결되는지 먼저 본다. 팝업·설정창은 `SWPopup`, 버튼·탭·토글은 `SWToolButton` / `SWToolGroup`, 일반 모드 로고 클릭 2단 메뉴는 `SWHeader`의 `homeMenu`(`SWHomeMenu` 데이터, 최근파일은 `SWRecentFiles`)이다. `SWToolButton`과 `SWHomeMenuItem`은 역할이 다르다(도구 막대 버튼 / 메뉴 타일). 서로 대신 쓰지 않는다.
|
|
- Popup 요청은 이렇게 판단한다: ① `SWPopup`이 프레임(외형·닫기·Escape·스크롤)을 제공한다 → ② 내용은 `children`으로 자유 구성(구조 제한 없음) → ③ 행 모양은 `SWPopupSection` / `SWPopupRow` + `SWHeaderInput`, 레이어·색상·선스타일 선택 행은 `SWPopupPropertyRow`(SWHeader 필드 Dropdown은 Header 전용), 게이지바는 `SWSlider`, 선택 목록은 `SWSelect` → ④ 그래도 SW에 없는 컨트롤(Switch, 하단 Button 등)만 `@hm-design/ui`를 children에 → ⑤ 프레임을 다시 만들거나 없는 Props(`content`, `renderContent` 등)를 추측하지 않는다.
|
|
3. **없으면 조합한다(2순위).** 개별 공개 컴포넌트(`SWHeaderHome`, `SWHeaderDocumentTitle`, `SWHeaderLayerMenu` …)를 `<SWTheme>` 안에 배치한다. 배치용 CSS만 소비 프로젝트에 작성한다([COMPOSITION_PATTERNS.md](./COMPOSITION_PATTERNS.md)).
|
|
4. **조합으로도 안 될 때만 새로 만든다(3순위).** 새 컴포넌트는 **소비 프로젝트**에 작성하고, 공개 컴포넌트(예: `SWHeaderInput`)를 내부에 재사용하며, 외형은 공개 토큰 `--hm-sw-header-*`만 읽는다([DESIGN_RULES.md](./DESIGN_RULES.md), 예제 D). 뷰어 모드의 새 UI는 `--hm-sw-viewer-*`(+ 공유 `--hm-sw-header-*` 면·외곽선, [DESIGN_RULES.md](./DESIGN_RULES.md) §11)를 읽고 Header 버튼·패널 버튼·입력은 `SWViewerHeaderButton`·`SWViewerButton`·`SWViewerField` + `SWViewerInput`을 재사용한다. 모드별 상세는 §0.4. 뷰어 화면에 일반 모드 컨트롤 모양을 섞지 않는다.
|
|
5. **토큰이 있는 값을 새로 만들지 않는다.** 크기·색·간격은 선택 모드의 토큰과 DESIGN_RULES(뷰어는 VIEWER.md도)의 확인값을 쓴다. 참고 값이 없을 때만 §0.4 ③으로 구성하고 "AI 구성 값 — 디자인 확인 필요"로 보고한다(화면 인상을 크게 바꾸는 값은 구현 전에 사용자에게 확인).
|
|
6. **존재하지 않는 API를 추측하지 않는다.** 카탈로그와 `dist/index.d.ts`에 없는 Export·Props는 없는 것이다.
|
|
7. **패키지 코드를 복사하지 않는다.** `node_modules/@hm-design/sw/dist`의 구현이나 `hm-sw-*` CSS 블록을 복사해 같은 컴포넌트를 다시 만들지 않는다.
|
|
8. **실제로 검증한다.** 소비 프로젝트에서 `tsc`, Production Build, 브라우저 렌더링(Dropdown 열기·Callback·Focus)을 확인한 뒤 완료로 보고한다. 실행하지 않은 검증은 PASS로 적지 않는다.
|
|
|
|
## 2. 설치·Import 규칙
|
|
|
|
```tsx
|
|
import { SWHeader, SWTheme, SWHeaderLayerMenu } from "@hm-design/sw"
|
|
import "@hm-design/sw/styles.css" // 앱 진입점에서 한 번
|
|
```
|
|
|
|
- 공식 진입점은 `@hm-design/sw`(JS·타입)와 `@hm-design/sw/styles.css` 두 개뿐이다. `package.json`의 `exports`가 다른 경로를 막는다.
|
|
- **금지:** `@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로 포함되어 별도 설정이 없다.
|
|
- SW 기본 글꼴은 Noto Sans KR이다(`--hm-sw-header-font-family: "Noto Sans KR", "Malgun Gothic", "Apple SD Gothic Neo", sans-serif`, 2026-10-20 확정 — 같은 날의 Dotum 기본값은 철회, Figma의 Dotum은 의도적으로 대체). 패키지는 글꼴 파일을 포함하지 않으며 앱이 Noto Sans KR(400/500/700)을 로드한다. 없으면 Malgun Gothic → Apple SD Gothic Neo로 대체된다. Dotum을 기본값으로 다시 넣지 않는다.
|
|
- SW 화면은 `SWTheme`(또는 SW 컴포넌트 루트)와 SW 토큰의 글꼴을 그대로 쓴다. Web UI도 Noto Sans KR이지만 Web 토큰(`--hm-font-family-base`)이나 Web `theme.css`의 글꼴 설정을 SW 화면에 복사하지 않고, SW 컴포넌트에 `font-family`를 개별 지정하지 않는다. 프로그램(사용자)이 다른 글꼴을 정한 경우에만 §3.1 방법으로 `--hm-sw-header-font-family`를 바꾸고 결과 보고에 "글꼴 변경"으로 적는다.
|
|
- Weight 범위(2026-10-20 사용자 확정): SWHeader 안의 필드 값은 400, Composed Controls(SWHeader 밖에 단독 배치한 `SWHeaderLayerMenu` 등)의 필드 값은 700. 파일명·Footer 보조기능/명령어 제목·Footer 분류 탭·Viewer Header 파일명/버튼 라벨/Model·Layout·최근파일 이름/경로/미리보기 제목, Footer Model/Layout 탭 라벨(모든 상태, 2026-10-22 사용자 확정, 이름 편집 입력은 400)은 700, Footer `전체보기`·명령·보조기능 라벨은 400. 임의로 일괄 변경하지 않는다. Figma 고정 폭 칸(예: 가중치·스케일 38px)에 그보다 긴 값(예: `ByLayer`)이 들어가면 말줄임 + `title`이 된다. Figma 레이어 이름의 `Dotum/bold/14`를 보고 700으로 바꾸거나 겹침·외곽선을 따로 만들지 않는다.
|
|
- CSS는 전역(`html`, `body`, `*`)을 건드리지 않는다. `body` margin 등 페이지 기본값은 소비 앱이 정한다.
|
|
- 스크롤바: SW 전용 스크롤바 디자인은 없다. 기존 SW 컴포넌트는 브라우저 기본 스크롤바를 쓰며(속성Bar만 `scrollbar-width: thin`), Popup 본문 스크롤은 `SWPopup`이 처리한다. 새 스크롤 영역에 임의 스크롤바 색·두께를 만들지 않는다.
|
|
- TypeScript에서 CSS side-effect import 오류가 나면 Vite의 `vite/client` 타입을 포함한다.
|
|
|
|
## 3. 스타일 규칙
|
|
|
|
- `SWHeader` 밖에서 하위 컴포넌트를 쓰면 반드시 `<SWTheme>`로 감싼다. 토큰·글꼴·버튼 초기화가 이 범위에서만 적용된다.
|
|
- 소비 코드는 `hm-sw-*` class를 붙이거나 재정의하지 않는다. 배치는 자기 class(`className`)와 `style`로 한다.
|
|
- 뷰어 모드 컴포넌트(`SWViewerHeader`·`SWViewerMenu`·`SWViewerPanel`)는 자체 `hm-sw-theme` 범위를 가지므로 `<SWTheme>`로 감싸지 않아도 된다. 소비 코드는 `hm-sw-viewer-*` class도 붙이거나 재정의하지 않는다.
|
|
- 외형 변경은 §3.1의 방법만 쓴다. 사용자 확정 면(파일명·객체 수정·속성 입력)은 기본값 유지를 권장한다.
|
|
- Header(`SWHeader`·`SWProcessHeader`·`SWViewerHeader`) 전용 스타일은 Header 영역에만 쓴다. 본문·패널에 Header 모양을 적용하지 않는다([AI_GUIDE.md](./AI_GUIDE.md) 5단계 "Header 전용 스타일의 적용 범위").
|
|
- Light/Dark 분기는 없다. SW 디자인은 하나다.
|
|
|
|
### 3.1 테마(토큰) 설정 — 공식 방법 (2026-10-20)
|
|
|
|
SW 토큰(`--hm-sw-header-*`, `--hm-sw-property-*`, `--hm-sw-viewer-*`, `--hm-sw-footer-*`)의 기본값은 **가장 바깥 SW 범위**(`<SWTheme>`, 또는 단독으로 쓴 `SWHeader`·`SWViewerHeader`·`SWViewerPanel`·`SWViewerMenu`·`SWFooter`의 루트)에서 한 번만 선언됩니다. 그 안의 SW 요소 — Header의 Dropdown·More, `SWViewerMenu`, `SWViewerPanel`과 안쪽 컨트롤, `SWFooterCommandLine`, Tooltip·안내 — 는 자기 루트에 `hm-sw-theme`이 있어도 값을 다시 정하지 않고 **상속**합니다.
|
|
|
|
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": '"Malgun Gothic", sans-serif' } as CSSProperties // 프로그램이 정한 값만
|
|
<SWTheme style={appSWTheme}>
|
|
<SWViewerHeader … /> {/* Dropdown·More 포함 */}
|
|
<SWViewerPanel …>…</SWViewerPanel>
|
|
</SWTheme>
|
|
```
|
|
2. 컴포넌트 하나만 쓰면 그 컴포넌트의 `style`로 정해도 됩니다(그 루트가 가장 바깥 범위). 안쪽 Dropdown·More·명령창에도 적용됩니다.
|
|
3. **Portal:** 상속은 DOM 위치를 따릅니다. 프로그램이 `createPortal`로 SW 요소를 범위 밖(`document.body` 등)에 렌더링하면 값이 전달되지 않으므로, Portal 내용을 같은 theme 객체의 `<SWTheme style={appSWTheme}>`으로 감쌉니다(예제 [ExampleJ-Theme.tsx](./examples/ExampleJ-Theme.tsx)). SW 패키지 컴포넌트 자체는 Portal을 쓰지 않습니다(Dropdown·More·Panel 모두 범위 안에 렌더링).
|
|
4. 영역마다 다른 값이 필요하면 영역별 `<SWTheme>`을 둡니다. 옆 영역끼리 섞이지 않고, 안쪽 `<SWTheme style>`은 그 안에서만 적용됩니다.
|
|
5. **하지 않음:** `hm-sw-*` class를 선택자로 쓴 CSS(`.hm-sw-header, .hm-sw-theme { --… }` 등), `!important`, 안쪽 컴포넌트마다 같은 값을 반복 지정, SW 범위가 아닌 조상(`body`, 앱 루트 `div`)에만 토큰 지정(SW 범위가 기본값을 다시 선언하므로 적용되지 않음).
|
|
- 다른 토큰을 참조하는 토큰(예: `--hm-sw-viewer-panel-background` = `var(--hm-sw-property-surface)`)은 가장 바깥 범위에서 계산됩니다. 참조되는 토큰을 바꿀 때도 가장 바깥 범위에서 바꿉니다.
|
|
|
|
## 4. 판단 기록 남기기
|
|
|
|
새 UI를 만들 때 결과 보고에 다음을 남긴다.
|
|
|
|
| 요청 항목 | 판단 | 근거 |
|
|
|---|---|---|
|
|
| 예: SW 모드 | 뷰어 모드 | 설정 `HMDesign 사용 유형: SW 뷰어` / 요청 "DWG 뷰어" / 사용자 답변 중 실제 근거 |
|
|
| 예: 레이어 | 재사용 | `SWHeaderLayerMenu` |
|
|
| 예: 검색 | 신규(소비 프로젝트) | 카탈로그 MISSING. `SWHeaderInput` 재사용 + 토큰 기반 표면 |
|
|
| 예: 뷰어 측정 패널 | 신규 콘텐츠(소비 프로젝트) | `SWViewerPanel` children에 `SWViewerField` + `SWViewerInput`. 토큰에 없는 값은 "AI 구성 값 — 디자인 확인 필요" |
|
|
|
|
새 컴포넌트를 SW 패키지 공식 컴포넌트로 승격할지는 별도 검토 대상이다. 임의로 패키지에 추가하지 않는다.
|
|
|
|
## 5. 디자인 시안 기반 Header 구현 — 도구 아이콘·창 제어 버튼 판단 (2026-11-05)
|
|
|
|
화면 이미지·Figma·캡처 같은 **디자인 시안**을 보고 SW Header(`SWHeader`·`SWProcessHeader`·`SWViewerHeader`)의 도구 버튼과 창 제어 버튼을 구현할 때 따르는 **단일 기준**입니다. 다른 문서는 이 절을 요약·참조만 합니다. 크기·색·상태 값은 [DESIGN_RULES.md](./DESIGN_RULES.md)(§9·§14, 뷰어는 [VIEWER.md](./VIEWER.md))를 따르며 이 절에서 다시 정하지 않습니다.
|
|
|
|
### 5.1 컴포넌트 기본 구성과 시안 재현은 다릅니다
|
|
|
|
| 구분 | 뜻 | 바꾸는 방법 |
|
|
|---|---|---|
|
|
| 컴포넌트 기본 구성 | Props를 생략했을 때 컴포넌트가 그리는 구성(예: `SWProcessHeader`는 `hiddenControls`가 없으면 창 이동·최소화·최대화/복원·종료를 모두 그림). 기존 소비 프로젝트가 의존하는 패키지 기본값 | 바꾸지 않습니다. 패키지 기본값·CSS를 고치거나 `hm-sw-*` class로 숨기지 않습니다 |
|
|
| 시안 재현 | 시안에 **보이는** 구성만 화면에 두는 것 | 공개 Props(`hiddenControls`·`tools`·`trailing` 등)로만 맞춥니다 |
|
|
|
|
- 카탈로그 예시·예제 파일·Storybook에 어떤 버튼이나 아이콘이 있다는 사실은 시안에 그것을 만들 근거가 아닙니다.
|
|
- **기존 화면 작업**(기존 화면을 HMDesign으로 옮기기, 이미 HMDesign을 쓰는 화면에 새 시안 적용)에는 [AI_GUIDE.md](./AI_GUIDE.md) 4단계 "기존 화면 전환 시 원본 보존"·"디자인 적용 시 변경 범위 제한"이 우선합니다. 원본에 있는 버튼·아이콘·창 제어 기능을 "시안에 없다"는 이유만으로 지우거나 `hiddenControls`를 더해 숨기지 않고, 원본에 없는 창 제어 버튼을 시안만 근거로 더하지 않습니다. 시안과 원본이 다르면 결과 보고의 "원본 대비 변경"에 확인 대상으로 적습니다. §5.5의 생략·추가 규칙은 신규 화면 기준입니다.
|
|
- 사용자가 창 제어·도구 버튼 구성 변경을 **명시적으로 요청**했으면 요청한 버튼에 한해 공개 Props로 바꾸고, "원본 대비 변경"의 근거를 "사용자 승인"으로 적습니다. 요청 범위 밖의 버튼은 그대로 둡니다.
|
|
|
|
### 5.2 도구 아이콘 선택 우선순위
|
|
|
|
| 순위 | 조건 | 할 일 |
|
|
|---|---|---|
|
|
| 1 | 사용자가 이번 작업에 제공했거나 사용을 승인한 이미지·SVG, 또는 소비 프로젝트에 이미 등록된 공식 아이콘이 있음 | 그 에셋을 씁니다. 상태별 그림이 있으면 기본은 `icon`, Hover 그림은 `hoverIcon`에 넣습니다(§5.4) |
|
|
| 2 | 제공된 에셋이 없고, `@hm-design/sw`가 **공개 Export**하는 아이콘·부품 중 **기능과 의미가 같은 것**이 있음 | 그것을 재사용합니다. 시안과 모양이 조금 달라도 기능이 같고 그 아이콘의 사용 위치·크기·상태 규칙 안이면 HMDesign 것을 우선합니다 |
|
|
| 3 | 1·2 모두 없음 | 대체·생략하지 않고 **코드를 쓰기 전에 사용자에게 먼저 묻습니다**(아래 3-A·3-B) |
|
|
|
|
- **시안 속 아이콘의 사용 권한:** Figma 등 시안에 그려져 있다는 사실만으로 사용 권한이 있다고 보지 않습니다. 시안에서 아이콘을 추출해 쓰려면 사용자가 그 에셋을 제공했거나 사용을 명시적으로 승인했는지 먼저 확인하고, 확인 전에는 1순위로 쓰지 않습니다(2·3순위로 판단). 이 승인은 해당 소비 프로젝트에서의 사용에만 해당하며, HMDesign 패키지 공식 등록·공개 배포 권한까지 포함하지 않습니다(3순위 4번, §5.3).
|
|
|
|
**2순위 — 현재 공개된 아이콘·아이콘 포함 부품**(목록 밖 이름은 [COMPONENT_CATALOG.md](./COMPONENT_CATALOG.md)와 `dist/index.d.ts`에서 확인):
|
|
|
|
| 공개 Export | 기능 | 사용 위치 |
|
|
|---|---|---|
|
|
| `SWHeader` 기본 부품(인쇄 `print`, K 가이드 `popupGuide`, 창 이동·최소화·종료) | 인쇄, 단축키 안내, 창 제어 | `SWHeader` 안(`hiddenControls`로 개별 제거). 아이콘만 꺼내 쓰는 API는 없습니다 |
|
|
| `SWHeaderActions` | 인쇄·K 가이드 버튼 pill(`onPrint`·`onPopupGuide`·`showPrint`·`showPopupGuide`·`disabled`) | `<SWTheme>` 안 SW 일반 모드 조합 Header([COMPOSITION_PATTERNS.md](./COMPOSITION_PATTERNS.md) 2). 컴포넌트 단위로만 재사용합니다 — 인쇄·K 아이콘 단독 Export는 없어 `SWToolButton`의 `icon`에 넣을 수 없습니다. `SWHeader`(이미 내장)·`SWProcessHeader` `tools`·뷰어 화면([VIEWER.md](./VIEWER.md) §2.1)에는 넣지 않습니다(검증된 조합 아님) |
|
|
| `SWHeaderWindowControls` | 창 이동·최소화·종료 | SW 일반 모드 조합 Header, 뷰어 `trailing` 끝(최소화·닫기만, `showWindowMove={false}`, VIEWER.md §2.1) |
|
|
| `SWProcessSplitButton` | 화면 분할 | `SWProcessHeader`의 `tools` |
|
|
| `SWLayerVisibilityIcon` | 레이어 표시·숨김 전구 | 뷰어 레이어 Popup(VIEWER.md §4.1) |
|
|
| `swFooterToolIcons` · `swFooterAuxIcons` | Footer 명령(Line·Circle …)·보조기능(객체스냅 …) | `SWFooter` 칸([FOOTER.md](./FOOTER.md)). 크기·상태 색이 Header 도구 버튼과 달라 Header pill에는 쓰지 않습니다 |
|
|
|
|
- 모양이 비슷하다는 이유만으로 기능이 다른 아이콘을 쓰지 않습니다(예: `swFooterToolIcons.rect`를 최대화 아이콘으로 쓰기 금지).
|
|
- `SWViewerIcon`은 외곽선만 더하는 감싸기 부품이며 그림을 제공하지 않습니다.
|
|
- **Header 도구 버튼용 범용 아이콘(도움말·3D 보기·설정·메뉴·나가기 등)은 현재 공개 Export가 없습니다.** 이런 아이콘이 시안에 있고 1순위 에셋도 없으면 3순위(사용자 확인)입니다.
|
|
|
|
**3순위 — 공개 Export가 없을 때(사용자 확인 필요):**
|
|
|
|
기능과 의미가 같은 아이콘이 HMDesign에 있는지 먼저 확인한 뒤, 해당하는 질문을 **코드를 쓰기 전에** 합니다. 질문에는 필요한 아이콘·기능·필요한 상태(기본·Hover 등)를 적습니다.
|
|
|
|
| 구분 | 상황 | 사용자에게 묻는 것 |
|
|
|---|---|---|
|
|
| 3-A | HMDesign 내부나 Storybook(예: `SW / Step Header` Story, §5.3)에 같은 기능의 아이콘이 있지만 공식 공개 Export가 없음 | 이번 소비 프로젝트에서 그 아이콘을 사용하도록 승인할지, 또는 별도 SVG 에셋을 제공할지. 공식 패키지 등록은 별도 검토가 필요하다는 점을 함께 알림 |
|
|
| 3-B | HMDesign 어디에도 같은 기능의 아이콘이 없음 | 에셋을 제공할지, 대체 아이콘을 쓸지(쓴다면 어떤 아이콘인지) |
|
|
|
|
> 3-A 질문 예: "요청하신 아이콘이 HMDesign Storybook에는 있지만 공식 공개 Export는 제공되지 않습니다. 해당 아이콘을 이번 프로젝트에서 사용하도록 승인하시겠습니까? 아니면 별도 SVG 에셋을 제공하시겠습니까? 공식 패키지 등록은 별도 검토가 필요합니다."
|
|
>
|
|
> 3-B 질문 예: "요청하신 아이콘은 HMDesign에 같은 기능의 아이콘이 없습니다. 에셋을 제공해 주시겠습니까, 아니면 대체 아이콘을 사용하시겠습니까?"
|
|
|
|
1. **답변 전에는 임의로 처리하지 않습니다.** 아이콘을 만들거나(AI가 그린 SVG), Storybook 파일을 복사하거나, 외부 아이콘 라이브러리(`lucide-react` 등 — Web 패키지 의존성이지만 SW 화면에 쓰지 않음)·다른 아이콘으로 대체하거나, 해당 버튼을 최종 화면에서 생략하는 것으로 확정하지 않습니다.
|
|
2. **답을 받을 수 없어 나머지를 진행해야 하면** 아이콘과 무관한 부분만 진행하고, 해당 도구 버튼은 구현하지 않은 채 "확인 대기"로 남깁니다(생략 확정이 아님). 결과 보고에 "아이콘 확인 대기 — 사용 승인 또는 에셋 제공 필요(기능·필요 상태)"로 적고, 답변을 받은 뒤 반영하거나 제거합니다. 임시 표시는 사용자가 승인한 것만 쓰며 최종 디자인으로 확정하지 않습니다.
|
|
3. **승인·제공을 받으면** 1순위로 처리합니다. 승인받은 Storybook 아이콘도 Storybook 파일 경로를 Import·참조하지 않고, 승인받은 SVG를 소비 프로젝트 자체 에셋으로 두어 그 경로를 씁니다(§5.3).
|
|
4. **소비 프로젝트 사용 승인은 공식 패키지 배포 권한이 아닙니다.** 사용 승인을 받아도 그 아이콘을 `@hm-design/sw`의 공식 Export로 등록하거나 등록된 것처럼 안내하지 않습니다. 출처·사용 권한(공개 패키지 배포 포함)이 확인되지 않은 아이콘은 공식 Export로 등록하지 않으며, 등록은 별도 검토·승인 대상으로만 보고합니다.
|
|
|
|
### 5.3 Storybook 전용 에셋과 공개 에셋의 차이
|
|
|
|
| 구분 | 공개 에셋·API | Storybook 전용 에셋(Fixture) |
|
|
|---|---|---|
|
|
| 위치 | `@hm-design/sw` 진입점 Export(카탈로그에 이름이 있음). SVG는 JS에 data URI로 포함 | HMDesign 저장소의 Story 데모 파일. 설치 패키지(`dist`·`ai`)에 포함되지 않음 |
|
|
| 보장 | 버전 호환·사용 규칙 문서화 대상 | 데모용. 출처·사용 권한·유지를 보장하지 않음 |
|
|
| 소비 프로젝트 | Import해서 사용 | 사용자 승인 전에는 Import·복사·경로 참조 금지(Git Submodule로 저장소 파일이 보여도 같음) |
|
|
|
|
- Storybook 화면에 보인다는 것은 공개 API라는 뜻이 아닙니다. Storybook은 조합·외형 참고용입니다([AI_GUIDE.md](./AI_GUIDE.md) 4단계 "Git Submodule 사용 규칙").
|
|
- Storybook 전용 에셋의 사용 승인은 **그 소비 프로젝트의 사용**에 한정됩니다. 승인 후에도 Storybook 경로를 Import하거나 공식 Import 경로로 안내하지 않으며, 공식 패키지 등록·공개 배포 권한은 승인된 것이 아닙니다(§5.2 3순위 3·4번).
|
|
- **2026-11-05 현재 Storybook 전용(공개 API 아님):** `SW / Step Header` Story의 도구 아이콘 — Multi Step의 도움말·3D 보기·설정·메뉴·나가기, Default의 View Property·Sub 창. 출처·사용 권한 확인 전이라 패키지에 등록하지 않았습니다. 시안에 이 아이콘이 있으면 3-A로 사용자에게 사용 승인 또는 별도 SVG 제공을 먼저 묻고(§5.2), 답변 전에는 사용·복사·생략 확정을 하지 않습니다. 승인·제공을 받으면 1순위로 처리합니다.
|
|
|
|
### 5.4 아이콘 상태 처리 — 기존 공개 API 방식 그대로
|
|
|
|
- `SWToolButton appearance="pill"`의 `icon`(기본 그림)과 `hoverIcon`(상태 그림)만 씁니다. Disabled 전용 아이콘 Prop은 없습니다. 상태별 현재 동작(패키지 CSS 기준)은 버튼이 놓인 곳에 따라 다릅니다.
|
|
|
|
| 상태 | `SWProcessHeader`의 `tools` 안 | 그 밖의 `pill`(`SWHeader`의 `tools`, `<SWTheme>` 조합) |
|
|
|---|---|---|
|
|
| Default | `icon`. `currentColor` = `#B6D0C9`(`--hm-sw-process-tool-icon-color`) | `icon`. `currentColor` = 상속 글자색 `--hm-sw-header-text-color`(`#F6F4F2`), `#B6D0C9` 아님 |
|
|
| Hover | 노란 링 + `currentColor` `#FFC600` + `hoverIcon`이 있으면 그 그림 | 노란 링 + `hoverIcon`이 있으면 그 그림. `currentColor` 색은 바뀌지 않음 |
|
|
| Pressed(`pressed` Prop, `aria-pressed`) | Hover와 같은 모양(노란 링 + `#FFC600` + `hoverIcon`) | `currentColor`만 `#FFC600`. 노란 링·`hoverIcon` 전환 없음 |
|
|
| Disabled | Hover 반응 없음, 기본 그림 유지, 투명도 0.4 | 같음 |
|
|
|
|
- 누르는 순간(`:active`)의 별도 모양은 없습니다. 위 Pressed는 `pressed` Prop 상태입니다.
|
|
- 색이 고정된 이미지는 기본·Hover 두 장을 줍니다. Hover 그림이 제공되지 않으면 `hoverIcon`을 생략하며(Hover에도 기본 그림 유지), 제공된 그림의 색을 바꿔 Hover 그림을 만들지 않습니다. `currentColor` 한 장으로 상태 색을 따르는 방식은 `SWProcessHeader`의 `tools`에서만 `#B6D0C9` → `#FFC600`이 됩니다. 그 밖의 `pill`에서 시안 색이 인쇄 버튼처럼 `#B6D0C9` → `#FFC600`이면 기본·Hover 두 장 이미지를 씁니다(값은 [DESIGN_RULES.md](./DESIGN_RULES.md) §9·§14).
|
|
- 위 표와 다른 상태 모양이 시안에 있으면 CSS로 맞추지 않고 지원 범위 밖으로 보고합니다.
|
|
- 그림은 장식이므로 `<img alt="" />`로 두고 버튼 이름은 `children`(문자열이면 기본 툴팁, DESIGN_RULES §15.2)으로 줍니다.
|
|
- 상태를 맞추려고 `hm-sw-*` class나 패키지 CSS를 덮지 않습니다.
|
|
|
|
### 5.5 창 제어 버튼(창 이동·최소화·최대화·닫기)
|
|
|
|
1. 시안에 **명확히 보이는** 창 제어 버튼만 구현합니다(웹 화면은 4번, 기존 화면은 §5.1이 우선).
|
|
2. 시안에 없고 별도 요구도 없으면 만들지 않는 것이 기본입니다. 컴포넌트 기본 구성(§5.1)에 있어도 공개 숨김 API로 뺍니다(신규 화면 기준, 기존 화면은 §5.1).
|
|
3. 시안의 오른쪽이 잘렸거나 일부가 보이지 않으면 보이지 않는 버튼의 존재를 확정하지 않습니다. 코드를 쓰기 전에 묻고, 답 없이 진행해야 하면 보이는 범위만 구현한 뒤 결과 보고에 "확인 필요(시안 잘림)"로 적습니다.
|
|
4. 브라우저에서 쓰는 웹 화면에서는 운영체제 창 제어 버튼을 새로 만들지 않는 것이 기본입니다. 시안에 창 제어 버튼이 보여도 실제로 연결할 창 동작(최소화·최대화·닫기를 처리하는 셸·Callback 요구)이 확인되지 않으면 임의로 구현하지 않습니다. 코드를 쓰기 전에 묻고, 답 없이 진행해야 하면 신규 창 제어 버튼 생성을 보류하고(아래 공개 숨김 API로 생략) 결과 보고에 "보류 — 창 동작 요구 확인 필요"로 적습니다. 빈 Callback·임의 `window.close()` 연결 같은 가짜 동작을 만들지 않습니다. 기존 화면에 이미 있는 창 제어 기능은 이 규칙을 이유로 별도 승인 없이 제거하지 않습니다(§5.1).
|
|
5. 데스크톱 프로그램(설치형·WebView 셸 등)처럼 창 제어가 필수인 환경은 플랫폼 요구와 사용자 명세를 우선합니다. 시안에 없는데 플랫폼상 필요해 보이면 임의로 더하지 않고 확인합니다. 실제 창 이동·최소화·최대화·종료는 프로그램 담당입니다(Callback 연결).
|
|
6. 숨김·생략은 아래 공개 API로만 합니다. 적절한 공개 API가 없으면 CSS로 감추는 우회 대신 지원 여부와 제약을 보고합니다.
|
|
|
|
| Header | 기본 구성 | 시안에 없을 때(공개 API) |
|
|
|---|---|---|
|
|
| `SWProcessHeader` | 창 이동·최소화·최대화/복원·종료 표시 | `hiddenControls`에 `"windowMove"`·`"minimize"`·`"maximize"`·`"close"` 중 없는 것. 넷 다 숨기고 `tools`도 없으면 창 영역 자체가 렌더링되지 않음 |
|
|
| `SWHeader` | 창 이동·최소화·종료 표시 | `hiddenControls`에 `"windowMove"`·`"minimize"`·`"close"` 중 없는 것 |
|
|
| `SWViewerHeader` | 창 제어 없음 | `trailing`에 `SWHeaderWindowControls`를 넣지 않음. 시안에 최소화·닫기가 있으면 `trailing` 맨 끝에 `showWindowMove={false}`로만 둠(VIEWER.md §2.1 승인 구성). 창 이동은 뷰어에서 지원하지 않으므로 시안에 있어도 넣지 않고 미지원으로 보고 |
|
|
| `<SWTheme>` 안 조합 Header | — | `SWHeaderWindowControls`를 두지 않거나 `showWindowMove`·`showMinimize`·`showClose`로 일부만 표시 |
|
|
|
|
### 5.6 공식 구현 예시 (공개 API만)
|
|
|
|
```tsx
|
|
import { SWHeader, SWProcessHeader, SWToolButton } from "@hm-design/sw"
|
|
// 1순위 에셋: 사용자·소비 프로젝트가 제공한 파일(HMDesign 패키지·Storybook 파일이 아님)
|
|
import helpIcon from "./assets/help.svg"
|
|
import helpIconHover from "./assets/help-hover.svg"
|
|
|
|
// 시안: 창 제어 버튼 없음, 도구는 도움말 하나
|
|
<SWProcessHeader appearance="multi" documentTitle={projectName} logoText="StrAna" onHomeClick={toggleFileMenu}
|
|
process={{ groups, 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={["windowMove", "minimize", "maximize", "close"]} />
|
|
|
|
// 시안: 최소화·닫기만 있음(창 이동·최대화 없음)
|
|
<SWProcessHeader documentTitle={fileName} process={processProps}
|
|
hiddenControls={["windowMove", "maximize"]} onMinimize={minimize} onClose={closeWindow} />
|
|
|
|
// 시안: 완성형 SWHeader에 창 제어 버튼 없음
|
|
<SWHeader documentTitle={fileName} {...headerProps} hiddenControls={["windowMove", "minimize", "close"]} />
|
|
```
|
|
|
|
### 5.7 결과 보고에 남길 것
|
|
|
|
§4 표에 다음 판단을 함께 적습니다.
|
|
|
|
| 요청 항목 | 판단 | 근거 |
|
|
|---|---|---|
|
|
| 예: 도움말 아이콘 | 1순위 사용 / 2순위 재사용 / 3순위 확인 대기 / 3순위 승인·제공 후 사용 | 사용자 제공 파일명 / 재사용한 공개 Export 이름 / "공개 Export 없음 — 사용 승인 또는 에셋 제공 확인 필요(3-A·3-B, 기능·필요 상태)" / 사용자 승인 내용. 승인은 이 소비 프로젝트 사용에 한하며 공식 패키지 등록은 별도 검토 |
|
|
| 예: 창 제어 버튼 | 구현 / 생략 / 보류 / 원본 유지 / 확인 필요 | 시안에 보인 버튼 목록, 사용한 `hiddenControls` 값, 시안 잘림·웹/데스크톱·플랫폼 요구 여부, 기존 화면이면 원본 구성과 사용자 승인 여부 |
|