Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

app-header-layout / stacking context / header vs. dialog in content container #279

Closed
JanGunzenhauser opened this issue Jul 21, 2016 · 14 comments

Comments

@JanGunzenhauser
Copy link

JanGunzenhauser commented Jul 21, 2016

Description

When using paper-dialog within components within #contentContainer of app-header-layout, the app-header stays on top of paper-dialog. Z-index 1 is assigned to app-header, while z-index 0 is assigned to #contentContainer, which seems to cause this behavior. Removing z-index 0 from contentContainer, this issue resolves.

Expected outcome

paper-dialog should stay on top of the app-header like its z-index suggests

Actual outcome

paper-dialog appears on top of other things within #contentContainer but not on top of the app-header

Steps to reproduce

  1. Use standard app-header-layout like in the first example of the docs https://elements.polymer-project.org/elements/app-layout?active=app-header-layout
  2. Replace "main content" with a component that has a dialog inside (e.g. iron-pages with a view component)
  3. Style the dialog to be high enough so that header and dialog overlap
  4. Open the dialog
<app-header-layout>

      <app-header reveals>
        <app-toolbar>
          <!-- Header content -->
        </app-toolbar>
      </app-header>  

      <iron-pages role="main" selected="[[activeView]]" attr-for-selected="name">
        <!-- a view with a paper-dialog inside -->
        <view-home 
          name="home"   
        </view-home>
      </iron-pages>

</app-header-layout>
@JanGunzenhauser
Copy link
Author

I have another issue in this same context. Using a paper-dialog with backdrop makes the backdrop appear in front of the dialog. Removing z-index 0 from the app-header-layout itself, this issue resolves.

So the current solution is to make a custom clone of app-header-layout without these z-index values. It would be nice if this could work out of the box. Can someone explain why they were set in the first place?

@jeremylowery
Copy link

jeremylowery commented Jul 21, 2016

We have run up on this issue as well. It applies to paper-toast as well as paper-dialog.

Actually, it also applies to app-drawer-layout as well. paper-dialog and friends are stuck behind the app-drawer.

The only solution we've found is to put the dialog/toast elements outside the app-drawer-layout and use events to show these. Quite the dirty hack.

@blasten
Copy link
Contributor

blasten commented Aug 1, 2016

  1. You could use app-header by itself (without app-header-layout) For example: https://github.com/PolymerElements/app-layout/blob/master/app-header/demo/blend-background-1.html By using app-header alone, you can set your own z-indexes.

Or you could move the paper-dialog outside app-header-layout.

@safizn
Copy link

safizn commented Aug 17, 2016

I wish there would be a cleaner solution. Maybe modify app-header-layout to allow setting z-index.

@abdonrd
Copy link
Member

abdonrd commented Sep 5, 2016

I have the same problem. :/

And I can't move the paper-dialog outside app-header-layout.

@abdonrd
Copy link
Member

abdonrd commented Sep 7, 2016

For example, I use the app-header-layout to fix the app-header.

<app-header-layout>
  <app-header fixed>
    [...]
  </app-header>
  <iron-pages selected="[[selectedPage]]" attr-for-selected="page-name" role="main">
    <view-home page-name="home"></view-home> <!-- with a paper-dialog inside -->
    [...]
  </iron-pages>
</app-header-layout>

And I can't move the paper-dialog outside app-header-layout.

How to fix it?

@liabru
Copy link

liabru commented Sep 19, 2016

I've solved this issue in my project by dynamically moving the dialog when it gets opened. I move it to be next to the overlay in the DOM, which already inserts itself at the end of body. It's still a bit of a hack but it seems to work fine for now until this gets fixed (just be careful with your styling):

<paper-dialog modal on-iron-overlay-opened="_overlayOpened"></paper-dialog>
_overlayOpened: function (e) {
  var dialog = e.target;
  var overlay = dialog.backdropElement;

  if (overlay.previousSibling !== dialog) {
    overlay.parentNode.insertBefore(dialog, null);
  }
}

@abdonrd
Copy link
Member

abdonrd commented Nov 4, 2016

Any news?

@florent1933
Copy link

