Merge branch 'integration/sw-home-menu' into feature/sw-home-menu

Integrate the SW home (logo) menu into SWHeader for SW general mode only.
SW viewer mode code and stories are unchanged.

- Resolve conflicts: keep both sw-home-menu and sw-viewer exports;
  renumber AI docs (catalog viewer 8->9, patterns home menu 7->8,
  design rules home menu 11->12)
- SWHeader: start the home menu after the file name when it sits
  inside controls, so the file name stays visible
- AI guides: mark home menu as general-mode only; forbid it in viewer
  mode (AI_USAGE, catalog, design rules, patterns, VIEWER.md, AI_GUIDE)
- Tests: ignore wildcard identifiers in ai-docs check; update expected
  Storybook SW titles (SW/Tool removed, SW/Viewer added)
- Add merge QA report docs/sw/sw-home-menu-merge-2026-10-19.md
This commit is contained in:
shkim4 committed 2026-10-19 18:21:19 +09:00
commit 3a5e29f2fa
122 files changed
+6547 -41

No files matched your search

@@ -0,0 +1,62 @@
// Example G — the logo (home) menu (Figma 26:10591): SWHeader `homeMenu` + sections data + the optional recent
// files panel. Hidden by default; a logo click opens it, a second click closes it. New / Open stay in the
// document dropdown. Every text, icon and action is the program's data; the package ships none.
import { useState } from "react"
import {
SWHeader, SWRecentFiles,
type SWFileEntry, type SWHomeMenuItemData, type SWHomeMenuSectionData,
} from "@hm-design/sw"
import { documents } from "./sample-data"
// One currentColor icon per tile follows the state colors (Default #B6B4AF, Hover / Active #FF5C00).
const Icon = ({ d }: { d: string }) => (
<svg viewBox="0 0 18 18" width="18" height="18" aria-hidden="true"><path d={d} fill="none" stroke="currentColor" strokeWidth="1.6" /></svg>
)
const recentFiles: SWFileEntry[] = [
{ id: "r1", name: "평면도_A.dwg", path: "D:\\Projects\\A" },
{ id: "r2", name: "종단면도_B.dwg", path: "D:\\Projects\\B" },
]
export function ExampleGHomeMenu({ onEvent }: { onEvent?: (name: string) => void }) {
const [activeDocumentId, setActiveDocumentId] = useState(documents[0].id)
const [extra, setExtra] = useState<SWHomeMenuItemData[]>([])
// The same handlers as the document dropdown: the menu adds entry points, never a second implementation.
const openFile = () => onEvent?.("document:open")
const newFile = () => onEvent?.("document:new")
const sections: SWHomeMenuSectionData[] = [
{ id: "working", title: "작업중인 파일", items: [
{ id: "save", label: "저장", icon: <Icon d="M3 3h10l2 2v10H3z M6 3v4h6V3" />, toggle: false, onSelect: () => onEvent?.("menu:save") },
{ id: "export", label: "내보내기", icon: <Icon d="M9 12V3 M5 7l4-4 4 4 M3 15h12" />, toggle: false, onSelect: () => onEvent?.("menu:export") },
] },
{ id: "open", title: "다른 파일 열기", items: [
{ id: "find-open", label: "찾아열기", icon: <Icon d="M3 5h5l2 2h5v8H3z" />, toggle: false, onSelect: openFile },
// Optional sub panel: the tile toggles it (Active = open), the menu shows the outline accent meanwhile.
{ id: "recent", label: "최근파일", icon: <Icon d="M9 4v5l3 2 M9 16A7 7 0 1 0 9 2a7 7 0 0 0 0 14" />,
panel: <SWRecentFiles files={recentFiles} onFileOpen={file => onEvent?.(`recent:${file.id}`)} />, panelLabel: "최근파일" },
{ id: "new-file", label: "새파일", icon: <Icon d="M4 2h7l3 3v11H4z M9 8v6 M6 11h6" />, toggle: false, onSelect: newFile },
...extra,
] },
]
return (
<>
<SWHeader
documentTitle={documents.find(item => item.id === activeDocumentId)?.name ?? ""}
logoAlt="예제 SW"
documents={documents}
activeDocumentId={activeDocumentId}
onDocumentSelect={document => { setActiveDocumentId(document.id); onEvent?.(`document:${document.id}`) }}
onDocumentNew={newFile}
onDocumentOpen={openFile}
homeMenu={{ sections, onItemSelect: event => onEvent?.(`menu:select:${event.item.id}:${event.active}`) }}
onHomeMenuOpenChange={(open, reason) => onEvent?.(`menu:${open ? "open" : "close"}:${reason}`)}
/>
{/* Adding an item is a data change only: width, dividers and corners follow the new item count. */}
<button type="button" style={{ marginTop: 40 }} onClick={() => setExtra(list => [...list, { id: `extra-${list.length + 1}`, label: `추가 ${list.length + 1}`, icon: <Icon d="M9 3v12 M3 9h12" /> }])}>
메뉴 항목 추가
</button>
</>
)
}