Skip to content

fix: panel buttons unresponsive after window resize#882

Merged
Nihal4777 merged 6 commits intoCircuitVerse:mainfrom
senutpal:fix/panel-buttons-unresponsive-after-resize-#874
Feb 8, 2026
Merged

fix: panel buttons unresponsive after window resize#882
Nihal4777 merged 6 commits intoCircuitVerse:mainfrom
senutpal:fix/panel-buttons-unresponsive-after-resize-#874

Conversation

@senutpal
Copy link
Contributor

@senutpal senutpal commented Jan 28, 2026

Fixes #874

Describe the changes you have made in this PR -

Root Cause

jQuery event listeners lost when Vue re-renders panel components during responsive switching.

Solution

1. Expose Functions Globally

File: ux.js

window.setupPanelListeners = setupPanelListeners
window.minimizePanel = (panelSelector) => {
    $(panelSelector + ' .minimize').trigger('click')
}

2. Call in Vue Components

Files: ElementsPanel, TimingDiagramPanel, TestBenchPanel, PropertiesPanel

onMounted(() => {
    // existing code
    window.setupPanelListeners?.('.panel-selector')
    window.minimizePanel?.('.timing-diagram-panel') // only for timing/testbench
})

Screenshots of the UI changes (If any) -

Recording.2026-02-04.185656.mp4

Code Understanding and AI Usage

Did you use AI assistance (ChatGPT, Claude, Copilot, etc.) to write any part of this code?

  • No, I wrote all the code myself
  • Yes, I used AI assistance (continue below)

If you used AI assistance:

  • I have reviewed every single line of the AI-generated code
  • I can explain the purpose and logic of each function/component I added
  • I have tested edge cases and understand how the code handles them
  • I have modified the AI output to follow this project's coding standards and conventions

Explain your implementation approach:

The problem occurs because of a mismatch between Vue's component lifecycle and jQuery's event handling. When the window resizes across the 991px breakpoint, Vue conditionally renders/unmounts panel components using v-if="!simulatorMobileStore.showMobileView". This destroys the DOM elements that jQuery listeners were attached to.So I re-attached listeners on component mount.

  • window.setupPanelListeners(selector): Re-attaches jQuery click handlers for minimize/maximize buttons on a specific panel
  • window.minimizePanel(selector): Triggers the minimize click event programmatically.
  • onMounted(): Vue lifecycle hook that runs when component's DOM is ready.

Checklist before requesting a review

  • I have added proper PR title and linked to the issue
  • I have performed a self-review of my code
  • I can explain the purpose of every function, class, and logic block I added
  • I understand why my changes work and have tested them thoroughly
  • I have considered potential edge cases and how my code handles them
  • If it is a core feature, I have added thorough tests
  • My code follows the project's style guidelines and conventions

Note: Please check Allow edits from maintainers if you would like us to assist in the PR.

Summary by CodeRabbit

  • New Features
    • Centralized per-panel interaction setup for more consistent drag, double‑click, and minimize/maximize behavior.
    • Timing Diagram and Testbench panels now auto‑minimize on startup to optimize workspace.
  • Bug Fixes
    • Prevents duplicate/conflicting panel event handlers for more reliable UI behavior and improved panel dragging z‑order.

@netlify
Copy link

netlify bot commented Jan 28, 2026

Deploy Preview for circuitverse ready!

