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

Component overlay opens multiple times in Safari #7245

Closed
KremnevDmitry opened this issue Mar 20, 2024 · 3 comments · Fixed by #7246
Closed

Component overlay opens multiple times in Safari #7245

KremnevDmitry opened this issue Mar 20, 2024 · 3 comments · Fixed by #7246
Assignees

Comments

@KremnevDmitry
Copy link

Description

Selecting values in any component that has an overlay causes the overlay to open multiple times.
Please, see attachment:

Screen.Recording.2024-03-20.at.10.28.44.mov

Expected outcome

The overlay won't open again.

Minimal reproducible example

Demo project:
my-app.zip

This does not happen with Google Chrome Version 122.0.6261.129 (Official Build) (x86_64) or with Firefox Version 124.0 (64-bit). Only Safari 17.4 is affected.

Steps to reproduce

  1. Start demo project
  2. Open address form view
  3. Try selecting any value in the State or Country fields

Environment

Flow: 24.3.7
Vaadin: 24.3.7
Java: Amazon.com Inc. 17.0.9
OS: aarch64 Mac OS X 14.4
Browser: Safari - Version 17.4 (19618.1.15.11.12)

Browsers

Safari

@web-padawan
Copy link
Member

web-padawan commented Mar 20, 2024

Thanks for the issue. Tested and could not reproduce in Safari 17.3.1:

select-safari-17.3.mp4

Confirmed that since Safari 17.4 it fails. This seems like a bug in Safari that we might need to workaround.

UPD: the issue can be also reproduced using web component without Flow, e.g. in dev page in this repo.

@web-padawan
Copy link
Member

Tested this and found that vaadin-date-picker and vaadin-combo-box overlays are also blinking on close.
The issue appears to be related to the dummy animation in Lumo (Material doesn't have it and works fine).

Removing these lines (or at least removing closing from here) helps to resolve the issue in Safari 17.4:

:host([opening]),
:host([closing]) {
animation: 0.14s lumo-overlay-dummy-animation;
}

@web-padawan
Copy link
Member

Created a reduced test case using simplified version of Lumo animations and longer duration to make bug noticeable:

<x-overlay-host>
  <button>Toggle</button>
</x-overlay-host>

<script type="module">
  customElements.define(
    'x-overlay-host',
    class extends HTMLElement {
      constructor() {
        super();
        this.attachShadow({ mode: 'open' });
        this.shadowRoot.innerHTML = `
          <style>
            :host {
              display: block;
            }
          </style>
          <slot></slot>
          <div>Overlay content</div>
        `;

        this.overlay = this.shadowRoot.querySelector('div');
        this.overlay.attachShadow({ mode: 'open' });
        this.overlay.shadowRoot.innerHTML = `
          <style>
            :host {
              display: flex;
            }

            [part='overlay'] {
              padding: 10px;
              border: solid 1px #ccc;
            }

            @keyframes x-overlay-dummy-animation {
              0% {
                opacity: 1;
              }

              100% {
                opacity: 1;
              }
            }

            :host(:not([opened]):not([closing])) {
              display: none !important;
            }

            :host([opening]),
            :host([closing]) {
              animation: 3s x-overlay-dummy-animation;
            }

            [part='overlay'] {
              will-change: opacity, transform;
            }

            :host([opening]) [part='overlay'] {
              animation: 1s x-overlay-enter ease-out both;
            }

            @keyframes x-overlay-enter {
              0% {
                opacity: 0;
                transform: translateY(-4px);
              }
            }

            :host([closing]) [part='overlay'] {
              animation: 1s x-overlay-exit both;
            }

            @keyframes x-overlay-exit {
              100% {
                opacity: 0;
              }
            }
          </style>
          <div part="overlay">
            <slot></slot>
          </div>
        `;
      }

      connectedCallback() {
        const button = this.querySelector('button');
        button.addEventListener('click', (e) => {
          if (this.opened) {
            this.close();
          } else {
            this.open();
          }
        });
      }

      close() {
        this.opened = false;

        this.overlay.removeAttribute('opened');

        // Animate closing
        const listener = (event) => {
          this.overlay.removeAttribute('closing');

          this.shadowRoot.insertBefore(this.overlay, this._placeholder);
          this.shadowRoot.removeChild(this._placeholder);

          this._placeholder = null;

          this.overlay.removeEventListener('animationend', listener);
        };
        this.overlay.addEventListener('animationend', listener);

        this.overlay.setAttribute('closing', '');
      }

      open() {
        this.opened = true;

        this.overlay.setAttribute('opened', '');
        this.overlay.setAttribute('opening', '');

        // Teleport the overlay under document body
        this._placeholder = document.createComment('x-overlay-placeholder');
        this.shadowRoot.insertBefore(this._placeholder, this.overlay);
        document.body.appendChild(this.overlay);

        // Animate opening
        const listener = (event) => {
          this.overlay.removeAttribute('opening');
          this.overlay.removeEventListener('animationend', listener);
        };
        this.overlay.addEventListener('animationend', listener);
      }
    },
  );
</script>

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

Successfully merging a pull request may close this issue.

2 participants