From 6a133c2c6771b243cf00a4883c0568f2dab57bfe Mon Sep 17 00:00:00 2001 From: Andreas Reinhold / reini Date: Wed, 16 Sep 2026 12:23:29 +0200 Subject: [PATCH] Fade the side and bottom sheet scrims out in Firefox too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both scrims are shown and hidden by Alpine's `x-show`, and faded by CSS: closing set `display: none` inline in the same frame as the opacity change, and `transition-behavior: allow-discrete` on `display` held the element for the fade. Firefox does not transition `display`, so no transition started there and the scrim vanished at once — what ContainmentTest's two fade-out tests caught. Alpine now holds `display` itself: `x-transition` with a class string waits for the element's computed transition-duration (the effects token, zero under reduced motion) before hiding it, the same in every engine, and registering `enter` too means reopening during the fade cancels the pending hide. `display` leaves the scrims' CSS transitions, so Chrome and Safari do not hold it a second time after Alpine's hold. The Alpine transition also holds `$nextTick` until the sheet is shown, which menu.js's openSheet() relies on ("Alpine holds $nextTick until then") and which had been lost when the bottom sheet moved off x-transition. Without it `focusItem()` could run while the sheet was still `display: none`, so ActionsTest's sheet-at-compact menu and its filter field did not take the focus in Firefox and Safari; both pass there again. Co-Authored-By: Claude Opus 5 (1M context) --- resources/css/components/bottom-sheet.css | 4 ++-- resources/css/components/drawer.css | 8 +++++--- resources/views/components/bottom-sheet.blade.php | 3 ++- resources/views/components/drawer.blade.php | 6 +++++- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/resources/css/components/bottom-sheet.css b/resources/css/components/bottom-sheet.css index 2b1218a5..ed2be020 100644 --- a/resources/css/components/bottom-sheet.css +++ b/resources/css/components/bottom-sheet.css @@ -36,16 +36,16 @@ @layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility; @layer material.components { + /* The scrim fades out while the view's `x-transition` holds its `display` (see drawer.css). */ [data-md-bottom-sheet-scrim] { position: fixed; inset: 0; z-index: 40; background-color: color-mix(in srgb, var(--md-sys-color-scrim) 32%, transparent); opacity: 0; - transition-property: opacity, display; + transition-property: opacity; transition-duration: var(--md-sys-motion-effects-default-duration); transition-timing-function: var(--md-sys-motion-effects-default); - transition-behavior: allow-discrete; } [data-md-bottom-sheet][data-md-open] > [data-md-bottom-sheet-scrim] { diff --git a/resources/css/components/drawer.css b/resources/css/components/drawer.css index 1afca009..f1f540d4 100644 --- a/resources/css/components/drawer.css +++ b/resources/css/components/drawer.css @@ -41,17 +41,19 @@ @import './divider.css'; @layer material.components { - /* The scrim fades in and, while `display` is held by `allow-discrete`, back out. */ + /* The scrim fades in from `@starting-style` and back out while the view's `x-transition` holds + its `display` for this duration. Not `allow-discrete` on `display`: Firefox does not transition + `display`, so the scrim vanished there, and in the other engines it would hold a second time + after Alpine's hold. */ [data-md-drawer-scrim] { position: fixed; inset: 0; z-index: 40; background-color: color-mix(in srgb, var(--md-sys-color-scrim) 32%, transparent); opacity: 0; - transition-property: opacity, display; + transition-property: opacity; transition-duration: var(--md-sys-motion-effects-default-duration); transition-timing-function: var(--md-sys-motion-effects-default); - transition-behavior: allow-discrete; } [data-md-drawer][data-md-open] > [data-md-drawer-scrim] { diff --git a/resources/views/components/bottom-sheet.blade.php b/resources/views/components/bottom-sheet.blade.php index b67a897a..844744f3 100644 --- a/resources/views/components/bottom-sheet.blade.php +++ b/resources/views/components/bottom-sheet.blade.php @@ -104,7 +104,8 @@ @if ($standard) data-md-standard @endif > @unless ($standard) - + {{-- Alpine's CSS transition holds the scrim for its fade, as in drawer.blade.php. --}} + @endunless @if ($stops !== []) diff --git a/resources/views/components/drawer.blade.php b/resources/views/components/drawer.blade.php index 93bb9fe1..9c86a64a 100644 --- a/resources/views/components/drawer.blade.php +++ b/resources/views/components/drawer.blade.php @@ -93,7 +93,11 @@ data-md-drawer @if ($standard) data-md-standard @endif > - + {{-- The class names only turn on Alpine's CSS transition: it keeps the scrim displayed for the + computed transition-duration (drawer.css's effects token) before hiding it, because Firefox + does not transition `display`, even with `allow-discrete`. Both stages, so reopening during + the fade cancels the pending hide. --}} +