Name Link
🔨 Latest commit af56bdb
🔍 Latest deploy log https://app.netlify.com/projects/circuitverse/deploys/698889300e4535000888fdb0
😎 Deploy Preview https://deploy-preview-882--circuitverse.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 47 (🔴 down 2 from production)
Accessibility: 73 (no change from production)
Best Practices: 92 (no change from production)
SEO: 82 (no change from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 28, 2026

Walkthrough

Panel components (ElementsPanel, PropertiesPanel, TestBenchPanel, TimingDiagramPanel) import and call an exported setupPanelListeners(selector) during onMounted; TestBenchPanel and TimingDiagramPanel also call an exported minimizePanel(selector) on mount. The simulator UX module (src/simulator/src/ux.js and v1 equivalent) adds and exports setupPanelListeners and minimizePanel, refactors setupPanels to invoke setupPanelListeners for multiple panels, and replaces direct DOM click triggers with namespaced event handlers and minimizePanel calls to centralize panel event wiring. Drag handler binding was made idempotent by namespacing the mousedown handler (mousedown.dragging).

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically identifies the main issue being fixed: panel buttons becoming unresponsive after window resize, which matches the core problem addressed in the changeset.
Linked Issues check ✅ Passed The PR addresses all coding requirements from issue #874: re-attaches jQuery event handlers when Vue components mount to restore responsiveness to panel buttons after window resize by calling setupPanelListeners and minimizePanel in onMounted hooks across all affected panel components.
Out of Scope Changes check ✅ Passed All changes are scoped to fixing panel button unresponsiveness: modifications to panel components (ElementsPanel, PropertiesPanel, TestBenchPanel, TimingDiagramPanel) and ux.js are directly addressing event handler persistence, with a single supporting change to drag.ts for handler namespace cleanup.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

No actionable comments were generated in the recent review. 🎉


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/simulator/src/ux.js (1)

380-408: Duplicate event handlers will accumulate on repeated calls.

Each time setupPanelListeners is called (after every Vue remount on window resize), new jQuery handlers are attached without removing the previous ones. This causes:

  1. Multiple click/dblclick handlers firing for a single interaction.
  2. The minimized closure variable becomes stale — each call creates a new minimized, but old handlers still reference their own copy.

Detach existing handlers before re-attaching:

🐛 Proposed fix to prevent duplicate handlers
 function setupPanelListeners(panelSelector) {
     var headerSelector = `${panelSelector} .panel-header`
     var minimizeSelector = `${panelSelector} .minimize`
     var maximizeSelector = `${panelSelector} .maximize`
     var bodySelector = `${panelSelector} > .panel-body`
 
     dragging(headerSelector, panelSelector)
-    // Current Panel on Top
-    var minimized = false
-    $(headerSelector).on('dblclick', () =>
+    // Remove existing handlers before re-attaching
+    $(headerSelector).off('dblclick')
+    $(minimizeSelector).off('click')
+    $(maximizeSelector).off('click')
+
+    // Track minimized state via DOM visibility instead of closure
+    $(headerSelector).on('dblclick', () => {
+        var minimized = $(bodySelector).is(':hidden')
         minimized
             ? $(maximizeSelector).trigger('click')
             : $(minimizeSelector).trigger('click')
-    )
+    })
     // Minimize
     $(minimizeSelector).on('click', () => {
         $(bodySelector).hide()
         $(minimizeSelector).hide()
         $(maximizeSelector).show()
-        minimized = true
     })
     // Maximize
     $(maximizeSelector).on('click', () => {
         $(bodySelector).show()
         $(minimizeSelector).show()
         $(maximizeSelector).hide()
-        minimized = false
     })
 }
🤖 Fix all issues with AI agents
In `@v1/src/simulator/src/ux.js`:
- Around line 353-357: setupPanelListeners is currently binding jQuery handlers
multiple times (called from setupPanels and again on Vue mount), causing stacked
event handlers; update setupPanelListeners to use namespaced events and call
.off('event.namespace') (or .off('.namespace')) on the specific panel selectors
before attaching handlers so each bind replaces previous ones (use a unique
namespace like '.panelListeners'); ensure all .on(...) calls inside
setupPanelListeners are converted to namespaced events (e.g.,
'click.panelListeners') and removed via .off(...) on the same selectors prior to
re-binding.
🧹 Nitpick comments (1)
src/components/Panels/TimingDiagramPanel/TimingDiagramPanel.vue (1)

56-59: Add TypeScript declarations for global window helpers.

These functions are assigned to window in src/simulator/src/ux.js but lack TypeScript declarations, causing potential type errors when called from .vue and .ts files. Add these declarations to your global typings file (e.g., src/env.d.ts or a dedicated global.d.ts):

Global typing declaration
+declare global {
+  interface Window {
+    setupPanelListeners?: (panelSelector: string) => void
+    minimizePanel?: (panelSelector: string) => void
+  }
+}

@senutpal senutpal marked this pull request as draft January 31, 2026 06:47
@senutpal senutpal marked this pull request as ready for review February 4, 2026 13:13
@senutpal
Copy link
Contributor Author

senutpal commented Feb 4, 2026

ready to review @tachyons @ThatDeparted2061 @Nihal4777

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
v1/src/simulator/src/ux.js (1)

381-414: ⚠️ Potential issue | 🟠 Major

Add cleanup before jQuery event binding in dragging().

The dragging() function at line 75 attaches a mousedown listener via $(DragEl).on('mousedown', ...) without removing previous listeners. When setupPanelListeners() runs on repeated remounts, these handlers will stack, causing the z-index logic to execute multiple times per click.

Add .off('mousedown') before .on() to prevent accumulation:

Suggested fix
$(DragEl)
    .off('mousedown')
    .on('mousedown', () => {
        $(`.draggable-panel:not(${DragEl})`).css('z-index', '99')
        $(DragEl).css('z-index', '99')
    })

The interact.js call handles repeated invocation safely (replaces config), but the jQuery binding does not.

src/simulator/src/ux.js (1)

381-413: ⚠️ Potential issue | 🟡 Minor

Add .off('mousedown') cleanup before reattaching handler in dragging().

The jQuery event binding on line 75 lacks cleanup. While interact.js on line 51 likely replaces configuration safely, the $(DragEl).on('mousedown') handler will stack if dragging() is called repeatedly. Use .off('mousedown') before .on(), or adopt a namespace like .off('mousedown.dragging').on('mousedown.dragging') to match the idempotent pattern already used elsewhere in ux.js (lines 390, 398, 407).

Copy link
Member

@Nihal4777 Nihal4777 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@senutpal I’d recommend exporting setupPanelListeners and minimizePanel from ux.js and importing them where needed instead of attaching them to window.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@v1/src/simulator/src/ux.js`:
- Around line 386-388: The dragging() function is currently attaching a jQuery
mousedown handler with no cleanup, which allows duplicate handlers to accumulate
when setupPanelListeners is called multiple times; update dragging() to remove
existing handlers before attaching by using namespaced events (e.g.,
.off('mousedown.dragging') before .on('mousedown.dragging', ...)) or call
.off('mousedown') first, and ensure any interact.js instantiation inside
dragging() is made idempotent (destroy or reconfigure existing interactable
before re-initializing) so repeated calls do not stack listeners or duplicate
interact.js behavior.

@senutpal
Copy link
Contributor Author

senutpal commented Feb 8, 2026

implemented suggestions @Nihal4777

@senutpal senutpal requested a review from Nihal4777 February 8, 2026 12:20
Nihal4777
Nihal4777 previously approved these changes Feb 8, 2026
Copy link
Member

@Nihal4777 Nihal4777 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @senutpal for implementing the changes.

@Nihal4777 Nihal4777 self-requested a review February 8, 2026 12:37
@Nihal4777 Nihal4777 dismissed their stale review February 8, 2026 12:37

coderabbit suggestion not implemented.

@senutpal
Copy link
Contributor Author

senutpal commented Feb 8, 2026

implemented coderabbit suggestions @Nihal4777

@Nihal4777
Copy link
Member

Thanks @senutpal for the quick changes. ❤️

@Nihal4777 Nihal4777 merged commit 4aa657b into CircuitVerse:main Feb 8, 2026
14 of 15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🐞 Bug: Dialog buttons become unresponsive after window resize

2 participants