florent1933 commented Dec 12, 2016

@liabru : I try your solution but with an animation, it's not really usable. It seems to open twice. (and in angular2, we lost bindings)

To correct the problem, I remove z-index :host and contentContainer of app-header-layout but it was not perfect.

In mobile view, the drawer was behind the app-header. To fix this new issue I override the z-index of app-header with adding :host { z-index: 0!important }

@rwestlund
Copy link

In my app, I decoupled my dialogs from the elements that use them, by using iron-signals. When an element needs to show a dialog (or anything with an overlay), it fires a signal, which a dedicated element catches. This allows my to put my forms outside of app-drawer-layout. I'm very pleased with this solution, as I now only need one instance of each form.

@web-padawan
Copy link

web-padawan commented Jan 30, 2017

Today I faced this weird issue with paper-dialog when migrating from paper-drawer-panel to app-layout. Do you guys really consider this WAI having this not fixed for half a year? 👎

@keanulee
Copy link
Contributor

@web-padawan We create a stacking context for the content of app-header-layout because we anticipate that, in most cases, you want to put content below the header. The fact that a dialog is trapped inside the content's stacking context is something that is unavoidable with the web platform (i.e. if you want to build something that works in all browsers, this is a limitation you have to work with). In other words, we can't fix this issue. Here's another GitHub issue that gives some more explanation.

As suggested above, you can still use app-header on its own (without app-header-layout) to control stacking contexts yourself. We provide app-header-layout to support the general use case, but we also support using app-header independently.

@web-padawan
Copy link

@keanulee Thanks for explanation, makes sense. I already switched to simple app-header usage.

@Alorel
Copy link

Alorel commented May 17, 2017

Hey, this might be an old discussion, but I found another workaround. You can wrap your paper dialogs in a dummy custom element and propagate dialog open/close events up the shadow DOM.

Assume your hierarchy is as such:

app-shell
  iron-pages
      my-page
        paper-dialog

Your wrapper could be something among the lines of

<dom-module id="my-dialog">
  <template>
    <!-- Propagate any arguments as necessary -->
    <paper-dialog opened="{{opened}}">
      <slot></slot>
    </paper-dialog>
  </template>
  <script>
    class MyDialog extends Polymer.Element {
      static get is() {
        return 'my-dialog';
      }

      static get properties() {
        return {
          opened: {
            type: Boolean,
            notify: true,
            observer: '_openChanged'
          }
          // ... and anything else you might need
        };
      }

      _openChanged(curr, old) {
        if (undefined !== old) {
          const name = `my-dialog-${curr ? 'opened' : 'closed'}`,
                // Make sure our event passes the shadow DOM
                options = {
                  bubbles: true,
                  composed: true
                };
          this.dispatchEvent(new CustomEvent(name, options));
        }
      }
    }

    customElements.define(MyDialog.is, MyDialog);
  </script>
</dom-module>

Having replaced your paper-dialogs with my-dialog, you can add an event listener on whatever element would receive them, e.g. iron-pages in the structure above. Add a CSS rule to your app shell's styles that sets z-index to auto:

.z-auto {
   z-index: auto !important;
}

Finally, listen for the events in your app shell and add or remove the rule accordingly:

<dom-module id="my-app">
  <template>
    <style>
      .z-auto {
        z-index: auto !important;
      }
    </style>
    <app-header-layout>
      <app-header id="header">
        <!-- Header contents -->
      </app-header>
      <iron-pages on-my-dialog-opened="_dialogOpened" on-my-dialog-closed="_dialogClosed">
        <my-page></my-page>
      </iron-pages>
    </app-header-layout>
  </template>
  <script>
    class MyApp extends Polymer.Element {
      static get is() {
        return 'my-app';
      }

      _dialogOpened() {
        this.$.header.classList.add('z-auto');
      }

      _dialogClosed() {
        this.$.header.classList.remove('z-auto');
      }
    }

    customElements.define(MyApp.is, MyApp);
  </script>
</dom-module>

Might not be the cleanest solution, but if it looks stupid and it works, it ain't stupid!

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

No branches or pull requests