Skip to content

Vaadin 25 - Dialogs are drawn on top of loading indicator modality curtain #23173

@lwilliamson123

Description

@lwilliamson123

Description of the bug

With reference to documentation Flow Reference -> Advanced Topics -> The Loading Indicator

I have a custom loading indicator which puts up a modality curtain as described in this documentation, and displays a custom component that I added to the v-loading-indicator div (a 'please wait' label with a spinning image).

This worked perfectly in Vaadin 24 under all scenarios.

In Vaadin 25, dialogs still appear nice and bright 'above' the modality curtain, and can still be interacted with.

Note: The complete 'modality curtain' is great from our perspective, as we know the users are locked out from further interaction whilst a longer running process is happening, and we don't have to think about it too much or code too protectively.

Image Image

Expected behavior

The modality curtain put on v-loading-indicator should cover everything, ensuring that nothing in the UI can be interacted with,

Minimal reproducible example

Relevant styles.css section

/* START OF CUSTOM LOADING INDICATOR SECTION */

/* Custom loading indicator which puts up a full screen modal curtain (animated to avoid flickering).
   The default loading indicator is disabled in ApplicationServiceInitListener (which also adds a 
   'please wait' label as a child to the vaadin loading indicator div which has this class name. */
.v-loading-indicator {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  pointer-events: auto;
  animation: fadein 0.5s ease-out 1.4s normal 1 both;
  z-index: 2147483647;
}

@keyframes fadein {
  0% {
    background: rgba(0,0,0,0);
  }
  100% {
    background: rgba(0,0,0,.50);
  }
}

/* styling for the 'please wait' label added to our custom loading indicator - this is hidden until
   the loading indicator enters its second or third stage */
   
 /* Original position in centre - moved to top right in vaadin 25 so it is unlikely to be hidden by a dialog which is at the moment
    drawing over the top of the indicator overlay (hopefully vaadin will fix this)
    
.gh-loading-label {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);   
    background-color: var(--lumo-base-color);
    padding: 20px 40px 20px 15px;
    border-radius: var(--lumo-border-radius-m);
    box-shadow: var(--lumo-box-shadow-xl);
    font-size: var(--lumo-font-size-l);
    display: none;
}
*/

.gh-loading-label {
    position: absolute;
    top: 5px;
    right: 5px;   
    background-color: var(--lumo-base-color);
    padding: 20px 40px 20px 15px;
    border-radius: var(--lumo-border-radius-m);
    box-shadow: var(--lumo-box-shadow-xl);
    font-size: var(--lumo-font-size-l);
    display: none;
}

/* Adds a spinning icon gif after our 'please wait' label in our custom loading indicator */
.gh-loading-label::after {    
    content: "";
    display: inline-block;
    width: 16px;
    height: 16px; 
    background-image: url('images/loading.gif');
    background-size: cover;
    position: absolute;
    top: 50%;
    right: 15px;
    transform: translateY(-50%);    
}

/* show our 'please wait' label only in the second or third stage of the loading indicator */
.v-loading-indicator.second .gh-loading-label, .v-loading-indicator.third .gh-loading-label {
    display: inline-block;
}

/* hide this as it is unused and only appears when we disable the default loading indicator */
.v-status-message {
    display: none;
}

/* END OF CUSTOM LOADING INDICATOR SECTION */

Configuration code invoked on VaadinServiceInitListener.serviceInit(ServiceInitEvent event):

    private void registerCustomLoadingIndicatorPerUI(ServiceInitEvent event)
    {
        // The custom loading indicator will put up a modal curtain when activated (if request doesnt return within
        // 100ms), dim it after 2 seconds, then also display a "Please wait" label with spinny icon after 3 seconds.
        event.getSource().addUIInitListener(uiInitEvent -> {
            LoadingIndicatorConfiguration conf = uiInitEvent.getUI().getLoadingIndicatorConfiguration();

            // disable default theme to avoid showing the default loading indicator (we have our own - see styles.css)
            conf.setApplyDefaultTheme(false);

            // loading indicator to be displayed after 100ms (this will throw up our modal curtain, and start the animation process
            // for darkening the screen).
            conf.setFirstDelay(100);

            // second stage of loading indicator after 3s (this will show our please wait label)
            conf.setSecondDelay(3000);

            // third stage of loading indicator after 5s (no further visible changes, we keep showing the label)
            conf.setThirdDelay(5000);

            // add a "please wait" label to the div that vaadin supplies for a loading indicator (the label is styled in styles.css)
            uiInitEvent.getUI().getPage().executeJs("var loadingIndicator = document.querySelector('.v-loading-indicator');" +
                    "if (loadingIndicator) {" +
                    "    var label = document.createElement('label');" +
                    "    label.textContent = 'Please wait';" +
                    "    label.classList.add('" + CSSClassNames.LOADING_LABEL + "');" +
                    "    loadingIndicator.appendChild(label);" +
                    "}");
        });
    }

Versions

  • Vaadin / Flow version: 25.0.2
  • Java version: 21.0.9
  • OS version: Windows 10 Enterprise
  • Browser version (if applicable): Edge
  • Application Server (if applicable):
  • IDE (if applicable):

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    Status

    🏗 WIP

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions