Skip to content

grey out modals when focus is outside - Eagle 1558 - #1076

Merged
M-Wicenec merged 3 commits into
masterfrom
eagle-1558
Sep 30, 2026
Merged

M-Wicenec merged 3 commits into
masterfrom
eagle-1558

Conversation

@M-Wicenec

@M-Wicenec M-Wicenec commented Sep 23, 2026 •

Copy link
Copy Markdown
Collaborator

added an event listener that cleans itself up when no modals are being used

if the modal is in a draggable state, it's header will appear greyed out when the user is interacting with ui outside of the modal

renamed a function to be more indicative of what it does, and removed an unnecessary console.log

Summary by Sourcery

Add focus-away feedback for draggable modals and improve modal listener lifecycle management.

New Features:

  • Visually indicate when a draggable modal loses focus to interactions outside the modal.

Bug Fixes:

  • Manage modal focus tracking only while modals are open and clear focus-away styling when modals close.

Enhancements:

  • Rename the graph deselection action to more clearly describe that it deselects all objects.

@sourcery-ai

sourcery-ai Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Reviewer's Guide

The PR introduces capture-phase, self-cleaning modal mousedown tracking to visually grey out draggable modal headers when interaction moves outside modal content, while preserving modal lifecycle and drag behavior. It also clarifies the graph deselection API and shortcut naming and removes an unnecessary console log.

Sequence diagram for modal focus-away tracking

sequenceDiagram
    participant User
    participant Document
    participant Modal as Open modal
    participant ModalContent as Modal content

    User->>Document: mousedown
    Document->>Modal: modalFocusStateHandler(event)
    alt target inside .modal-content
        Modal->>Modal: removeClass(modal-focus-away)
    else target outside .modal-content
        Modal->>Modal: addClass(modal-focus-away)
    end
    User->>ModalContent: mousedown on modal header
    ModalContent->>Modal: removeClass(modal-focus-away)
Loading

State diagram for modal focus listener lifecycle

stateDiagram-v2
    [*] --> NoModal
    NoModal --> ModalOpen: show.bs.modal / attachModalFocusListener
    ModalOpen --> ModalOpen: mousedown / update modal-focus-away
    ModalOpen --> NoModal: hide.bs.modal and no .modal.show / detachModalFocusListener
    ModalOpen --> ModalOpen: hide.bs.modal while another modal is shown
Loading

Flow diagram for graph deselection shortcut rename

flowchart LR
    Escape[Escape shortcut] --> Shortcut[select_no_objects_in_graph]
    Shortcut --> Method[Eagle.selectNoObjectsInGraph]
    Method --> Clear["selectedObjects([])"]
Loading

File-Level Changes

Change Details Files
Added lifecycle-managed modal focus tracking that greys out the modal header when pointer interaction occurs outside modal content.
  • Register a capture-phase mousedown listener when a modal opens and remove it once no modal remains open.
  • Toggle the modal focus-away class based on whether the event target is inside modal content.
  • Reset the class during modal hide/show and preserve existing draggable modal pointer-event behavior.
src/Eagle.ts
static/base.css
Renamed the graph deselection action to clarify that it clears selected objects.
  • Renamed the Eagle method and keyboard shortcut identifier/text.
  • Updated the Escape shortcut to call the renamed method.
  • Removed the diagnostic console output.
src/Eagle.ts
src/KeyboardShortcut.ts

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="src/Eagle.ts" line_range="5787-5788" />
<code_context>
         $('.modal .modal-content').css({"pointerEvents":"auto"})
+
+        // Keep the listener alive if another modal is taking over during this transition.
+        if ($('.modal.show').length === 0) {
+            detachModalFocusListener();
+        }
     });  
</code_context>
<issue_to_address>
**issue (bug_risk):** The listener is not detached when the last modal is closed because this check runs in the `hide.bs.modal` handler while the closing modal still has the `.show` class, so `$('.modal.show').length` is nonzero. The document-level `mousedown` listener therefore remains attached permanently after the first modal is used.

**Triggers:** After a modal has been opened and then closed.

**Suggested fix:** Move the check to a `hidden.bs.modal` handler, or defer the check until the modal has finished hiding.
</issue_to_address>

Sourcery assessment

Approval pending. 1 finding to address first.

Blocking findings: src/Eagle.ts:5788


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread src/Eagle.ts

@james-strauss-uwa james-strauss-uwa left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks good

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Sourcery assessment

Approved.

@M-Wicenec
M-Wicenec merged commit ea2ec5e into master Sep 30, 2026
5 checks passed
@M-Wicenec
M-Wicenec deleted the eagle-1558 branch September 30, 2026 06:54
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.

2 participants