vaadin-component-factory / vcf-leaflet

vcf-leaflet provides a Java API for Leaflet.
Other
0 stars 1 forks source link

Dialog Renders Behind Leaf Let Map #14

Open JariHanah opened 4 months ago

JariHanah commented 4 months ago

Describe the bug Dialog and MenuBar shows behind the LeafLet map.

To Reproduce Steps to reproduce the behavior: just fire a Dialog after clicking on a Marker.onClick(new Dialog). Or add a MenuBar above or below the leafLet Map, if it opens, it will render behind the map.

Expected behavior Dialog should appear above the Map.

Screenshots Sure

Desktop (please complete the following information):

Smartphone (please complete the following information):

Additional context Check code:

package com.example.application.views;

import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.dialog.Dialog;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.*;
import org.vaadin.addons.componentfactory.leaflet.LeafletMap;
import org.vaadin.addons.componentfactory.leaflet.layer.events.MouseEvent;
import org.vaadin.addons.componentfactory.leaflet.layer.groups.LayerGroup;
import org.vaadin.addons.componentfactory.leaflet.layer.map.options.DefaultMapOptions;
import org.vaadin.addons.componentfactory.leaflet.layer.map.options.MapOptions;
import org.vaadin.addons.componentfactory.leaflet.layer.ui.marker.Marker;
import org.vaadin.addons.componentfactory.leaflet.types.LatLng;

@PageTitle("MapLeafLet3")
@Route(value = "map3", layout = MainLayout.class)
@RouteAlias(value = "map33")
public class MapView3 extends VerticalLayout implements AfterNavigationObserver {
    //LeafletMap leafletMap;
    LayerGroup lg;
    @Override
    public void afterNavigation(AfterNavigationEvent afterNavigationEvent) {
        MapOptions options = new DefaultMapOptions();
        options.setCenter(new LatLng(47.070121823, 19.204101562500004));
        options.setZoom(2);
        LeafletMap leafletMap = new LeafletMap(options );
        leafletMap.setBaseUrl("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png");
        leafletMap.setSizeFull();
        //leafletMap.setHeight("400px");
        Marker m=new Marker(new LatLng(0,0));
        m.onClick(mouseEvent -> {
            System.err.println("Hello");
            Notification.show("marker clicked", 5000, Notification.Position.MIDDLE);
            Dialog d=new Dialog();
            d.add(new Button("Hello"));
            d.open();
        });
        lg=new LayerGroup();
        lg.addTo(leafletMap);

        m.addTo(lg);

        setSizeFull();
        add(leafletMap);

    //    add(new Button("HEY"));

    }

}

Screenshot 2024-04-30 121312

chippmann commented 1 month ago

This is due to the default z-index of leaflet maps: https://leafletjs.com/reference.html#map-pane

I have the following css which i inject into the shadow dom of the leaflet map to combat this:

/* customization of default map pane layers to not interfere with vaadin layering */
/* https://leafletjs.com/reference.html#map-pane */
.leaflet-map-pane {
    z-index: 0;
}
.leaflet-tile-pane {
    z-index: 1;
}
.leaflet-overlay-pane {
    z-index: 2;
}
.leaflet-shadow-pane {
    z-index: 3;
}
.leaflet-marker-pane {
    z-index: 4;
}
.leaflet-tooltip-pane {
    z-index: 5;
}
.leaflet-popup-pane {
    z-index: 6;
}

the injection i perform using a js function i call on the Map class:

override fun onAttach(attachEvent: AttachEvent?) {
        super.onAttach(attachEvent)
        // the LeafletMap component does not expose any parts through which we can customize the css in the shadow dom
        // hence, after our view is constructed, we inject the css we want manually into the shadow dom of the LeafletMap
        this.element.executeJs("window.injectStylesIntoShadowDom($0, $1)", map, css)
}

where css is the css above as a string which i load from the resource directory

the javascript i import on the view in question with: @JsModule("./injectStylesIntoShadowDom.js")

And the javascript i use resides in fontend/injectStylesIntoShadowDom.js:

/**
 * Injects CSS styles into the Shadow DOM of a given component.
 *
 * This is needed if a component does not expose any parts through which we can modify the css directly.
 *
 * An example is the LeafletMap component.
 *
 * @param element The Vaadin element for which we want to inject the css into the shadow dom
 * @param css The css we want to inject into the element
 */
window.injectStylesIntoShadowDom = (element, css) => {
    const shadowRoot = element.shadowRoot;
    if (shadowRoot) {
        const styleElement = document.createElement('style');
        styleElement.textContent = css;
        shadowRoot.appendChild(styleElement);
    }
};

Another way would be to simply increase the z-index of the dialog you want above the map to a value > 700