From 0c1d14dd9c85c4ef8db7f68dcd320ce8cbffd1e6 Mon Sep 17 00:00:00 2001 From: Avinash Dwarapu Date: Mon, 27 Apr 2026 10:17:34 +0200 Subject: [PATCH] fix: Skip local drawer animations on initial render --- .../widget-contract-old.test.tsx.snap | 16 ++++++++ ...get-contract-split-panel-old.test.tsx.snap | 10 +++++ src/app-layout/__tests__/drawers.test.tsx | 39 +++++++++++++++++++ .../drawer/global-ai-drawer.tsx | 6 ++- .../drawer/global-bottom-drawer.tsx | 5 ++- .../drawer/global-drawer.tsx | 2 + .../drawer/local-drawer.tsx | 4 +- .../visual-refresh-toolbar/interfaces.ts | 1 + .../state/use-app-layout.tsx | 13 ++++++- 9 files changed, 91 insertions(+), 5 deletions(-) diff --git a/src/app-layout/__tests__/__snapshots__/widget-contract-old.test.tsx.snap b/src/app-layout/__tests__/__snapshots__/widget-contract-old.test.tsx.snap index 9dac021b6e..4df495afa8 100644 --- a/src/app-layout/__tests__/__snapshots__/widget-contract-old.test.tsx.snap +++ b/src/app-layout/__tests__/__snapshots__/widget-contract-old.test.tsx.snap @@ -42,6 +42,7 @@ Map { }, "breadcrumbs": undefined, "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { @@ -239,6 +240,7 @@ Map { }, "breadcrumbs": undefined, "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { @@ -393,6 +395,7 @@ Map { }, "breadcrumbs": undefined, "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { @@ -577,6 +580,7 @@ Map { }, "breadcrumbs": undefined, "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { @@ -731,6 +735,7 @@ Map { }, "breadcrumbs": undefined, "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { @@ -891,6 +896,7 @@ Map { breadcrumbs , "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { @@ -1097,6 +1103,7 @@ Map { breadcrumbs , "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { @@ -1257,6 +1264,7 @@ Map { breadcrumbs , "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { @@ -1419,6 +1427,7 @@ Map { breadcrumbs , "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { @@ -1611,6 +1620,7 @@ Map { breadcrumbs , "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { @@ -1771,6 +1781,7 @@ Map { breadcrumbs , "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { @@ -1947,6 +1958,7 @@ Map { }, "breadcrumbs": undefined, "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { @@ -2162,6 +2174,7 @@ Map { }, "breadcrumbs": undefined, "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { @@ -2332,6 +2345,7 @@ Map { }, "breadcrumbs": undefined, "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { @@ -2532,6 +2546,7 @@ Map { }, "breadcrumbs": undefined, "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { @@ -2702,6 +2717,7 @@ Map { }, "breadcrumbs": undefined, "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { diff --git a/src/app-layout/__tests__/__snapshots__/widget-contract-split-panel-old.test.tsx.snap b/src/app-layout/__tests__/__snapshots__/widget-contract-split-panel-old.test.tsx.snap index 1f309a2ee6..4883c5fc36 100644 --- a/src/app-layout/__tests__/__snapshots__/widget-contract-split-panel-old.test.tsx.snap +++ b/src/app-layout/__tests__/__snapshots__/widget-contract-split-panel-old.test.tsx.snap @@ -42,6 +42,7 @@ Map { }, "breadcrumbs": undefined, "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { @@ -239,6 +240,7 @@ Map { }, "breadcrumbs": undefined, "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { @@ -393,6 +395,7 @@ Map { }, "breadcrumbs": undefined, "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { @@ -584,6 +587,7 @@ Map { }, "breadcrumbs": undefined, "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { @@ -738,6 +742,7 @@ Map { }, "breadcrumbs": undefined, "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { @@ -896,6 +901,7 @@ Map { }, "breadcrumbs": undefined, "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { @@ -1093,6 +1099,7 @@ Map { }, "breadcrumbs": undefined, "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { @@ -1247,6 +1254,7 @@ Map { }, "breadcrumbs": undefined, "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { @@ -1437,6 +1445,7 @@ Map { }, "breadcrumbs": undefined, "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { @@ -1591,6 +1600,7 @@ Map { }, "breadcrumbs": undefined, "discoveredBreadcrumbs": null, + "drawerAnimationDisabled": true, "drawers": [ { "ariaLabels": { diff --git a/src/app-layout/__tests__/drawers.test.tsx b/src/app-layout/__tests__/drawers.test.tsx index b7a80938ef..56766cb1d7 100644 --- a/src/app-layout/__tests__/drawers.test.tsx +++ b/src/app-layout/__tests__/drawers.test.tsx @@ -10,6 +10,7 @@ import createWrapper from '../../../lib/components/test-utils/dom'; import { testIf } from '../../__tests__/utils'; import { describeEachAppLayout, manyDrawers, renderComponent, testDrawer } from './utils'; +import resizeStyles from '../../../lib/components/app-layout/resize/styles.css.js'; import toolbarTriggerButtonStyles from '../../../lib/components/app-layout/visual-refresh-toolbar/toolbar/trigger-button/styles.css.js'; import visualRefreshStyles from '../../../lib/components/app-layout/visual-refresh/styles.selectors.js'; @@ -295,4 +296,42 @@ describeEachAppLayout(({ size, theme }) => { expect(wrapper!.findDrawerTriggerTooltip()).toBeNull(); expect(() => result.getByTestId(testDrawer.ariaLabels.drawerName)).toThrow(); }); + + testIf(theme === 'refresh-toolbar' && size === 'desktop')( + 'does not apply motion class to drawer open on initial render', + () => { + const { wrapper } = renderComponent( + {}} /> + ); + const drawerElement = wrapper.findActiveDrawer()!.getElement(); + expect(drawerElement.classList.contains(resizeStyles['with-motion-horizontal'])).toBe(false); + } + ); + + testIf(theme === 'refresh-toolbar' && size === 'desktop')( + 'does not apply motion class when toolsOpen is set on initial render', + () => { + const { wrapper } = renderComponent( + {}} /> + ); + const toolsElement = wrapper.findTools()!.getElement(); + expect(toolsElement.classList.contains(resizeStyles['with-motion-horizontal'])).toBe(false); + } + ); + + testIf(theme === 'refresh-toolbar' && size === 'desktop')( + 'applies motion class after user-initiated drawer toggle', + () => { + const onChange = jest.fn(); + const { wrapper, rerender } = renderComponent( + + ); + // Close the drawer via close button (user-initiated) + wrapper.findActiveDrawerCloseButton()!.click(); + // Rerender with drawer open again + rerender(); + const drawerElement = wrapper.findActiveDrawer()!.getElement(); + expect(drawerElement.classList.contains(resizeStyles['with-motion-horizontal'])).toBe(true); + } + ); }); diff --git a/src/app-layout/visual-refresh-toolbar/drawer/global-ai-drawer.tsx b/src/app-layout/visual-refresh-toolbar/drawer/global-ai-drawer.tsx index 27b9221e3d..1bdefc0258 100644 --- a/src/app-layout/visual-refresh-toolbar/drawer/global-ai-drawer.tsx +++ b/src/app-layout/visual-refresh-toolbar/drawer/global-ai-drawer.tsx @@ -68,7 +68,7 @@ export function AppLayoutGlobalAiDrawerImplementation({ expandedDrawerId, setExpandedDrawerId, } = aiDrawerProps; - const { verticalOffsets, placement } = appLayoutInternals; + const { verticalOffsets, placement, drawerAnimationDisabled } = appLayoutInternals; const drawerRef = useRef(null); const activeDrawerId = activeAiDrawer?.id; @@ -92,7 +92,9 @@ export function AppLayoutGlobalAiDrawerImplementation({ const isExpanded = activeAiDrawer?.isExpandable && expandedDrawerId === activeDrawerId; const wasExpanded = usePrevious(isExpanded); const animationDisabled = - (activeAiDrawer?.defaultActive && !drawersOpenQueue?.includes(activeAiDrawer.id)) || (wasExpanded && !isExpanded); + drawerAnimationDisabled || + (activeAiDrawer?.defaultActive && !drawersOpenQueue?.includes(activeAiDrawer.id)) || + (wasExpanded && !isExpanded); const drawerHeight = `calc(100vh - ${verticalOffsets.toolbar + placement.insetBlockEnd}px)`; // disable resizing when the drawer is at its minimum width in a "squeezed" state // (window is between mobile and desktop sizes). At this point, the drawer can't be diff --git a/src/app-layout/visual-refresh-toolbar/drawer/global-bottom-drawer.tsx b/src/app-layout/visual-refresh-toolbar/drawer/global-bottom-drawer.tsx index 318229db1f..5387a436dc 100644 --- a/src/app-layout/visual-refresh-toolbar/drawer/global-bottom-drawer.tsx +++ b/src/app-layout/visual-refresh-toolbar/drawer/global-bottom-drawer.tsx @@ -79,6 +79,7 @@ function AppLayoutGlobalBottomDrawerImplementation({ reportBottomDrawerSize, verticalOffsets, placement, + drawerAnimationDisabled, } = widgetizedState; const drawerRef = useRef(null); const headerRef = useRef(null); @@ -113,7 +114,9 @@ function AppLayoutGlobalBottomDrawerImplementation({ const isExpanded = activeDrawer?.isExpandable && expandedDrawerId === activeDrawerId; const wasExpanded = usePrevious(isExpanded); const animationDisabled = - (activeDrawer?.defaultActive && !drawersOpenQueue.includes(activeDrawer.id)) || (wasExpanded && !isExpanded); + drawerAnimationDisabled || + (activeDrawer?.defaultActive && !drawersOpenQueue.includes(activeDrawer.id)) || + (wasExpanded && !isExpanded); // Prevent main content scroll when bottom drawer opens with animations useEffect(() => { diff --git a/src/app-layout/visual-refresh-toolbar/drawer/global-drawer.tsx b/src/app-layout/visual-refresh-toolbar/drawer/global-drawer.tsx index a14f4861db..c39a6488a6 100644 --- a/src/app-layout/visual-refresh-toolbar/drawer/global-drawer.tsx +++ b/src/app-layout/visual-refresh-toolbar/drawer/global-drawer.tsx @@ -47,6 +47,7 @@ function AppLayoutGlobalDrawerImplementation({ expandedDrawerId, setExpandedDrawerId, activeAiDrawer, + drawerAnimationDisabled, } = appLayoutInternals; const drawerRef = useRef(null); const activeDrawerId = activeGlobalDrawer?.id ?? ''; @@ -75,6 +76,7 @@ function AppLayoutGlobalDrawerImplementation({ const isExpanded = activeGlobalDrawer?.isExpandable && expandedDrawerId === activeDrawerId; const wasExpanded = usePrevious(isExpanded); const animationDisabled = + drawerAnimationDisabled || (activeGlobalDrawer?.defaultActive && !drawersOpenQueue.includes(activeGlobalDrawer.id)) || (wasExpanded && !isExpanded); let drawerActions: ReadonlyArray = [ diff --git a/src/app-layout/visual-refresh-toolbar/drawer/local-drawer.tsx b/src/app-layout/visual-refresh-toolbar/drawer/local-drawer.tsx index 1e988cb9ac..6584468cbf 100644 --- a/src/app-layout/visual-refresh-toolbar/drawer/local-drawer.tsx +++ b/src/app-layout/visual-refresh-toolbar/drawer/local-drawer.tsx @@ -40,6 +40,7 @@ export function AppLayoutDrawerImplementation({ drawersOpenQueue, onActiveDrawerChange, onActiveDrawerResize, + drawerAnimationDisabled, } = appLayoutInternals; const drawerRef = useRef(null); const activeDrawerId = activeDrawer?.id; @@ -70,7 +71,8 @@ export function AppLayoutDrawerImplementation({ const isLegacyDrawer = drawersOpenQueue === undefined; const size = getLimitedValue(minDrawerSize, activeDrawerSize, maxDrawerSize); const lastOpenedDrawerId = drawersOpenQueue?.length ? drawersOpenQueue[0] : activeDrawerId; - const animationDisabled = activeDrawer?.defaultActive && !drawersOpenQueue.includes(activeDrawer.id); + const animationDisabled = + drawerAnimationDisabled || (activeDrawer?.defaultActive && !drawersOpenQueue.includes(activeDrawer.id)); return ( diff --git a/src/app-layout/visual-refresh-toolbar/interfaces.ts b/src/app-layout/visual-refresh-toolbar/interfaces.ts index 8fb7779d47..75b7c7a782 100644 --- a/src/app-layout/visual-refresh-toolbar/interfaces.ts +++ b/src/app-layout/visual-refresh-toolbar/interfaces.ts @@ -74,6 +74,7 @@ export interface AppLayoutInternals { onActiveDrawerChange: (newDrawerId: string | null, params: OnChangeParams) => void; onActiveDrawerResize: (detail: { id: string; size: number }) => void; onActiveGlobalDrawersChange: (newDrawerId: string, params: OnChangeParams) => void; + drawerAnimationDisabled?: boolean; splitPanelAnimationDisabled?: boolean; expandedDrawerId: string | null; setExpandedDrawerId: (value: string | null) => void; diff --git a/src/app-layout/visual-refresh-toolbar/state/use-app-layout.tsx b/src/app-layout/visual-refresh-toolbar/state/use-app-layout.tsx index aafb2b36c1..b9d9d637e2 100644 --- a/src/app-layout/visual-refresh-toolbar/state/use-app-layout.tsx +++ b/src/app-layout/visual-refresh-toolbar/state/use-app-layout.tsx @@ -71,6 +71,7 @@ export const useAppLayout = ( const [notificationsHeight, setNotificationsHeight] = useState(0); const [navigationAnimationDisabled, setNavigationAnimationDisabled] = useState(true); const [splitPanelAnimationDisabled, setSplitPanelAnimationDisabled] = useState(true); + const [drawerAnimationDisabled, setDrawerAnimationDisabled] = useState(true); const [isNested, setIsNested] = useState(false); const [expandedDrawerId, setInternalExpandedDrawerId] = useState(null); const rootRefInternal = useRef(null); @@ -86,6 +87,7 @@ export const useAppLayout = ( changeHandler: 'onToolsChange', }); const onToolsToggle = (open: boolean) => { + setDrawerAnimationDisabled(false); setToolsOpen(open); drawersFocusControl.setFocus(); fireNonCancelableEvent(onToolsChange, { open }); @@ -288,6 +290,9 @@ export const useAppLayout = ( drawerId: string | null, params: OnChangeParams = { initiatedByUserAction: true } ) => { + if (params.initiatedByUserAction) { + setDrawerAnimationDisabled(false); + } onActiveDrawerChange(drawerId, params); drawersFocusControl.setFocus(); if (featureNotificationsProps?.drawer?.id && featureNotificationsProps?.drawer?.id === drawerId) { @@ -455,7 +460,12 @@ export const useAppLayout = ( activeGlobalDrawers, activeGlobalDrawersIds, activeGlobalDrawersSizes, - onActiveGlobalDrawersChange, + onActiveGlobalDrawersChange: (drawerId: string, params: OnChangeParams) => { + if (params.initiatedByUserAction) { + setDrawerAnimationDisabled(false); + } + onActiveGlobalDrawersChange(drawerId, params); + }, drawersFocusControl, globalDrawersFocusControl, splitPanelPosition, @@ -475,6 +485,7 @@ export const useAppLayout = ( onActiveDrawerChange: onActiveDrawerChangeHandler, onActiveDrawerResize, splitPanelAnimationDisabled, + drawerAnimationDisabled, expandedDrawerId, setExpandedDrawerId, aiDrawer,