# BUG-5: Code Editor Modal Won't Close on Outside Click **Priority:** P1 - Significant UX Issue **Status:** Sort of fixed but still bugs on the Blockly node 'generated code' button **Created:** January 13, 2026 **Updated:** January 14, 2026 --- ## Problem When opening the new JavaScriptEditor (CodeMirror 6) by clicking a code property in the property panel, the modal stays on screen even when clicking outside of it. This prevents users from closing the editor without saving. **Expected behavior:** - Click outside modal → Auto-saves and closes - Press Escape → Auto-saves and closes - Click Save button → Saves and stays open **Current behavior:** - Click outside modal → Nothing happens (modal stays open) - Only way to close is clicking Save button --- ## Impact - Users feel "trapped" in the code editor - Unclear how to dismiss the modal - Inconsistent with other popout behaviors in OpenNoodl --- ## Root Cause Analysis ### Code Flow 1. **CodeEditorType.ts** calls `this.parent.showPopout()` with JavaScriptEditor content 2. **showPopout()** should close on outside clicks by default (unless `manualClose: true`) 3. **onClose callback** calls `save()` which auto-saves changes 4. Something is preventing the outside click from triggering close ### Likely Causes **Possibility 1: Event Propagation** - JavaScriptEditor or its container might be stopping event propagation - Click events not bubbling up to PopupLayer **Possibility 2: Z-index/Pointer Events** - Modal overlay might not be capturing clicks - CSS `pointer-events` preventing click detection **Possibility 3: React Event Handling** - React's synthetic event system might interfere with jQuery-based popout system - Event listener attachment timing issue --- ## Investigation Steps ### 1. Check Event Propagation Verify JavaScriptEditor isn't stopping clicks: ```typescript // In JavaScriptEditor.tsx
// Should NOT have onClick that calls event.stopPropagation() ``` ### 2. Check Popout Configuration Current call in `CodeEditorType.ts`: ```typescript this.parent.showPopout({ content: { el: [this.popoutDiv] }, attachTo: $(el), position: 'right', disableDynamicPositioning: true, // manualClose is NOT set, so should close on outside click onClose: function () { save(); // Auto-saves // ... cleanup } }); ``` ### 3. Compare with Monaco Editor The old Monaco CodeEditor works correctly - compare popout setup. ### 4. Test Overlay Click Handler Check if PopupLayer's overlay click handler is working: ```javascript // In browser console when modal is open: document.querySelector('.popout-overlay')?.addEventListener('click', (e) => { console.log('Overlay clicked', e); }); ``` --- ## Solution Options ### Option A: Fix Event Propagation (Preferred) If JavaScriptEditor is stopping events, remove/fix that: ```typescript // JavaScriptEditor.tsx - ensure no stopPropagation on root
``` ### Option B: Add Explicit Close Button If outside-click proves unreliable, add a close button: ```typescript
``` But this is less elegant - prefer fixing the root cause. ### Option C: Set manualClose Flag Force manual close behavior and add close button: ```typescript this.parent.showPopout({ // ... manualClose: true, // Require explicit close onClose: function () { save(); // Still auto-save // ... } }); ``` --- ## Implementation Plan 1. **Investigate** - Determine exact cause (event propagation vs overlay) 2. **Fix Root Cause** - Prefer making outside-click work 3. **Test** - Verify click-outside, Escape key, and Save all work 4. **Fallback** - If outside-click unreliable, add close button --- ## Design Decision: Auto-Save Behavior **Chosen: Option A - Auto-save on close** - Clicking outside closes modal and auto-saves - No "unsaved changes" warning needed - Consistent with existing Monaco editor behavior - Simpler UX - less friction **Rejected alternatives:** - Option B: Require explicit save (adds friction) - Option C: Add visual feedback (over-engineering for this use case) --- ## Files to Modify **Investigation:** - `packages/noodl-core-ui/src/components/code-editor/JavaScriptEditor.tsx` - Check event handlers - `packages/noodl-editor/src/editor/src/views/popuplayer.js` - Check overlay click handling **Fix (likely):** - `packages/noodl-core-ui/src/components/code-editor/JavaScriptEditor.tsx` - Remove stopPropagation if present - `packages/noodl-editor/src/editor/src/views/panels/propertyeditor/CodeEditor/CodeEditorType.ts` - Verify popout config **Fallback:** - Add close button to JavaScriptEditor if outside-click proves unreliable --- ## Testing Checklist - [ ] Click outside modal closes it - [ ] Changes are auto-saved on close - [ ] Escape key closes modal (if PopupLayer supports it) - [ ] Save button works (saves but doesn't close) - [ ] Works for both editable and read-only editors - [ ] No console errors on close - [ ] Cursor position preserved if re-opening same editor --- ## Related Issues - Related to Task 11 (Advanced Code Editor implementation) - Similar pattern needed for Blockly editor modals --- ## Notes - This is a quick fix - should be resolved before continuing with other bugs - Auto-save behavior matches existing patterns in OpenNoodl - If outside-click proves buggy across different contexts, consider standardizing on explicit close buttons --- _Last Updated: January 13, 2026_