diff --git a/apps/web/src/components/DiagramEditorPane.test.mjs b/apps/web/src/components/DiagramEditorPane.test.mjs index 2672f035..fb838590 100644 --- a/apps/web/src/components/DiagramEditorPane.test.mjs +++ b/apps/web/src/components/DiagramEditorPane.test.mjs @@ -115,6 +115,7 @@ describe("diagram editor canvas surface", () => { test("organizes architecture resources in a searchable category library", () => { expect(source).toContain("ARCHITECTURE_LIBRARY_CATEGORIES"); expect(source).toContain('t("diagram.componentLibrary")'); + expect(source).toContain('onPointerEnter={() => setOpen(true)}'); expect(source).toContain('t("diagram.componentSearch")'); expect(source).toContain('labelKey: "diagram.componentCategoryExperience"'); expect(source).toContain('labelKey: "diagram.componentCategoryServices"'); @@ -141,6 +142,16 @@ describe("diagram editor canvas surface", () => { expect(source).not.toContain('className="line-clamp-2"'); }); + test("opens every diagram insertion library immediately on pointer hover", () => { + expect(source).toContain("const DiagramInsertMenu = ({"); + expect(source.match(/onPointerEnter=\{\(\) => setOpen\(true\)\}/g)?.length).toBe(2); + expect(source).toContain('label={t("diagram.addTopic")}'); + expect(source).toContain('label: t("diagram.addSiblingTopic")'); + expect(source).toContain('label={t("diagram.addStep")}'); + expect(source).toContain('label: t("diagram.addDecision")'); + expect(source).toContain('label: t("diagram.addTerminator")'); + }); + test("shows connection handles only on selected flowchart nodes", () => { expect(globalStyles).toContain('.x6-node.edgeever-flow-node-active .edgeever-flow-port-dot'); expect(globalStyles).toContain('.x6-port-body:hover .edgeever-flow-port-dot'); diff --git a/apps/web/src/components/DiagramEditorPane.tsx b/apps/web/src/components/DiagramEditorPane.tsx index 4e3ac4d7..0be4b7c6 100644 --- a/apps/web/src/components/DiagramEditorPane.tsx +++ b/apps/web/src/components/DiagramEditorPane.tsx @@ -322,7 +322,9 @@ const ArchitectureComponentLibrary = ({ if (!nextOpen) setQuery(""); }}> - +
@@ -385,6 +387,40 @@ const ArchitectureComponentLibrary = ({ ); }; +const DiagramInsertMenu = ({ + icon: TriggerIcon, + items, + label, +}: { + icon: LucideIcon; + items: Array<{ icon: LucideIcon; label: string; onSelect: () => void }>; + label: string; +}) => { + const [open, setOpen] = useState(false); + return ( + + + + + + {items.map((item) => { + const Icon = item.icon; + return ( + + + {item.label} + + ); + })} + + + ); +}; + const FLOW_ACTIVE_NODE_CLASS = "edgeever-flow-node-active"; const FLOW_PORT_HIT_RADIUS = 14; const FLOW_PORT_DOT_RADIUS = 7; @@ -2074,12 +2110,14 @@ export const DiagramEditorPane = ({
{!readOnly && ( document.kind === "mind-map" ? ( - - - - - {t("diagram.mindMapShortcuts")} - + addNode("topic", { relation: "child" }) }, + { icon: ListTree, label: t("diagram.addSiblingTopic"), onSelect: () => addNode("topic", { relation: "sibling" }) }, + ]} + /> ) : document.kind === "architecture" ? ( <> ) : ( <> - - - - - {t("diagram.flowchartShortcuts")} - - {t("diagram.addDecision")} - {t("diagram.addTerminator")} + addNode("process") }, + { icon: Diamond, label: t("diagram.addDecision"), onSelect: () => addNode("decision") }, + { icon: Circle, label: t("diagram.addTerminator"), onSelect: () => addNode("terminator") }, + ]} + /> {t("diagram.connectHint")} ) diff --git a/packages/shared/src/i18n/en-US.ts b/packages/shared/src/i18n/en-US.ts index e96aed5b..a5e7a7b6 100644 --- a/packages/shared/src/i18n/en-US.ts +++ b/packages/shared/src/i18n/en-US.ts @@ -250,6 +250,7 @@ export const enUS = { title: "Diagram title", canvas: "{{type}} canvas", addTopic: "Add child topic", + addSiblingTopic: "Add sibling topic", mindMapShortcuts: "Tab adds a child; Enter adds a sibling", addStep: "Add step", flowchartShortcuts: "Tab connects the next node; Enter edits; Cmd/Ctrl+D duplicates; arrow keys nudge", diff --git a/packages/shared/src/i18n/zh-CN.ts b/packages/shared/src/i18n/zh-CN.ts index b63975da..431f0f15 100644 --- a/packages/shared/src/i18n/zh-CN.ts +++ b/packages/shared/src/i18n/zh-CN.ts @@ -250,6 +250,7 @@ export const zhCN = { title: "图表标题", canvas: "{{type}}画布", addTopic: "添加子主题", + addSiblingTopic: "添加同级主题", mindMapShortcuts: "Tab 添加子主题,Enter 添加同级主题", addStep: "添加步骤", flowchartShortcuts: "Tab 连接后续节点,Enter 编辑,⌘/Ctrl+D 复制,方向键微调",