feat(sw): integrate home menu into SWHeader (Task A + B)
Combine Task A (e8409ef, SW 0.2.0 integrated improvement) with Task B
(396539d, Figma-based SWHomeMenu / SWHomeMenuSection / SWHomeMenuItem /
SWRecentFiles). Task B's 84 new files are taken unchanged except for the
public-import Storybook update and joining the popup Escape stack.
- Export the home menu from @hm-design/sw
- SWHeader homeMenu / homeMenuOpen / defaultHomeMenuOpen /
onHomeMenuOpenChange: hidden by default, the logo toggles it (onHomeClick
is not called while homeMenu is set), placed from the measured header,
closes with / closes the document and field dropdowns
- Logo aria-expanded / aria-controls; menu layer CSS (z-index 20)
- AI catalog / patterns / design rules, example G, README, usage guide
- Storybook SW/Home Menu uses @hm-design/sw; integration story
Verified: SW typecheck, tsc -b, SW build, Storybook build, AI docs 22/22,
28/28 existing SW shots pixel-identical, regression 96 PASS / 0 FAIL,
home menu checks 22/22. Not run: tarball consumer install.
This commit is contained in:
1 parent
e8409eff44
commit
1472e51f47
110 files changed
+6463
-17
No files matched your search
@@ -0,0 +1,113 @@
|
||||
// Storybook fixture for SWHomeMenu: the Figma 26:10591 sample menu (rj6wpsfk24lOWvWiVRAANP).
|
||||
// Texts, icons and ids are sample data only; the package ships no menu items or icons.
|
||||
import type { ReactNode } from "react"
|
||||
import type { SWFileEntry, SWHomeMenuSectionData } from "@hm-design/sw"
|
||||
import monitorA from "./assets/home-menu/file-open-monitor-a.svg"
|
||||
import monitorB from "./assets/home-menu/file-open-monitor-b.svg"
|
||||
import previewImage from "./assets/home-menu/figma-preview-h1100.png"
|
||||
import save from "./assets/home-menu/save.svg"
|
||||
import saveHover from "./assets/home-menu/save-hover.svg"
|
||||
import saveAs from "./assets/home-menu/save-as.svg"
|
||||
import saveAsHover from "./assets/home-menu/save-as-hover.svg"
|
||||
import exportIcon from "./assets/home-menu/export.svg"
|
||||
import exportHover from "./assets/home-menu/export-hover.svg"
|
||||
import bundle from "./assets/home-menu/bundle.svg"
|
||||
import bundleHover from "./assets/home-menu/bundle-hover.svg"
|
||||
import findOpen from "./assets/home-menu/find-open.svg"
|
||||
import findOpenHover from "./assets/home-menu/find-open-hover.svg"
|
||||
import recent from "./assets/home-menu/recent.svg"
|
||||
import recentHover from "./assets/home-menu/recent-hover.svg"
|
||||
import newFile from "./assets/home-menu/new-file.svg"
|
||||
import newFileHover from "./assets/home-menu/new-file-hover.svg"
|
||||
import recover from "./assets/home-menu/recover.svg"
|
||||
import recoverHover from "./assets/home-menu/recover-hover.svg"
|
||||
import tempFile from "./assets/home-menu/temp-file.svg"
|
||||
import tempFileHover from "./assets/home-menu/temp-file-hover.svg"
|
||||
import display from "./assets/home-menu/display.svg"
|
||||
import displayHover from "./assets/home-menu/display-hover.svg"
|
||||
import settingSave from "./assets/home-menu/setting-save.svg"
|
||||
import settingSaveHover from "./assets/home-menu/setting-save-hover.svg"
|
||||
import settingLoad from "./assets/home-menu/setting-load.svg"
|
||||
import settingLoadHover from "./assets/home-menu/setting-load-hover.svg"
|
||||
import help from "./assets/home-menu/help.svg"
|
||||
import helpHover from "./assets/home-menu/help-hover.svg"
|
||||
import inquiry from "./assets/home-menu/inquiry.svg"
|
||||
import inquiryHover from "./assets/home-menu/inquiry-hover.svg"
|
||||
import swInfo from "./assets/home-menu/sw-info.svg"
|
||||
import swInfoHover from "./assets/home-menu/sw-info-hover.svg"
|
||||
|
||||
/**
|
||||
* Figma icon asset (SVG with its own shadow margin). `dx` / `dy` move it from the centered position in the
|
||||
* 18px slot to its Figma position (measured from each tile's icon frame and asset inset, 2026-10-19).
|
||||
*/
|
||||
function figmaIcon(src: string, width: number, height: number, dx = 0, dy = 0) {
|
||||
return <img src={src} alt="" width={width} height={height} style={dx || dy ? { transform: `translate(${dx}px, ${dy}px)` } : undefined} />
|
||||
}
|
||||
function pair(defaultSrc: string, hoverSrc: string, width: number, height: number, dx = 0, dy = 0) {
|
||||
return { icon: figmaIcon(defaultSrc, width, height, dx, dy), hoverIcon: figmaIcon(hoverSrc, width, height, dx, dy) }
|
||||
}
|
||||
|
||||
/** Figma node of each tile component set, for the 22-node checklist. */
|
||||
export const figmaTileNodes: Record<string, string> = {
|
||||
save: "26:11355", "save-as": "26:11371", export: "26:11387", bundle: "26:11403",
|
||||
"find-open": "26:11416", recent: "26:11450", "new-file": "26:11485",
|
||||
recover: "26:11507", "temp-file": "26:11529",
|
||||
display: "26:11542", "setting-save": "26:11558", "setting-load": "26:11586",
|
||||
help: "26:11599", inquiry: "26:11615", "sw-info": "26:11631",
|
||||
}
|
||||
export const figmaTitleNodes: Record<string, string> = {
|
||||
working: "26:12604", open: "26:12610", damaged: "26:12622", setting: "26:12628 (참고)", help: "26:12616",
|
||||
}
|
||||
|
||||
export const figmaHomeMenuSections: SWHomeMenuSectionData[] = [
|
||||
{ id: "working", title: "작업중인 파일", items: [
|
||||
{ id: "save", label: "저장", ...pair(save, saveHover, 21.5, 21.5, -0.25, -0.25) },
|
||||
{ id: "save-as", label: "복사저장", ...pair(saveAs, saveAsHover, 23.3, 23, 0, 0.5) },
|
||||
{ id: "export", label: "내보내기", ...pair(exportIcon, exportHover, 22.52, 23.2775, 0, 0.64) },
|
||||
{ id: "bundle", label: "도면묶기", ...pair(bundle, bundleHover, 23, 22) },
|
||||
] },
|
||||
{ id: "open", title: "다른파일 열기", items: [
|
||||
{ id: "find-open", label: "찾아열기", ...pair(findOpen, findOpenHover, 24.6989, 20, -0.15, -1) },
|
||||
{ id: "recent", label: "최근파일", ...pair(recent, recentHover, 22, 24.5, 1, 1.25) },
|
||||
{ id: "new-file", label: "새파일", ...pair(newFile, newFileHover, 20, 23) },
|
||||
] },
|
||||
{ id: "damaged", title: "파일 손상시", items: [
|
||||
{ id: "recover", label: "복구하기", ...pair(recover, recoverHover, 21, 22.3601, 0, -0.5) },
|
||||
{ id: "temp-file", label: "임시파일", ...pair(tempFile, tempFileHover, 22.25, 24.5, 0.125, 0.25) },
|
||||
] },
|
||||
{ id: "setting", title: "My Setting", items: [
|
||||
{ id: "display", label: "Display...", ...pair(display, displayHover, 24, 22, 1, 2) },
|
||||
{ id: "setting-save", label: "저장하기", ...pair(settingSave, settingSaveHover, 24.3087, 24.5, 1.15, 1.25) },
|
||||
{ id: "setting-load", label: "불러오기", ...pair(settingLoad, settingLoadHover, 18, 18, 1, 0) },
|
||||
] },
|
||||
{ id: "help", title: "궁금하면", items: [
|
||||
{ id: "help", label: "설명보기", ...pair(help, helpHover, 18, 18, 1, 0) },
|
||||
{ id: "inquiry", label: "문의하기", ...pair(inquiry, inquiryHover, 23, 23, 1, 0.5) },
|
||||
{ id: "sw-info", label: "S/W정보", ...pair(swInfo, swInfoHover, 21.5, 20, 0.75, 0) },
|
||||
] },
|
||||
]
|
||||
|
||||
export const figmaHomeMenuItemIds = figmaHomeMenuSections.flatMap(section => section.items.map(item => item.id))
|
||||
|
||||
// Figma 최근파일 662:67331 sample rows (15) and the 2-depth preview 662:67471 (sample data only).
|
||||
const recentNames = [
|
||||
["001-연결종합 계획평면도22222222.dwg", "a"], ["03.암발파공법적용도_231011.grm", "b"], ["1.배수공-일반사항_231004.dwg", "b"],
|
||||
["00.시공상세도 분석 및 목차_20240416.grm"], ["0_목차.dwg"], ["001-연결종합 계획평면도22222222.dwg"], ["03.암발파공법적용도_231011.grm"],
|
||||
["001-연결종합 계획평면도22222222.dwg"], ["03.암발파공법적용도_231011.grm"], ["0_목차.dwg"], ["00.시공상세도 분석 및 목차_20240416.grm"],
|
||||
["001-연결종합 계획평면도22222222.dwg"], ["03.암발파공법적용도_231011.grm"], ["0_목차.dwg"], ["00.시공상세도 분석 및 목차_20240416.grm"],
|
||||
] as const
|
||||
const monitor = { a: monitorA, b: monitorB }
|
||||
export const figmaRecentFiles: SWFileEntry[] = recentNames.map(([name, badge], index) => ({
|
||||
id: `recent-${index + 1}`,
|
||||
name,
|
||||
path: index < 2 ? "Z:\\01.기술개발센터\\04_그리미시스템\\Design..." : "Z:\\01.기술개발센터\\04_그리미시스템\\D...",
|
||||
badge: badge ? <img src={monitor[badge]} alt="" width={37} height={32} style={{ transform: "translateY(-2px)" }} /> : undefined,
|
||||
// Figma image 918 crop inside the 310 x 244 frame.
|
||||
preview: <img src={previewImage} alt="" style={{ position: "absolute", left: "-25.97%", top: "-52.46%", width: "158.67%", height: "191.87%", maxWidth: "none", objectFit: "fill" }} />,
|
||||
previewTitle: "C:/Users/user/Desktop/H1100.DWG",
|
||||
}))
|
||||
|
||||
/** The Figma menu with the optional 최근파일 sub panel attached to the 최근파일 tile. */
|
||||
export function withRecentFiles(sections: readonly SWHomeMenuSectionData[], panel: ReactNode): SWHomeMenuSectionData[] {
|
||||
return sections.map(section => ({ ...section, items: section.items.map(item => item.id === "recent" ? { ...item, panel, panelLabel: "최근파일" } : item) }))
|
||||
}
|
||||
Reference in new issue
Block a user