Mind-map node context menu has different styling than the rest of the whiteboard #155
Labels
No labels
prio_critical
prio_low
type_bug
type_contact
type_issue
type_lead
type_question
type_story
type_task
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lhumina_code/hero_whiteboard#155
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The right-click context menu for mind-map nodes uses its own DOM/CSS implementation that does not match the standard whiteboard context menu used by sticky notes, shapes, frames, and the empty-canvas right-click.
Expected
The mind-map node context menu should reuse the same context-menu structure and styling as the rest of the canvas — same background, border, item hover state, separator style, icon spacing, font, and theme reactivity.
Actual
The mind-map menu appears with mismatched styling — different paddings, different background, different item layout. Visually inconsistent with the rest of the app.
Notes
The standard menu lives in
crates/hero_whiteboard_ui/static/web/js/whiteboard/contextmenu.js. The mind-map node menu is built ad-hoc insidemindmap.js(showNodeContextMenu). The fix is to either route mind-map node menu items through the shared module, or at minimum reuse the same CSS classes (.wb-context-menu,.wb-context-menu-item, etc. — confirm the actual class names by reading the standard menu code).Implementation Spec
Root cause
The standard whiteboard menu is rendered by
WhiteboardContextMenuincrates/hero_whiteboard_ui/static/web/js/whiteboard/contextmenu.js(renderMenu~L141–171), using CSS classeswb-context-menu,ctx-item,ctx-divider,ctx-dangerdefined inwhiteboard.css~L111–118. These classes use theme variables (--wb-ctx-bg,--wb-border,--wb-text,--wb-hover,--wb-text-muted).The mind-map node menu (
showNodeContextMenuinmindmap.js~L624–657) builds its own DOM with hardcoded inline styles (#2b3035background,#495057borders,#e0e0e0text, hover viamouseenter/mouseleave) and emoji-glyph icons instead of Bootstrap icons. Nowb-context-menu/ctx-itemclasses are used, so the menu is hardcoded dark, ignores theme, and uses different paddings, min-width, and box-shadow than the standard menu.Today
WhiteboardContextMenuonly exposesinitandhide— there's no programmatic API to render an arbitrary menu at a coordinate.Approach: extract a shared
show(items, x, y)helperOption A (call existing API) is impossible — no public API exists. Option B (just adopt the classes) duplicates the markup pattern in two places. Option C — extract a small public
show(items, x, y)helper fromshowAtPositionand have both the canvas path and the mindmap path use it — eliminates duplication and is barely more work sinceshowAtPositionalready separates "build items" from "render + position".Files to Modify
crates/hero_whiteboard_ui/static/web/js/whiteboard/contextmenu.js— extract render/position/show into a publicshow(items, x, y); export it from the IIFE; refactorshowAtPositionto delegate to it.crates/hero_whiteboard_ui/static/web/js/whiteboard/mindmap.js— replace the hand-rolled DOM inshowNodeContextMenuwith a call toWhiteboardContextMenu.show(items, evt.clientX, evt.clientY). DropcloseNodeContextMenuand_nodeMenuOutsideHandler— the shared module already wires document-level click + Escape dismissal.No CSS changes.
Implementation Plan
Step 1 — extract shared helper
Files:
contextmenu.jsshow(items, x, y)that callsrenderMenu(items)and runs the existing viewport-clamp positioning (currently inlined at the end ofshowAtPosition): computemenuW/menuHfrom the rendered element, clamp x/y to viewport, setmenuEl.style.left/top/display = 'block'.showAtPositionso the final "render+position+display" step (~L127–138) becomes a singleshow(items, x, y)call. The earlier logic that resolvestargetNode, selects on right-click, and builds the canvas/object items array stays exactly as-is.targetNodeis set insideshowAtPositionfor the canvas path's action callbacks. The newshowmust NOT clear it — callers managetargetNodethemselves. Mindmap callers don't touchtargetNode(their actions close overgroup/nodeData/nodeRect).show:return { init, hide, show };.menuElis null insideshow, lazily callinit()first.Step 2 — switch mindmap menu to shared helper
Files:
mindmap.jsshowNodeContextMenubody with the standard items shape and a call to the new helper:closeNodeContextMenuand_nodeMenuOutsideHandler(their only callers are insideshowNodeContextMenuitself). Also remove the leadingcloseNodeContextMenu()call.onNodeContextMenuwithpreventDefault/stopPropagation/cancelBubble) stays exactly as-is — that block is what stops the document-level menu from also firing on top of the per-node menu.Dependencies: none.
Acceptance Criteria
ctx-dangerstyling). Label flips based onnodeData.comment.var(--wb-hover)background); Delete uses red hover from.ctx-danger:hover..ctx-divider).What NOT to break
e3c4cb8): per-nodecontextmenulisteners on rect/label/indicator/addBtn/commentIcon withpreventDefault+stopPropagation+cancelBubble. Without this the document-level handler still fires the canvas menu.showCommentPopup, Add Child →addChildToNode, Delete Node →deleteNode. Closures overgroup/nodeData/nodeRectmust survive.showAtPosition's order of operations for the canvas/object menu (resolvetargetNode, select on right-click, build items) — only the final render-and-position step changes.WhiteboardContextMenu.hidecallers —hidestays exported.Validation
cargo check --workspacecargo test --workspace --libImplementation summary
Changes
crates/hero_whiteboard_ui/static/web/js/whiteboard/contextmenu.js— extracted a publicshow(items, x, y)helper that callsrenderMenu(items)and runs the existing viewport-clamp / display logic.showAtPositionnow delegates the final "render + position + display" step toshow. Exported as part of the IIFE return:{ init, hide, show }.targetNodehandling for canvas-menu actions is unchanged.crates/hero_whiteboard_ui/static/web/js/whiteboard/mindmap.js— replaced the bespoke DOM inshowNodeContextMenuwith a singleWhiteboardContextMenu.show(items, evt.clientX, evt.clientY)call. Items use the standard renderer's keys (label,icon,action,divider,danger):bi-chat)bi-plus-circle)bi-trash, danger)Removed
closeNodeContextMenuand_nodeMenuOutsideHandler— outside-click and Escape dismissal are already wired byWhiteboardContextMenu.init().Issue #154's wiring (
onNodeContextMenuattached to every per-node sub-shape) is intact.Validation
cargo check --workspace: passcargo test --workspace --lib: passNotes
UI-only change. Verify visually: right-click any mind-map node — the menu should look identical to the right-click menu used for sticky notes / shapes / frames / empty canvas. Theme switch should re-color the menu the same way it re-colors the standard menu.