Mind map node edit input is unreadable at low zoom #152

Open
opened 2026-05-06 08:01:27 +00:00 by AhmedHanafy725 · 3 comments
Member

When editing a mind-map node (double-click to edit text) while the canvas is zoomed out, the edit input box renders tiny because it scales with the canvas zoom. The visible node is much larger than the input that sits on top of it, making it hard to read what is being typed.

Expected

The edit input should be readable at any zoom level — comparable to how the comment popover renders at a fixed DOM size and stays readable regardless of canvas zoom.

Actual

The input shrinks with the canvas zoom and becomes unreadable when zoomed out. See screenshot — the small "New Node" box at the top-left is the actual edit input; the large rounded shape behind it is the actual node.

Repro

  1. Open a board, create a mind map
  2. Zoom the canvas out (Ctrl+-) a few steps
  3. Double-click any node to edit
  4. Observe that the edit input is much smaller than the node visual
When editing a mind-map node (double-click to edit text) while the canvas is zoomed out, the edit input box renders tiny because it scales with the canvas zoom. The visible node is much larger than the input that sits on top of it, making it hard to read what is being typed. ## Expected The edit input should be readable at any zoom level — comparable to how the comment popover renders at a fixed DOM size and stays readable regardless of canvas zoom. ## Actual The input shrinks with the canvas zoom and becomes unreadable when zoomed out. See screenshot — the small "New Node" box at the top-left is the actual edit input; the large rounded shape behind it is the actual node. ## Repro 1. Open a board, create a mind map 2. Zoom the canvas out (Ctrl+-) a few steps 3. Double-click any node to edit 4. Observe that the edit input is much smaller than the node visual
6.4 KiB
Author
Member

Implementation Spec

Root cause

Two edit-input builders in crates/hero_whiteboard_ui/static/web/js/whiteboard/mindmap.js size their DOM <input> elements by multiplying canvas pixels by the current Konva stage scale, so they shrink with zoom level instead of staying at a fixed screen size:

  1. editMindmapTitle (~lines 430–468) — title editor. width = 200 * stageScale, height = 24 * stageScale, fontSize = 16 * stageScale.
  2. editMindmapNode (~lines 639–678) — per-node editor. width = NODE_W(140) * stageScale, height = NODE_H(36) * stageScale, fontSize = 12 * stageScale.

When stageScale < 1 (zoomed out) the input collapses (font becomes ~3–4px) while the underlying Konva node looks visually unchanged on screen. Screen-space size of the input should be constant; only the position should depend on the absolute transform.

The pattern was already corrected for the comment popup showCommentPopup (uses .comment-popover CSS class with screen-fixed sizing, computes screen position via getAbsoluteTransform().point(...) plus stageBox). That is the model to mirror.

Files to Modify

  • crates/hero_whiteboard_ui/static/web/js/whiteboard/mindmap.js — only file with code changes.

No CSS changes required — reuse existing .konva-text-edit rule and --wb-* CSS variables already defined in whiteboard.css.

Implementation Plan

Step 1: Fix screen-fixed sizing in both edit-input builders

