Skip to content

[mdl] View transition for adding detail broken in Safari #9901

@sissbruecker

Description

@sissbruecker

Description

Specifically in Safari, the view transition for adding / showing the detail area is broken. It incorrectly slides out the master area to the right:

Bildschirmaufnahme.2025-08-05.um.11.46.25.mov

In Chrome it works correctly:

Bildschirmaufnahme.2025-08-05.um.11.47.07.mov

Expected outcome

The master area should not have a slide animation, at least not when the component is not in stack mode.

Minimal reproducible example

Can be reproduced with this version of the dev pages:

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Master-Detail Layout</title>
<link rel="stylesheet" href="/packages/vaadin-lumo-styles/lumo.css" />
<script type="module" src="./common.js"></script>
</head>
<body>
<style>
html,
body {
height: 100%;
margin: 0;
padding: 10px;
box-sizing: border-box;
}
mdl-view {
display: block;
height: 100%;
max-width: 100%;
max-height: 100%;
overflow: hidden;
}
body > mdl-view > vaadin-master-detail-layout {
border: 1px solid lightgray;
resize: both;
}
.master {
box-sizing: border-box;
height: 100%;
padding: 1.5rem;
overflow: auto;
}
.master > header {
display: flex;
align-items: center;
gap: 1em;
}
.master > header > h3 {
flex: auto;
}
.close-btn,
.replace-btn {
visibility: hidden;
position: absolute;
}
.detail .close-btn,
.detail .replace-btn {
visibility: visible;
position: relative;
}
.static-detail {
box-sizing: border-box;
height: 100%;
padding: 1.5rem;
overflow: auto;
}
</style>
<mdl-view></mdl-view>
<template id="static-detail">
<div class="static-detail">
<vaadin-button>Close</vaadin-button><br />
<vaadin-text-field label="First Name"></vaadin-text-field>
<vaadin-text-field label="Last Name"></vaadin-text-field>
<vaadin-text-field label="Email"></vaadin-text-field>
<vaadin-select label="Country"></vaadin-select>
</div>
</template>
<script type="module">
// Enable feature flag
window.Vaadin ||= {};
window.Vaadin.featureFlags ||= {};
window.Vaadin.featureFlags.masterDetailLayoutComponent = true;
import '@vaadin/button';
import '@vaadin/checkbox';
import '@vaadin/select';
import '@vaadin/text-field';
import '@vaadin/radio-group';
import '@vaadin/icon';
import '@vaadin/master-detail-layout';
import '@vaadin/tooltip';
import '@vaadin/vaadin-lumo-styles/icons';
import { html, LitElement, render } from 'lit';
window.mdlCount = 1;
// prettier-ignore
const lorem = html`Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eligendi suscipit rem, non temporibus
laboriosam maiores distinctio numquam, dolorum ducimus dolores sequi reprehenderit iste consectetur adipisci
delectus aperiam voluptatibus! Vitae, adipisci.`;
class MDLView extends LitElement {
static get is() {
return 'mdl-view';
}
createRenderRoot() {
return this;
}
createDetail() {
const temp = document.createElement('div');
render(html`<mdl-view class="detail"></mdl-view>`, temp, { host: this });
return temp.firstElementChild;
}
firstUpdated() {
this._mdl = this.querySelector('vaadin-master-detail-layout');
this._parentMdl = this.closest('vaadin-master-detail-layout');
}
openDetail() {
window.mdlCount++;
this._mdl._setDetail(this.createDetail());
}
openStaticDetail() {
const detail = document.querySelector('#static-detail').content.firstElementChild.cloneNode(true);
detail.querySelector('vaadin-button').onclick = () => {
detail.closest('vaadin-master-detail-layout')._setDetail(null);
};
this._mdl._setDetail(detail);
}
closeDetail() {
this._mdl._setDetail(null);
}
closeParentDetail() {
this._parentMdl._setDetail(null);
}
replaceDetail() {
window.mdlCount++;
const detail = this.createDetail();
const prop = this._parentMdl.orientation == 'vertical' ? 'height' : 'width';
if (this.style.getPropertyValue(prop) != '500px') {
detail.style.setProperty(prop, '500px');
} else {
detail.style.setProperty(prop, '300px');
}
this._parentMdl._setDetail(detail);
}
render() {
return html`
<vaadin-master-detail-layout>
<div class="master">
<header>
<vaadin-button
aria-label="close detail view"
class="close-btn"
theme="tertiary contrast icon"
@click=${this.closeParentDetail}
>
<vaadin-icon icon="lumo:arrow-left"></vaadin-icon>
</vaadin-button>
<h3>View ${window.mdlCount}</h3>
<vaadin-button
aria-label="replace detail view"
class="replace-btn"
theme="tertiary icon"
@click=${this.replaceDetail}
>
<vaadin-icon icon="lumo:reload">
<vaadin-tooltip
slot="tooltip"
text="Replace with another detail view with different size"
></vaadin-tooltip>
</vaadin-icon>
</vaadin-button>
</header>
<vaadin-radio-group
@change=${this._configChange}
class="orientation"
label="Orientation"
theme="vertical"
value="horizontal"
>
<vaadin-radio-button value="horizontal" label="Horizontal"></vaadin-radio-button>
<vaadin-radio-button value="vertical" label="Vertical"></vaadin-radio-button>
</vaadin-radio-group>
<vaadin-radio-group
@change=${this._configChange}
class="containment"
label="Containment"
theme="vertical"
value="layout"
>
<vaadin-radio-button value="layout" label="Layout"></vaadin-radio-button>
<vaadin-radio-button value="viewport" label="Viewport"></vaadin-radio-button>
</vaadin-radio-group>
<br />
<vaadin-radio-group
@change=${this._configChange}
class="masterSize"
label="Master Size"
theme="vertical"
value="auto"
>
<vaadin-radio-button value="auto" label="Auto"></vaadin-radio-button>
<vaadin-radio-button value="250px" label="250px"></vaadin-radio-button>
<vaadin-radio-button value="30%" label="30%"></vaadin-radio-button>
</vaadin-radio-group>
<vaadin-radio-group
@change=${this._configChange}
class="masterMinSize"
label="Master Min Size"
theme="vertical"
value="none"
>
<vaadin-radio-button value="none" label="None"></vaadin-radio-button>
<vaadin-radio-button value="250px" label="250px"></vaadin-radio-button>
<vaadin-radio-button value="100%" label="100%"></vaadin-radio-button>
</vaadin-radio-group>
<br />
<vaadin-button @click=${this.openStaticDetail}>Open Static Detail</vaadin-button>
<vaadin-button @click=${this.openDetail}>Open Nested Test View</vaadin-button>
<br />
<vaadin-radio-group
@change=${this._configChange}
class="detailSize"
label="Detail Size"
theme="vertical"
value="auto"
>
<vaadin-radio-button value="auto" label="Auto"></vaadin-radio-button>
<vaadin-radio-button value="300px" label="300px"></vaadin-radio-button>
<vaadin-radio-button value="70%" label="70%"></vaadin-radio-button>
</vaadin-radio-group>
<vaadin-radio-group
@change=${this._configChange}
class="detailMinSize"
label="Detail Min Size"
theme="vertical"
value="none"
>
<vaadin-radio-button value="none" label="None"></vaadin-radio-button>
<vaadin-radio-button value="400px" label="400px"></vaadin-radio-button>
<vaadin-radio-button value="100%" label="100%"></vaadin-radio-button>
</vaadin-radio-group>
<p>${lorem}</p>
</div>
</vaadin-master-detail-layout>
`;
}
_configChange(e) {
this._mdl[e.currentTarget.className] = e.target.value.match(/auto|none/) ? null : e.target.value;
}
}
customElements.define(MDLView.is, MDLView);
</script>
</body>
</html>

Steps to reproduce

  1. Click "Open Static Detail"
  2. Observe that master area slides to the right
  3. Close detail
  4. Observer that master area slides in from the right

Environment

Vaadin version(s): v25

Browsers

Safari

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions