diff --git a/src/app-layout/__tests__/runtime-drawers.test.tsx b/src/app-layout/__tests__/runtime-drawers.test.tsx index c8d954e51f..7c30238f25 100644 --- a/src/app-layout/__tests__/runtime-drawers.test.tsx +++ b/src/app-layout/__tests__/runtime-drawers.test.tsx @@ -1042,5 +1042,111 @@ describe('toolbar mode only features', () => { expect(wrapper.findActiveDrawer()!.getElement()).toHaveTextContent('runtime drawer content'); }); + + describe('dynamically registered drawers with defaultActive: true', () => { + test('should open if there are already open local drawer on the page', async () => { + const { wrapper, globalDrawersWrapper } = await renderComponent(); + + wrapper.findDrawerTriggerById('security')!.click(); + expect(wrapper.findActiveDrawer()!.getElement()).toHaveTextContent('Security'); + + awsuiPlugins.appLayout.registerDrawer({ + ...drawerDefaults, + id: 'global1', + type: 'global', + defaultActive: true, + }); + + await delay(); + + expect(globalDrawersWrapper.findDrawerById('global1')!.isActive()).toBe(true); + + awsuiPlugins.appLayout.registerDrawer({ + ...drawerDefaults, + id: 'global2', + type: 'global', + defaultActive: true, + }); + + await delay(); + + expect(wrapper.findActiveDrawer()!.getElement()).toHaveTextContent('Security'); + expect(globalDrawersWrapper.findDrawerById('global1')!.isActive()).toBe(true); + expect(globalDrawersWrapper.findDrawerById('global2')!.isActive()).toBe(true); + }); + + test('should not open if there are already global drawers opened by user action on the page', async () => { + const { wrapper, globalDrawersWrapper } = await renderComponent(); + + wrapper.findDrawerTriggerById('security')!.click(); + expect(wrapper.findActiveDrawer()!.getElement()).toHaveTextContent('Security'); + + awsuiPlugins.appLayout.registerDrawer({ + ...drawerDefaults, + id: 'global1', + type: 'global', + }); + + await delay(); + + wrapper.findDrawerTriggerById('global1')!.click(); + expect(globalDrawersWrapper.findDrawerById('global1')!.isActive()).toBe(true); + + awsuiPlugins.appLayout.registerDrawer({ + ...drawerDefaults, + id: 'global2', + type: 'global', + defaultActive: true, + }); + + await delay(); + + expect(wrapper.findActiveDrawer()!.getElement()).toHaveTextContent('Security'); + expect(globalDrawersWrapper.findDrawerById('global1')!.isActive()).toBe(true); + expect(globalDrawersWrapper.findDrawerById('global2')).toBeFalsy(); + }); + + test('should not open if the maximum number (2) of global drawers is already open on the page', async () => { + const { wrapper, globalDrawersWrapper } = await renderComponent(); + + wrapper.findDrawerTriggerById('security')!.click(); + expect(wrapper.findActiveDrawer()!.getElement()).toHaveTextContent('Security'); + + awsuiPlugins.appLayout.registerDrawer({ + ...drawerDefaults, + id: 'global1', + type: 'global', + defaultActive: true, + }); + + await delay(); + + expect(globalDrawersWrapper.findDrawerById('global1')!.isActive()).toBe(true); + + awsuiPlugins.appLayout.registerDrawer({ + ...drawerDefaults, + id: 'global2', + type: 'global', + defaultActive: true, + }); + + await delay(); + + // this drawer should not open because there are already two global drawers open on the page, which is the maximum limit + awsuiPlugins.appLayout.registerDrawer({ + ...drawerDefaults, + id: 'global3', + type: 'global', + defaultActive: true, + }); + + await delay(); + + expect(wrapper.findActiveDrawer()!.getElement()).toHaveTextContent('Security'); + expect(globalDrawersWrapper.findDrawerById('global1')!.isActive()).toBe(true); + expect(globalDrawersWrapper.findDrawerById('global2')!.isActive()).toBe(true); + expect(globalDrawersWrapper.findDrawerById('global3')).toBeFalsy(); + }); + }); }); }); diff --git a/src/app-layout/utils/use-drawers.ts b/src/app-layout/utils/use-drawers.ts index fdce5fd12e..19bd196c00 100644 --- a/src/app-layout/utils/use-drawers.ts +++ b/src/app-layout/utils/use-drawers.ts @@ -63,8 +63,10 @@ function useRuntimeDrawers( const onLocalDrawerChangeStable = useStableCallback(onActiveDrawerChange); const onGlobalDrawersChangeStable = useStableCallback(onActiveGlobalDrawersChange); - const drawersWereOpenRef = useRef(false); - drawersWereOpenRef.current = drawersWereOpenRef.current || !!activeDrawerId || !!activeGlobalDrawersIds.length; + const localDrawerWasOpenRef = useRef(false); + localDrawerWasOpenRef.current = localDrawerWasOpenRef.current || !!activeDrawerId; + const activeGlobalDrawersIdsRef = useRef>([]); + activeGlobalDrawersIdsRef.current = activeGlobalDrawersIds; useEffect(() => { if (disableRuntimeDrawers) { @@ -74,17 +76,27 @@ function useRuntimeDrawers( const localDrawers = drawers.filter(drawer => drawer.type !== 'global'); const globalDrawers = drawers.filter(drawer => drawer.type === 'global'); setRuntimeDrawers(convertRuntimeDrawers(localDrawers, globalDrawers)); - if (!drawersWereOpenRef.current) { + if (!localDrawerWasOpenRef.current) { const defaultActiveLocalDrawer = sortByPriority(localDrawers).find(drawer => drawer.defaultActive); if (defaultActiveLocalDrawer) { onLocalDrawerChangeStable(defaultActiveLocalDrawer.id); } + } - const defaultActiveGlobalDrawers = sortByPriority(globalDrawers).filter(drawer => drawer.defaultActive); - defaultActiveGlobalDrawers.forEach(drawer => { - onGlobalDrawersChangeStable(drawer.id); - }); + const drawersNotActiveByDefault = globalDrawers.filter(drawer => !drawer.defaultActive); + const hasDrawersOpenByUserAction = drawersNotActiveByDefault.find(drawer => + activeGlobalDrawersIdsRef.current.includes(drawer.id) + ); + if (hasDrawersOpenByUserAction || activeGlobalDrawersIdsRef.current.length === DRAWERS_LIMIT) { + return; } + + const defaultActiveGlobalDrawers = sortByPriority(globalDrawers).filter( + drawer => !activeGlobalDrawersIdsRef.current.includes(drawer.id) && drawer.defaultActive + ); + defaultActiveGlobalDrawers.forEach(drawer => { + onGlobalDrawersChangeStable(drawer.id); + }); }); return () => { unsubscribe();