Files
shkim4 42f0cb7d0b docs(sw): ask the user before substituting or omitting a missing icon
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.
2026-11-05 17:59:20 +09:00

42 KiB

@hm-design/sw — AI 코딩 도구 사용 안내

이 폴더(node_modules/@hm-design/sw/ai/)는 다른 React 프로젝트에서 AI 코딩 도구가 SW 패키지를 재사용·조합·확장할 때 먼저 읽는 안내서입니다. 패키지 자체에는 AI 기능이 없습니다. 아래 문서는 실제 공개 API와 CSS에서 확인한 값만 적습니다.

먼저 AI_GUIDE.md(HMDesign 공통: 사용 유형 Web / SW 일반·뷰어 / OrgChart / 혼합 확인, 작업 1~7단계, 패키지 분리, 결과 보고)를 읽고 사용 유형이 SW 또는 SW가 포함된 혼합일 때 이 폴더를 씁니다.

문서 내용
AI_GUIDE.md HMDesign 공통 진입점(모든 HMDesign 패키지에 같은 사본)
COMPONENT_CATALOG.md 공식 공개 컴포넌트(일반 모드: Header·개별 컨트롤·Popup·도구 막대·로고 클릭 메뉴 / 뷰어 모드 §9: SWViewer* 전체 Export)·Props·Callback·크기·CSS 의존성
DESIGN_RULES.md SW 전용 토큰·Typography·간격·Hover/Focus/Selected·Overlay·Motion·반응형·Popup 외형·도구 버튼·로고 클릭 메뉴(일반 모드 §1~10·§12), 뷰어 토큰·상태값 요약(§11)
COMPOSITION_PATTERNS.md 완성형·간소화·기능 중심·확장 Header, Popup(자유 콘텐츠), 일반 모드 Header + 도구 막대(1~6), 뷰어 모드 기본 조합(7)
examples/ 공개 API만 쓰는 예제 AJ(10개). 일반 모드 AG·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 일반 모드 하단 막대: SWFooter(보조기능·바 안 명령창·명령 칸·분류 탭·명령어 전체보기), SWFooterLayoutTabs(Model/Layout 탭), SWFooterCommandLine(명령창). AI 작업 순서 1~6
VIEWER.md 뷰어 모드 전용: SWViewerHeader(데이터 메뉴·More·외곽선·로고 규칙), SWViewerMenu(Dropdown·서브메뉴·우클릭), SWViewerPanel(팝업 프레임 + 자유 콘텐츠). 일반 SW 모드는 SWHeader·SWPopup을 그대로 씁니다

0. SW 모드 선택 — SW 일반 모드 / SW 뷰어 모드 (코드 작성 전에 결정)

SW 패키지에는 Header·Popup 계열이 두 벌 있습니다. 화면마다 하나의 모드를 고르고 그 모드의 컴포넌트만 씁니다. 공통 사용 유형 확인(Web / SW / OrgChart / 혼합)은 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 §2)
하단 Footer SWFooter(+ 바 안 명령창 command={<SWFooterCommandLine />}, 좌표 status, SWFooterLayoutTabs, 부품 SWFooter*), 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 §18·§10·§11, DESIGN_RULES.md §110·§12·§13·§14, COMPOSITION_PATTERNS.md 16·8·10·12, FOOTER.md, 예제 AG·I VIEWER.md, COMPONENT_CATALOG.md §9, DESIGN_RULES.md §11, COMPOSITION_PATTERNS.md 7, 예제 H
  • 프로세스 단계 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 §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를 따르고, 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 §4(테두리형 gradient 링, 텍스트형 글자만 #FFC600). 안쪽 입력은 SWHeaderInput 재사용(예제 D) 토큰 --hm-sw-viewer-* + 공유 --hm-sw-header-*(면·외곽선). 상태 표현은 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 SWViewerPanel 절).
  • 어느 단계에서도 패키지 원본(node_modules/@hm-design/sw) 수정, hm-sw-* class 재사용·재정의, dist 코드·CSS 복사를 하지 않습니다. 새 class는 소비 프로젝트 접두사(예: app-)를 씁니다.

1. 작업 순서 (필수)

  1. 먼저 검색한다. §0에서 모드를 정하고, 요청 기능을 COMPONENT_CATALOG.md의 공개 컴포넌트(뷰어 모드는 §9와 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).
  4. 조합으로도 안 될 때만 새로 만든다(3순위). 새 컴포넌트는 소비 프로젝트에 작성하고, 공개 컴포넌트(예: SWHeaderInput)를 내부에 재사용하며, 외형은 공개 토큰 --hm-sw-header-*만 읽는다(DESIGN_RULES.md, 예제 D). 뷰어 모드의 새 UI는 --hm-sw-viewer-*(+ 공유 --hm-sw-header-* 면·외곽선, 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 규칙

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 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: … })도 됩니다.
    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). 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(§9·§14, 뷰어는 VIEWER.md)를 따르며 이 절에서 다시 정하지 않습니다.

5.1 컴포넌트 기본 구성과 시안 재현은 다릅니다

구분 뜻 바꾸는 방법
컴포넌트 기본 구성 Props를 생략했을 때 컴포넌트가 그리는 구성(예: SWProcessHeader는 hiddenControls가 없으면 창 이동·최소화·최대화/복원·종료를 모두 그림). 기존 소비 프로젝트가 의존하는 패키지 기본값 바꾸지 않습니다. 패키지 기본값·CSS를 고치거나 hm-sw-* class로 숨기지 않습니다
시안 재현 시안에 보이는 구성만 화면에 두는 것 공개 Props(hiddenControls·tools·trailing 등)로만 맞춥니다
  • 카탈로그 예시·예제 파일·Storybook에 어떤 버튼이나 아이콘이 있다는 사실은 시안에 그것을 만들 근거가 아닙니다.
  • 기존 화면 작업(기존 화면을 HMDesign으로 옮기기, 이미 HMDesign을 쓰는 화면에 새 시안 적용)에는 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와 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 2). 컴포넌트 단위로만 재사용합니다 — 인쇄·K 아이콘 단독 Export는 없어 SWToolButton의 icon에 넣을 수 없습니다. SWHeader(이미 내장)·SWProcessHeader tools·뷰어 화면(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). 크기·상태 색이 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 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 §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만)

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 값, 시안 잘림·웹/데스크톱·플랫폼 요구 여부, 기존 화면이면 원본 구성과 사용자 승인 여부