From 6ef05705a07bd2ae770d53ae9ba5f325473de9f0 Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Thu, 5 Nov 2026 07:01:28 +0100 Subject: [PATCH] fix(app): fade the dialog card in and land the dim at once --- packages/app/e2e/browser/onboarding.spec.ts | 2 +- packages/app/e2e/support/helpers/onboarding.ts | 2 +- .../app/src/components/adaptive-modal-sheet.tsx | 14 +++++++++----- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/app/e2e/browser/onboarding.spec.ts b/packages/app/e2e/browser/onboarding.spec.ts index 8d3fd15217..a6bfe52615 100644 --- a/packages/app/e2e/browser/onboarding.spec.ts +++ b/packages/app/e2e/browser/onboarding.spec.ts @@ -114,7 +114,7 @@ test("a new user goes from the loading screen straight into setup", async ({ pag const launch = await readFirstLaunch(page); expect(launch.appBeforeSetup).toBe(false); expect(launch.setupOpacityOnArrival).toBeLessThan(1); - await expect(page.getByTestId("onboarding-modal")).toHaveCSS("opacity", "1"); + await expect(setupModal(page)).toHaveCSS("opacity", "1"); } finally { await host.close(); } diff --git a/packages/app/e2e/support/helpers/onboarding.ts b/packages/app/e2e/support/helpers/onboarding.ts index eeda0113d3..4226c1c27e 100644 --- a/packages/app/e2e/support/helpers/onboarding.ts +++ b/packages/app/e2e/support/helpers/onboarding.ts @@ -48,7 +48,7 @@ export async function recordFirstLaunch(page: Page): Promise { const record: FirstLaunchRecord = { appBeforeSetup: false, setupOpacityOnArrival: null }; Object.assign(window, { __firstLaunch: record }); const observer = new MutationObserver(() => { - const setup = document.querySelector('[data-testid="onboarding-modal"]'); + const setup = document.querySelector('[data-testid="onboarding-modal"] [role="dialog"]'); if (setup) { record.setupOpacityOnArrival = Number(getComputedStyle(setup).opacity); observer.disconnect(); diff --git a/packages/app/src/components/adaptive-modal-sheet.tsx b/packages/app/src/components/adaptive-modal-sheet.tsx index 1c5c70f624..ba27d4c9dd 100644 --- a/packages/app/src/components/adaptive-modal-sheet.tsx +++ b/packages/app/src/components/adaptive-modal-sheet.tsx @@ -235,8 +235,9 @@ const WEB_EXIT_DURATION_MS = 160; const WEB_ENTER_DURATION_MS = 160; const WEB_ENTER_ANIMATION_NAME = "paseo-modal-enter"; -// The desktop overlay fades in as it fades out. A CSS animation runs from the overlay's first -// paint, so a dialog that opens on its own, like first-run setup, never pops in. +// The desktop card fades in; the dim lands at once, so the screen behind is never seen undimmed +// while the dialog arrives. A CSS animation runs from the card's first paint, so a dialog that opens +// on its own, like first-run setup, never pops in. Closing fades the whole overlay. function ensureWebEnterKeyframes() { if (!isWeb || typeof document === "undefined") return; if (document.getElementById(WEB_ENTER_ANIMATION_NAME)) return; @@ -246,6 +247,11 @@ function ensureWebEnterKeyframes() { document.head.appendChild(style); } ensureWebEnterKeyframes(); +const WEB_ENTER_STYLE = { + animationName: WEB_ENTER_ANIMATION_NAME, + animationDuration: `${WEB_ENTER_DURATION_MS}ms`, + animationTimingFunction: "ease-out", +}; /** The compact sheet's surface: Gorhom's `backgroundComponent` for every bottom sheet. */ export function SheetBackground({ style }: BottomSheetBackgroundProps) { @@ -676,6 +682,7 @@ export function AdaptiveModalSheet({ styles.desktopCard, desktopHeight != null && { height: desktopHeight }, desktopMaxWidth != null && { maxWidth: desktopMaxWidth }, + isWeb && WEB_ENTER_STYLE, ], [desktopMaxWidth, desktopHeight], ); @@ -685,9 +692,6 @@ export function AdaptiveModalSheet({ isWeb && { zIndex: modalLayer, opacity: isWebClosing ? 0 : 1, - animationName: WEB_ENTER_ANIMATION_NAME, - animationDuration: `${WEB_ENTER_DURATION_MS}ms`, - animationTimingFunction: "ease-out", transitionDuration: `${WEB_EXIT_DURATION_MS}ms`, transitionProperty: "opacity", transitionTimingFunction: "ease",