Skip to content

fix: track visual modality so dialogs are refreshed on hotswap - #25417

Open
totally-not-ai[bot] wants to merge 2 commits into
mainfrom
fix/hotswap-refresh-with-visual-modality
Open

fix: track visual modality so dialogs are refreshed on hotswap#25417
totally-not-ai[bot] wants to merge 2 commits into
mainfrom
fix/hotswap-refresh-with-visual-modality

Conversation

@totally-not-ai

@totally-not-ai totally-not-ai Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Dialogs are visually modal by default since 25.0, but ModalityMode.VISUAL was mapped to setChildModeless, so a component with visual modality was not tracked on the server side at all.

Both code paths that deal with overlays attached to the UI instead of the route were guarded by UI.hasModalComponent(), so with an open dialog they became no-ops:

  • AbstractNavigationStateRenderer no longer detached the dialog on a route refresh, leaving it visible with outdated contents.
  • Hotswapper no longer requested a refresh of the whole route chain.

What changed

  • Components set to ModalityMode.VISUAL are now tracked in UIInternals without making the UI inert. The meaning of hasModalComponent() and the inert semantics are unchanged; the new hasModalityComponent() / getModalityComponents() cover both strict and visual modality, and both call sites take the new information into account.
  • Components with modality are kept in a single recency-ordered stack, in the order they were set, while the existing modal component stack keeps taking care of the inert state only. Tracking strict and visual modality in two separate stacks would make getModalityComponents() report the components in the wrong order and, when a component switched between the two modes, report it twice.
  • Registration of the detach listener that stops tracking a component is idempotent, so repeatedly applying the same modality to a component does not pile up listeners on its element.
  • cleanModalComponents() in AbstractNavigationStateRenderer now removes all components with modality on REFRESH_ROUTE, instead of draining only the strict-modal stack. Modeless components are left untouched.

Fixes #25415

API Changes

com.vaadin.flow.component.internal.UIInternals

// Added
public boolean hasModalityComponent() // true if a child component with STRICT or VISUAL modality is set; unlike hasModalComponent() it also counts components that only show a modality curtain
public List<Component> getModalityComponents() // child components with STRICT or VISUAL modality, most recently set first, never null
public void setChildVisuallyModal(Component child) // tracks the child as having modality without making the UI and its other components inert

Dialogs are visually modal by default since 25.0, and ModalityMode.VISUAL
was mapped to setChildModeless, so a component with visual modality was
not tracked on the server side at all.

Both the code paths that deal with overlays attached to the UI instead of
the route are guarded by UI.hasModalComponent(), so with an open dialog
they became no-ops: AbstractNavigationStateRenderer no longer detached the
dialog on a route refresh, leaving it visible with outdated contents, and
Hotswapper no longer requested a refresh of the whole route chain.

Components set to ModalityMode.VISUAL are now tracked in UIInternals
without making the UI inert, keeping the meaning of hasModalComponent()
and the inert semantics unchanged, and both call sites take the new
information into account.

Fixes #25415
Tracking strict and visual modality in two separate stacks made
getModalityComponents() report the components in the wrong order and, when
a component switched between the two modes, report it twice.

Components with modality are now kept in one stack, in the order they were
set, while the existing modal component stack keeps taking care of the
inert state only. Registration of the detach listener that stops tracking a
component is idempotent, so repeatedly applying the same modality to a
component does not pile up listeners on its element.
@github-actions github-actions Bot added the +0.0.1 label Sep 1, 2026
@sonarqubecloud

sonarqubecloud Bot commented Sep 1, 2026

Copy link
Copy Markdown

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Test Results

 1 389 files  ±0   1 390 suites  ±0   1h 28m 24s ⏱️ - 1m 34s
10 657 tests +5  10 590 ✅ +5  67 💤 ±0  0 ❌ ±0 
10 976 runs  +5  10 908 ✅ +5  68 💤 ±0  0 ❌ ±0 

Results for commit 3471c2b. ± Comparison against base commit e736ed3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Changes to the Dialog are not reflected in the UI after HotSwap

0 participants