Files: mindmap.js

  1. Position computation (already correct — uses getAbsoluteTransform().point(...) + stageBox) stays as-is.
  2. Width with readable floor:
    • Node editor: width = Math.max(NODE_W * stageScale, 160) + 'px'
    • Title editor: width = Math.max(200 * stageScale, 200) + 'px'
  3. Height: fixed pixels (28px node, 32px title). Do not multiply by scale.
  4. Font size: fixed CSS strings — '14px' node (matches comment popover typography), '15px' bold for title.
  5. Replace inline hand-rolled colors with --wb-* CSS variables:
    • background: var(--wb-surface) (opaque — .konva-text-edit has background: transparent, must override so the giant zoomed node doesn't bleed through)
    • color: var(--wb-text) (title editor preserves group._mmState.tree.color override)
    • border: 1px solid var(--wb-border), borderRadius: 4px, padding: 4px 8px
    • On focus: outline: 2px solid var(--wb-primary)
  6. Keep className = 'konva-text-edit' on the node editor.

Dependencies: none

Acceptance Criteria

  • Zoom out to ~40%, double-click a mind-map node. Edit input renders at the same on-screen size and font as at 100%.
  • Zoom in to ~200%. Input has fixed legible font (~14px) and never balloons.
  • At every zoom level the input is anchored to the node's screen position.
  • Double-click the mind-map title at 25% zoom — title input is legible (≥14px).
  • Input matches the rest of the app visually: surface, border, focus outline tokens.
  • Screenshot from the issue (small input over a much larger node) no longer reproducible.
  • Light/dark theme switching still works for the input.

Behaviors that MUST be preserved

  • Pre-fill with nodeData.text / group._mmState.title
  • focus() + select() on open
  • Enter → blur → save
  • Blur saves: writes value back, renderMindmap(group), removes DOM, WhiteboardSync.onUpdate(group)
  • e.stopPropagation() in keydown — global shortcuts must not intercept typing
  • Lock check at call sites unchanged
  • Title-color override in editMindmapTitle preserved
  • Position anchoring (getAbsoluteTransform + stageBox) unchanged

Notes

Task description's mention of "add new node auto-focus + immediate edit flow" is aspirational — addChildToNode does not currently call editMindmapNode. Out of scope for this fix.

## Implementation Spec ### Root cause Two edit-input builders in `crates/hero_whiteboard_ui/static/web/js/whiteboard/mindmap.js` size their DOM `<input>` elements by multiplying canvas pixels by the current Konva stage scale, so they shrink with zoom level instead of staying at a fixed screen size: 1. **`editMindmapTitle`** (~lines 430–468) — title editor. `width = 200 * stageScale`, `height = 24 * stageScale`, `fontSize = 16 * stageScale`. 2. **`editMindmapNode`** (~lines 639–678) — per-node editor. `width = NODE_W(140) * stageScale`, `height = NODE_H(36) * stageScale`, `fontSize = 12 * stageScale`. When `stageScale < 1` (zoomed out) the input collapses (font becomes ~3–4px) while the underlying Konva node looks visually unchanged on screen. Screen-space size of the input should be constant; only the *position* should depend on the absolute transform. The pattern was already corrected for the comment popup `showCommentPopup` (uses `.comment-popover` CSS class with screen-fixed sizing, computes screen position via `getAbsoluteTransform().point(...)` plus `stageBox`). That is the model to mirror. ### Files to Modify - `crates/hero_whiteboard_ui/static/web/js/whiteboard/mindmap.js` — only file with code changes. No CSS changes required — reuse existing `.konva-text-edit` rule and `--wb-*` CSS variables already defined in `whiteboard.css`. ### Implementation Plan #### Step 1: Fix screen-fixed sizing in both edit-input builders Files: `mindmap.js` 1. Position computation (already correct — uses `getAbsoluteTransform().point(...)` + `stageBox`) stays as-is. 2. Width with readable floor: - Node editor: `width = Math.max(NODE_W * stageScale, 160) + 'px'` - Title editor: `width = Math.max(200 * stageScale, 200) + 'px'` 3. Height: fixed pixels (`28px` node, `32px` title). Do not multiply by scale. 4. Font size: fixed CSS strings — `'14px'` node (matches comment popover typography), `'15px'` bold for title. 5. Replace inline hand-rolled colors with `--wb-*` CSS variables: - `background: var(--wb-surface)` (opaque — `.konva-text-edit` has `background: transparent`, must override so the giant zoomed node doesn't bleed through) - `color: var(--wb-text)` (title editor preserves `group._mmState.tree.color` override) - `border: 1px solid var(--wb-border)`, `borderRadius: 4px`, `padding: 4px 8px` - On focus: `outline: 2px solid var(--wb-primary)` 6. Keep `className = 'konva-text-edit'` on the node editor. Dependencies: none ### Acceptance Criteria - [ ] Zoom out to ~40%, double-click a mind-map node. Edit input renders at the same on-screen size and font as at 100%. - [ ] Zoom in to ~200%. Input has fixed legible font (~14px) and never balloons. - [ ] At every zoom level the input is anchored to the node's screen position. - [ ] Double-click the mind-map title at 25% zoom — title input is legible (≥14px). - [ ] Input matches the rest of the app visually: surface, border, focus outline tokens. - [ ] Screenshot from the issue (small input over a much larger node) no longer reproducible. - [ ] Light/dark theme switching still works for the input. ### Behaviors that MUST be preserved - Pre-fill with `nodeData.text` / `group._mmState.title` - `focus()` + `select()` on open - Enter → blur → save - Blur saves: writes value back, `renderMindmap(group)`, removes DOM, `WhiteboardSync.onUpdate(group)` - `e.stopPropagation()` in keydown — global shortcuts must not intercept typing - Lock check at call sites unchanged - Title-color override in `editMindmapTitle` preserved - Position anchoring (`getAbsoluteTransform` + `stageBox`) unchanged ### Notes Task description's mention of "add new node auto-focus + immediate edit flow" is aspirational — `addChildToNode` does not currently call `editMindmapNode`. Out of scope for this fix.
Author
Member

Validation

Check Result
Files changed 1 file, JS only (mindmap.js)
cargo check --workspace pass
cargo test --workspace --lib pass (0 failures across all lib targets)
## Validation | Check | Result | |---|---| | Files changed | 1 file, JS only (`mindmap.js`) | | `cargo check --workspace` | pass | | `cargo test --workspace --lib` | pass (0 failures across all lib targets) |
Author
Member

Implementation summary

Changes

  • crates/hero_whiteboard_ui/static/web/js/whiteboard/mindmap.js — fixed both editMindmapTitle and editMindmapNode so the edit input has a screen-fixed size that does not shrink with canvas zoom.
    • Width has a readable floor (Math.max(NODE_W * scale, 160) for nodes, Math.max(200 * scale, 200) for the title).
    • Height is fixed in pixels (28px node, 32px title) — no zoom multiplier.
    • Font size is fixed (14px node, 15px bold title) — no zoom multiplier.
    • Inline colors moved from hardcoded values / mindmap-comment-* theme tokens to --wb-* CSS variables (--wb-surface, --wb-text, --wb-border, --wb-primary) that match the rest of the app and re-theme automatically.
    • Background is now opaque (var(--wb-surface)) so the giant zoomed-up node behind doesn't bleed through. The .konva-text-edit rule's 2px solid var(--wb-primary) focus outline now actually shows on the node editor (the previous inline outline: 'none' was suppressing it).
    • Position computation, pre-fill, focus+select, Enter→blur, blur→save (renderMindmap + WhiteboardSync.onUpdate), e.stopPropagation(), lock checks, and the title-color override are all preserved.

Validation

  • cargo check --workspace: pass
  • cargo test --workspace --lib: pass
  • Diff scope: 1 file, JS only

Notes

This is a UI-only change. Confirm visually by zooming the canvas to ~40% and double-clicking a mind-map node — the edit input should render at the same on-screen size and font as it does at 100%.

## Implementation summary ### Changes - `crates/hero_whiteboard_ui/static/web/js/whiteboard/mindmap.js` — fixed both `editMindmapTitle` and `editMindmapNode` so the edit input has a screen-fixed size that does not shrink with canvas zoom. - Width has a readable floor (`Math.max(NODE_W * scale, 160)` for nodes, `Math.max(200 * scale, 200)` for the title). - Height is fixed in pixels (`28px` node, `32px` title) — no zoom multiplier. - Font size is fixed (`14px` node, `15px` bold title) — no zoom multiplier. - Inline colors moved from hardcoded values / `mindmap-comment-*` theme tokens to `--wb-*` CSS variables (`--wb-surface`, `--wb-text`, `--wb-border`, `--wb-primary`) that match the rest of the app and re-theme automatically. - Background is now opaque (`var(--wb-surface)`) so the giant zoomed-up node behind doesn't bleed through. The `.konva-text-edit` rule's `2px solid var(--wb-primary)` focus outline now actually shows on the node editor (the previous inline `outline: 'none'` was suppressing it). - Position computation, pre-fill, focus+select, Enter→blur, blur→save (`renderMindmap` + `WhiteboardSync.onUpdate`), `e.stopPropagation()`, lock checks, and the title-color override are all preserved. ### Validation - `cargo check --workspace`: pass - `cargo test --workspace --lib`: pass - Diff scope: 1 file, JS only ### Notes This is a UI-only change. Confirm visually by zooming the canvas to ~40% and double-clicking a mind-map node — the edit input should render at the same on-screen size and font as it does at 100%.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_whiteboard#152
No description provided.