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:
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>
|
||||
</>
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user