@@ -1439,6 +1667,8 @@ Map {
"setFocus": [Function],
},
"navigationOpen": true,
+ "onActiveAiDrawerChange": [Function],
+ "onActiveAiDrawerResize": [Function],
"onActiveDrawerChange": [Function],
"onActiveDrawerResize": [Function],
"onActiveGlobalDrawersChange": [Function],
@@ -1489,11 +1719,30 @@ Map {
},
"AppLayoutGlobalDrawersImplementation" => {
"appLayoutInternals": {
+ "activeAiDrawer": null,
+ "activeAiDrawerId": null,
+ "activeAiDrawerSize": 0,
"activeDrawer": undefined,
"activeDrawerSize": 290,
"activeGlobalDrawers": [],
"activeGlobalDrawersIds": [],
"activeGlobalDrawersSizes": {},
+ "aiDrawer": null,
+ "aiDrawerFocusControl": {
+ "loseFocus": [Function],
+ "refs": {
+ "close": {
+ "current": null,
+ },
+ "slider": {
+ "current": null,
+ },
+ "toggle": {
+ "current": null,
+ },
+ },
+ "setFocus": [Function],
+ },
"ariaLabels": {
"drawers": undefined,
"drawersOverflow": undefined,
@@ -1552,8 +1801,10 @@ Map {
},
"headerVariant": undefined,
"isMobile": false,
+ "maxAiDrawerSize": Infinity,
"maxDrawerSize": Infinity,
"maxGlobalDrawersSizes": {},
+ "minAiDrawerSize": 290,
"minDrawerSize": 290,
"minGlobalDrawersSizes": {},
"navigation":
@@ -1575,6 +1826,8 @@ Map {
"setFocus": [Function],
},
"navigationOpen": true,
+ "onActiveAiDrawerChange": [Function],
+ "onActiveAiDrawerResize": [Function],
"onActiveDrawerChange": [Function],
"onActiveDrawerResize": [Function],
"onActiveGlobalDrawersChange": [Function],
@@ -1630,6 +1883,9 @@ exports[`Theme=refresh-toolbar, Size=desktop contract with drawers 1`] = `
Map {
"AppLayoutToolbarImplementation" => {
"appLayoutInternals": {
+ "activeAiDrawer": null,
+ "activeAiDrawerId": null,
+ "activeAiDrawerSize": 0,
"activeDrawer": {
"ariaLabels": {
"closeButton": "Security close button",
@@ -1649,6 +1905,22 @@ Map {
"activeGlobalDrawers": [],
"activeGlobalDrawersIds": [],
"activeGlobalDrawersSizes": {},
+ "aiDrawer": null,
+ "aiDrawerFocusControl": {
+ "loseFocus": [Function],
+ "refs": {
+ "close": {
+ "current": null,
+ },
+ "slider": {
+ "current": null,
+ },
+ "toggle": {
+ "current": null,
+ },
+ },
+ "setFocus": [Function],
+ },
"ariaLabels": {
"drawers": undefined,
"drawersOverflow": undefined,
@@ -1705,8 +1977,10 @@ Map {
},
"headerVariant": undefined,
"isMobile": false,
+ "maxAiDrawerSize": Infinity,
"maxDrawerSize": Infinity,
"maxGlobalDrawersSizes": {},
+ "minAiDrawerSize": 290,
"minDrawerSize": 290,
"minGlobalDrawersSizes": {},
"navigation":
,
@@ -1726,6 +2000,8 @@ Map {
"setFocus": [Function],
},
"navigationOpen": true,
+ "onActiveAiDrawerChange": [Function],
+ "onActiveAiDrawerResize": [Function],
"onActiveDrawerChange": [Function],
"onActiveDrawerResize": [Function],
"onActiveGlobalDrawersChange": [Function],
@@ -1818,6 +2094,9 @@ Map {
},
"AppLayoutNavigationImplementation" => {
"appLayoutInternals": {
+ "activeAiDrawer": null,
+ "activeAiDrawerId": null,
+ "activeAiDrawerSize": 0,
"activeDrawer": {
"ariaLabels": {
"closeButton": "Security close button",
@@ -1837,6 +2116,22 @@ Map {
"activeGlobalDrawers": [],
"activeGlobalDrawersIds": [],
"activeGlobalDrawersSizes": {},
+ "aiDrawer": null,
+ "aiDrawerFocusControl": {
+ "loseFocus": [Function],
+ "refs": {
+ "close": {
+ "current": null,
+ },
+ "slider": {
+ "current": null,
+ },
+ "toggle": {
+ "current": null,
+ },
+ },
+ "setFocus": [Function],
+ },
"ariaLabels": {
"drawers": undefined,
"drawersOverflow": undefined,
@@ -1893,8 +2188,10 @@ Map {
},
"headerVariant": undefined,
"isMobile": false,
+ "maxAiDrawerSize": Infinity,
"maxDrawerSize": Infinity,
"maxGlobalDrawersSizes": {},
+ "minAiDrawerSize": 290,
"minDrawerSize": 290,
"minGlobalDrawersSizes": {},
"navigation":
,
@@ -1914,6 +2211,8 @@ Map {
"setFocus": [Function],
},
"navigationOpen": true,
+ "onActiveAiDrawerChange": [Function],
+ "onActiveAiDrawerResize": [Function],
"onActiveDrawerChange": [Function],
"onActiveDrawerResize": [Function],
"onActiveGlobalDrawersChange": [Function],
@@ -1964,6 +2263,9 @@ Map {
},
"AppLayoutSplitPanelDrawerBottomImplementation" => {
"appLayoutInternals": {
+ "activeAiDrawer": null,
+ "activeAiDrawerId": null,
+ "activeAiDrawerSize": 0,
"activeDrawer": {
"ariaLabels": {
"closeButton": "Security close button",
@@ -1983,6 +2285,22 @@ Map {
"activeGlobalDrawers": [],
"activeGlobalDrawersIds": [],
"activeGlobalDrawersSizes": {},
+ "aiDrawer": null,
+ "aiDrawerFocusControl": {
+ "loseFocus": [Function],
+ "refs": {
+ "close": {
+ "current": null,
+ },
+ "slider": {
+ "current": null,
+ },
+ "toggle": {
+ "current": null,
+ },
+ },
+ "setFocus": [Function],
+ },
"ariaLabels": {
"drawers": undefined,
"drawersOverflow": undefined,
@@ -2039,8 +2357,10 @@ Map {
},
"headerVariant": undefined,
"isMobile": false,
+ "maxAiDrawerSize": Infinity,
"maxDrawerSize": Infinity,
"maxGlobalDrawersSizes": {},
+ "minAiDrawerSize": 290,
"minDrawerSize": 290,
"minGlobalDrawersSizes": {},
"navigation":
,
@@ -2060,6 +2380,8 @@ Map {
"setFocus": [Function],
},
"navigationOpen": true,
+ "onActiveAiDrawerChange": [Function],
+ "onActiveAiDrawerResize": [Function],
"onActiveDrawerChange": [Function],
"onActiveDrawerResize": [Function],
"onActiveGlobalDrawersChange": [Function],
@@ -2141,6 +2463,9 @@ Map {
},
"AppLayoutDrawerImplementation" => {
"appLayoutInternals": {
+ "activeAiDrawer": null,
+ "activeAiDrawerId": null,
+ "activeAiDrawerSize": 0,
"activeDrawer": {
"ariaLabels": {
"closeButton": "Security close button",
@@ -2160,6 +2485,22 @@ Map {
"activeGlobalDrawers": [],
"activeGlobalDrawersIds": [],
"activeGlobalDrawersSizes": {},
+ "aiDrawer": null,
+ "aiDrawerFocusControl": {
+ "loseFocus": [Function],
+ "refs": {
+ "close": {
+ "current": null,
+ },
+ "slider": {
+ "current": null,
+ },
+ "toggle": {
+ "current": null,
+ },
+ },
+ "setFocus": [Function],
+ },
"ariaLabels": {
"drawers": undefined,
"drawersOverflow": undefined,
@@ -2216,8 +2557,10 @@ Map {
},
"headerVariant": undefined,
"isMobile": false,
+ "maxAiDrawerSize": Infinity,
"maxDrawerSize": Infinity,
"maxGlobalDrawersSizes": {},
+ "minAiDrawerSize": 290,
"minDrawerSize": 290,
"minGlobalDrawersSizes": {},
"navigation":
,
@@ -2237,6 +2580,8 @@ Map {
"setFocus": [Function],
},
"navigationOpen": true,
+ "onActiveAiDrawerChange": [Function],
+ "onActiveAiDrawerResize": [Function],
"onActiveDrawerChange": [Function],
"onActiveDrawerResize": [Function],
"onActiveGlobalDrawersChange": [Function],
@@ -2287,6 +2632,9 @@ Map {
},
"AppLayoutGlobalDrawersImplementation" => {
"appLayoutInternals": {
+ "activeAiDrawer": null,
+ "activeAiDrawerId": null,
+ "activeAiDrawerSize": 0,
"activeDrawer": {
"ariaLabels": {
"closeButton": "Security close button",
@@ -2306,6 +2654,22 @@ Map {
"activeGlobalDrawers": [],
"activeGlobalDrawersIds": [],
"activeGlobalDrawersSizes": {},
+ "aiDrawer": null,
+ "aiDrawerFocusControl": {
+ "loseFocus": [Function],
+ "refs": {
+ "close": {
+ "current": null,
+ },
+ "slider": {
+ "current": null,
+ },
+ "toggle": {
+ "current": null,
+ },
+ },
+ "setFocus": [Function],
+ },
"ariaLabels": {
"drawers": undefined,
"drawersOverflow": undefined,
@@ -2362,8 +2726,10 @@ Map {
},
"headerVariant": undefined,
"isMobile": false,
+ "maxAiDrawerSize": Infinity,
"maxDrawerSize": Infinity,
"maxGlobalDrawersSizes": {},
+ "minAiDrawerSize": 290,
"minDrawerSize": 290,
"minGlobalDrawersSizes": {},
"navigation":
,
@@ -2383,6 +2749,8 @@ Map {
"setFocus": [Function],
},
"navigationOpen": true,
+ "onActiveAiDrawerChange": [Function],
+ "onActiveAiDrawerResize": [Function],
"onActiveDrawerChange": [Function],
"onActiveDrawerResize": [Function],
"onActiveGlobalDrawersChange": [Function],
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 159bfc2954..5d86e0a1db 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
@@ -4,11 +4,30 @@ exports[`Theme=refresh-toolbar, Size=desktop contract with split panel (trigger
Map {
"AppLayoutToolbarImplementation" => {
"appLayoutInternals": {
+ "activeAiDrawer": null,
+ "activeAiDrawerId": null,
+ "activeAiDrawerSize": 0,
"activeDrawer": undefined,
"activeDrawerSize": 290,
"activeGlobalDrawers": [],
"activeGlobalDrawersIds": [],
"activeGlobalDrawersSizes": {},
+ "aiDrawer": null,
+ "aiDrawerFocusControl": {
+ "loseFocus": [Function],
+ "refs": {
+ "close": {
+ "current": null,
+ },
+ "slider": {
+ "current": null,
+ },
+ "toggle": {
+ "current": null,
+ },
+ },
+ "setFocus": [Function],
+ },
"ariaLabels": {
"drawers": undefined,
"drawersOverflow": undefined,
@@ -63,8 +82,10 @@ Map {
},
"headerVariant": undefined,
"isMobile": false,
+ "maxAiDrawerSize": Infinity,
"maxDrawerSize": Infinity,
"maxGlobalDrawersSizes": {},
+ "minAiDrawerSize": 290,
"minDrawerSize": 290,
"minGlobalDrawersSizes": {},
"navigation":
,
@@ -84,6 +105,8 @@ Map {
"setFocus": [Function],
},
"navigationOpen": true,
+ "onActiveAiDrawerChange": [Function],
+ "onActiveAiDrawerResize": [Function],
"onActiveDrawerChange": [Function],
"onActiveDrawerResize": [Function],
"onActiveGlobalDrawersChange": [Function],
@@ -174,11 +197,30 @@ Map {
},
"AppLayoutNavigationImplementation" => {
"appLayoutInternals": {
+ "activeAiDrawer": null,
+ "activeAiDrawerId": null,
+ "activeAiDrawerSize": 0,
"activeDrawer": undefined,
"activeDrawerSize": 290,
"activeGlobalDrawers": [],
"activeGlobalDrawersIds": [],
"activeGlobalDrawersSizes": {},
+ "aiDrawer": null,
+ "aiDrawerFocusControl": {
+ "loseFocus": [Function],
+ "refs": {
+ "close": {
+ "current": null,
+ },
+ "slider": {
+ "current": null,
+ },
+ "toggle": {
+ "current": null,
+ },
+ },
+ "setFocus": [Function],
+ },
"ariaLabels": {
"drawers": undefined,
"drawersOverflow": undefined,
@@ -233,8 +275,10 @@ Map {
},
"headerVariant": undefined,
"isMobile": false,
+ "maxAiDrawerSize": Infinity,
"maxDrawerSize": Infinity,
"maxGlobalDrawersSizes": {},
+ "minAiDrawerSize": 290,
"minDrawerSize": 290,
"minGlobalDrawersSizes": {},
"navigation":
,
@@ -254,6 +298,8 @@ Map {
"setFocus": [Function],
},
"navigationOpen": true,
+ "onActiveAiDrawerChange": [Function],
+ "onActiveAiDrawerResize": [Function],
"onActiveDrawerChange": [Function],
"onActiveDrawerResize": [Function],
"onActiveGlobalDrawersChange": [Function],
@@ -304,11 +350,30 @@ Map {
},
"AppLayoutSplitPanelDrawerBottomImplementation" => {
"appLayoutInternals": {
+ "activeAiDrawer": null,
+ "activeAiDrawerId": null,
+ "activeAiDrawerSize": 0,
"activeDrawer": undefined,
"activeDrawerSize": 290,
"activeGlobalDrawers": [],
"activeGlobalDrawersIds": [],
"activeGlobalDrawersSizes": {},
+ "aiDrawer": null,
+ "aiDrawerFocusControl": {
+ "loseFocus": [Function],
+ "refs": {
+ "close": {
+ "current": null,
+ },
+ "slider": {
+ "current": null,
+ },
+ "toggle": {
+ "current": null,
+ },
+ },
+ "setFocus": [Function],
+ },
"ariaLabels": {
"drawers": undefined,
"drawersOverflow": undefined,
@@ -363,8 +428,10 @@ Map {
},
"headerVariant": undefined,
"isMobile": false,
+ "maxAiDrawerSize": Infinity,
"maxDrawerSize": Infinity,
"maxGlobalDrawersSizes": {},
+ "minAiDrawerSize": 290,
"minDrawerSize": 290,
"minGlobalDrawersSizes": {},
"navigation":
,
@@ -384,6 +451,8 @@ Map {
"setFocus": [Function],
},
"navigationOpen": true,
+ "onActiveAiDrawerChange": [Function],
+ "onActiveAiDrawerResize": [Function],
"onActiveDrawerChange": [Function],
"onActiveDrawerResize": [Function],
"onActiveGlobalDrawersChange": [Function],
@@ -472,11 +541,30 @@ Map {
},
"AppLayoutDrawerImplementation" => {
"appLayoutInternals": {
+ "activeAiDrawer": null,
+ "activeAiDrawerId": null,
+ "activeAiDrawerSize": 0,
"activeDrawer": undefined,
"activeDrawerSize": 290,
"activeGlobalDrawers": [],
"activeGlobalDrawersIds": [],
"activeGlobalDrawersSizes": {},
+ "aiDrawer": null,
+ "aiDrawerFocusControl": {
+ "loseFocus": [Function],
+ "refs": {
+ "close": {
+ "current": null,
+ },
+ "slider": {
+ "current": null,
+ },
+ "toggle": {
+ "current": null,
+ },
+ },
+ "setFocus": [Function],
+ },
"ariaLabels": {
"drawers": undefined,
"drawersOverflow": undefined,
@@ -531,8 +619,10 @@ Map {
},
"headerVariant": undefined,
"isMobile": false,
+ "maxAiDrawerSize": Infinity,
"maxDrawerSize": Infinity,
"maxGlobalDrawersSizes": {},
+ "minAiDrawerSize": 290,
"minDrawerSize": 290,
"minGlobalDrawersSizes": {},
"navigation":
,
@@ -552,6 +642,8 @@ Map {
"setFocus": [Function],
},
"navigationOpen": true,
+ "onActiveAiDrawerChange": [Function],
+ "onActiveAiDrawerResize": [Function],
"onActiveDrawerChange": [Function],
"onActiveDrawerResize": [Function],
"onActiveGlobalDrawersChange": [Function],
@@ -602,11 +694,30 @@ Map {
},
"AppLayoutGlobalDrawersImplementation" => {
"appLayoutInternals": {
+ "activeAiDrawer": null,
+ "activeAiDrawerId": null,
+ "activeAiDrawerSize": 0,
"activeDrawer": undefined,
"activeDrawerSize": 290,
"activeGlobalDrawers": [],
"activeGlobalDrawersIds": [],
"activeGlobalDrawersSizes": {},
+ "aiDrawer": null,
+ "aiDrawerFocusControl": {
+ "loseFocus": [Function],
+ "refs": {
+ "close": {
+ "current": null,
+ },
+ "slider": {
+ "current": null,
+ },
+ "toggle": {
+ "current": null,
+ },
+ },
+ "setFocus": [Function],
+ },
"ariaLabels": {
"drawers": undefined,
"drawersOverflow": undefined,
@@ -661,8 +772,10 @@ Map {
},
"headerVariant": undefined,
"isMobile": false,
+ "maxAiDrawerSize": Infinity,
"maxDrawerSize": Infinity,
"maxGlobalDrawersSizes": {},
+ "minAiDrawerSize": 290,
"minDrawerSize": 290,
"minGlobalDrawersSizes": {},
"navigation":
,
@@ -682,6 +795,8 @@ Map {
"setFocus": [Function],
},
"navigationOpen": true,
+ "onActiveAiDrawerChange": [Function],
+ "onActiveAiDrawerResize": [Function],
"onActiveDrawerChange": [Function],
"onActiveDrawerResize": [Function],
"onActiveGlobalDrawersChange": [Function],
@@ -737,11 +852,30 @@ exports[`Theme=refresh-toolbar, Size=desktop contract with split panel 1`] = `
Map {
"AppLayoutToolbarImplementation" => {
"appLayoutInternals": {
+ "activeAiDrawer": null,
+ "activeAiDrawerId": null,
+ "activeAiDrawerSize": 0,
"activeDrawer": undefined,
"activeDrawerSize": 290,
"activeGlobalDrawers": [],
"activeGlobalDrawersIds": [],
"activeGlobalDrawersSizes": {},
+ "aiDrawer": null,
+ "aiDrawerFocusControl": {
+ "loseFocus": [Function],
+ "refs": {
+ "close": {
+ "current": null,
+ },
+ "slider": {
+ "current": null,
+ },
+ "toggle": {
+ "current": null,
+ },
+ },
+ "setFocus": [Function],
+ },
"ariaLabels": {
"drawers": undefined,
"drawersOverflow": undefined,
@@ -796,8 +930,10 @@ Map {
},
"headerVariant": undefined,
"isMobile": false,
+ "maxAiDrawerSize": Infinity,
"maxDrawerSize": Infinity,
"maxGlobalDrawersSizes": {},
+ "minAiDrawerSize": 290,
"minDrawerSize": 290,
"minGlobalDrawersSizes": {},
"navigation":
,
@@ -817,6 +953,8 @@ Map {
"setFocus": [Function],
},
"navigationOpen": true,
+ "onActiveAiDrawerChange": [Function],
+ "onActiveAiDrawerResize": [Function],
"onActiveDrawerChange": [Function],
"onActiveDrawerResize": [Function],
"onActiveGlobalDrawersChange": [Function],
@@ -907,11 +1045,30 @@ Map {
},
"AppLayoutNavigationImplementation" => {
"appLayoutInternals": {
+ "activeAiDrawer": null,
+ "activeAiDrawerId": null,
+ "activeAiDrawerSize": 0,
"activeDrawer": undefined,
"activeDrawerSize": 290,
"activeGlobalDrawers": [],
"activeGlobalDrawersIds": [],
"activeGlobalDrawersSizes": {},
+ "aiDrawer": null,
+ "aiDrawerFocusControl": {
+ "loseFocus": [Function],
+ "refs": {
+ "close": {
+ "current": null,
+ },
+ "slider": {
+ "current": null,
+ },
+ "toggle": {
+ "current": null,
+ },
+ },
+ "setFocus": [Function],
+ },
"ariaLabels": {
"drawers": undefined,
"drawersOverflow": undefined,
@@ -966,8 +1123,10 @@ Map {
},
"headerVariant": undefined,
"isMobile": false,
+ "maxAiDrawerSize": Infinity,
"maxDrawerSize": Infinity,
"maxGlobalDrawersSizes": {},
+ "minAiDrawerSize": 290,
"minDrawerSize": 290,
"minGlobalDrawersSizes": {},
"navigation":
,
@@ -987,6 +1146,8 @@ Map {
"setFocus": [Function],
},
"navigationOpen": true,
+ "onActiveAiDrawerChange": [Function],
+ "onActiveAiDrawerResize": [Function],
"onActiveDrawerChange": [Function],
"onActiveDrawerResize": [Function],
"onActiveGlobalDrawersChange": [Function],
@@ -1037,11 +1198,30 @@ Map {
},
"AppLayoutSplitPanelDrawerBottomImplementation" => {
"appLayoutInternals": {
+ "activeAiDrawer": null,
+ "activeAiDrawerId": null,
+ "activeAiDrawerSize": 0,
"activeDrawer": undefined,
"activeDrawerSize": 290,
"activeGlobalDrawers": [],
"activeGlobalDrawersIds": [],
"activeGlobalDrawersSizes": {},
+ "aiDrawer": null,
+ "aiDrawerFocusControl": {
+ "loseFocus": [Function],
+ "refs": {
+ "close": {
+ "current": null,
+ },
+ "slider": {
+ "current": null,
+ },
+ "toggle": {
+ "current": null,
+ },
+ },
+ "setFocus": [Function],
+ },
"ariaLabels": {
"drawers": undefined,
"drawersOverflow": undefined,
@@ -1096,8 +1276,10 @@ Map {
},
"headerVariant": undefined,
"isMobile": false,
+ "maxAiDrawerSize": Infinity,
"maxDrawerSize": Infinity,
"maxGlobalDrawersSizes": {},
+ "minAiDrawerSize": 290,
"minDrawerSize": 290,
"minGlobalDrawersSizes": {},
"navigation":
,
@@ -1117,6 +1299,8 @@ Map {
"setFocus": [Function],
},
"navigationOpen": true,
+ "onActiveAiDrawerChange": [Function],
+ "onActiveAiDrawerResize": [Function],
"onActiveDrawerChange": [Function],
"onActiveDrawerResize": [Function],
"onActiveGlobalDrawersChange": [Function],
@@ -1204,11 +1388,30 @@ Map {
},
"AppLayoutDrawerImplementation" => {
"appLayoutInternals": {
+ "activeAiDrawer": null,
+ "activeAiDrawerId": null,
+ "activeAiDrawerSize": 0,
"activeDrawer": undefined,
"activeDrawerSize": 290,
"activeGlobalDrawers": [],
"activeGlobalDrawersIds": [],
"activeGlobalDrawersSizes": {},
+ "aiDrawer": null,
+ "aiDrawerFocusControl": {
+ "loseFocus": [Function],
+ "refs": {
+ "close": {
+ "current": null,
+ },
+ "slider": {
+ "current": null,
+ },
+ "toggle": {
+ "current": null,
+ },
+ },
+ "setFocus": [Function],
+ },
"ariaLabels": {
"drawers": undefined,
"drawersOverflow": undefined,
@@ -1263,8 +1466,10 @@ Map {
},
"headerVariant": undefined,
"isMobile": false,
+ "maxAiDrawerSize": Infinity,
"maxDrawerSize": Infinity,
"maxGlobalDrawersSizes": {},
+ "minAiDrawerSize": 290,
"minDrawerSize": 290,
"minGlobalDrawersSizes": {},
"navigation":
,
@@ -1284,6 +1489,8 @@ Map {
"setFocus": [Function],
},
"navigationOpen": true,
+ "onActiveAiDrawerChange": [Function],
+ "onActiveAiDrawerResize": [Function],
"onActiveDrawerChange": [Function],
"onActiveDrawerResize": [Function],
"onActiveGlobalDrawersChange": [Function],
@@ -1334,11 +1541,30 @@ Map {
},
"AppLayoutGlobalDrawersImplementation" => {
"appLayoutInternals": {
+ "activeAiDrawer": null,
+ "activeAiDrawerId": null,
+ "activeAiDrawerSize": 0,
"activeDrawer": undefined,
"activeDrawerSize": 290,
"activeGlobalDrawers": [],
"activeGlobalDrawersIds": [],
"activeGlobalDrawersSizes": {},
+ "aiDrawer": null,
+ "aiDrawerFocusControl": {
+ "loseFocus": [Function],
+ "refs": {
+ "close": {
+ "current": null,
+ },
+ "slider": {
+ "current": null,
+ },
+ "toggle": {
+ "current": null,
+ },
+ },
+ "setFocus": [Function],
+ },
"ariaLabels": {
"drawers": undefined,
"drawersOverflow": undefined,
@@ -1393,8 +1619,10 @@ Map {
},
"headerVariant": undefined,
"isMobile": false,
+ "maxAiDrawerSize": Infinity,
"maxDrawerSize": Infinity,
"maxGlobalDrawersSizes": {},
+ "minAiDrawerSize": 290,
"minDrawerSize": 290,
"minGlobalDrawersSizes": {},
"navigation":
,
@@ -1414,6 +1642,8 @@ Map {
"setFocus": [Function],
},
"navigationOpen": true,
+ "onActiveAiDrawerChange": [Function],
+ "onActiveAiDrawerResize": [Function],
"onActiveDrawerChange": [Function],
"onActiveDrawerResize": [Function],
"onActiveGlobalDrawersChange": [Function],
diff --git a/src/app-layout/__tests__/multi-layout-props.test.tsx b/src/app-layout/__tests__/multi-layout-props.test.tsx
index 7a47bd71d9..74b3fc1ba5 100644
--- a/src/app-layout/__tests__/multi-layout-props.test.tsx
+++ b/src/app-layout/__tests__/multi-layout-props.test.tsx
@@ -45,6 +45,7 @@ describe('mergeMultiAppLayoutProps', () => {
splitPanelFocusRef: React.createRef(),
onSplitPanelToggle: mockParentSplitPanelToggle,
setExpandedDrawerId: mockSetExpandedDrawerId,
+ aiDrawerFocusRef: React.createRef(),
};
const additionalPropsBase: Partial
[] = [
diff --git a/src/app-layout/__tests__/runtime-drawers-layout.test.tsx b/src/app-layout/__tests__/runtime-drawers-layout.test.tsx
index 5e4a3a82b8..34ea2b4523 100644
--- a/src/app-layout/__tests__/runtime-drawers-layout.test.tsx
+++ b/src/app-layout/__tests__/runtime-drawers-layout.test.tsx
@@ -48,6 +48,7 @@ jest.mock('../../../lib/components/app-layout/utils/use-app-layout-placement', (
inlineSize: Infinity,
insetBlockStart: 0,
insetBlockEnd: 0,
+ maxAiDrawerSize: 0,
},
]),
};
@@ -89,6 +90,7 @@ describe('toolbar mode only features', () => {
maxGlobalDrawersSizes: {},
totalActiveGlobalDrawersSize: 0,
resizableSpaceAvailable: 792,
+ maxAiDrawerSize: 0,
});
awsuiPlugins.appLayout.registerDrawer({
...drawerDefaults,
@@ -141,6 +143,7 @@ describe('toolbar mode only features', () => {
maxGlobalDrawersSizes: {},
totalActiveGlobalDrawersSize: 0,
resizableSpaceAvailable: 792,
+ maxAiDrawerSize: 0,
});
const onToggle = jest.fn();
awsuiPlugins.appLayout.registerDrawer({
@@ -198,6 +201,7 @@ describe('toolbar mode only features', () => {
},
totalActiveGlobalDrawersSize: 0,
resizableSpaceAvailable: 792,
+ maxAiDrawerSize: 0,
});
const onDrawerItemResize = jest.fn();
awsuiPlugins.appLayout.registerDrawer({
diff --git a/src/app-layout/__tests__/runtime-drawers-widgetized.test.tsx b/src/app-layout/__tests__/runtime-drawers-widgetized.test.tsx
new file mode 100644
index 0000000000..1bcd908e42
--- /dev/null
+++ b/src/app-layout/__tests__/runtime-drawers-widgetized.test.tsx
@@ -0,0 +1,197 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+import React from 'react';
+import { act, render } from '@testing-library/react';
+
+import AppLayout from '../../../lib/components/app-layout';
+import { metrics } from '../../../lib/components/internal/metrics';
+import { DrawerPayload } from '../../../lib/components/internal/plugins/widget/interfaces';
+import * as awsuiWidgetPlugins from '../../../lib/components/internal/plugins/widget/internal';
+import createWrapper from '../../../lib/components/test-utils/dom';
+import { describeEachAppLayout, getGlobalDrawersTestUtils } from './utils';
+
+const drawerDefaults: DrawerPayload = {
+ id: 'test',
+ ariaLabels: {},
+ trigger: { customIcon: 'custom icon' },
+ mountContent: container => (container.textContent = 'widgetized drawer content'),
+ unmountContent: () => {},
+};
+
+beforeEach(() => {
+ awsuiWidgetPlugins.clearInitialMessages();
+ jest.resetAllMocks();
+});
+
+function renderComponent(jsx: React.ReactElement) {
+ const { container, rerender, ...rest } = render(jsx);
+ const wrapper = createWrapper(container).findAppLayout()!;
+ const globalDrawersWrapper = getGlobalDrawersTestUtils(wrapper);
+ return {
+ wrapper,
+ globalDrawersWrapper,
+ rerender,
+ ...rest,
+ };
+}
+
+describeEachAppLayout({ themes: ['refresh-toolbar'] }, ({ size }) => {
+ test('renders ai drawer when registered', () => {
+ awsuiWidgetPlugins.registerLeftDrawer(drawerDefaults);
+ const { globalDrawersWrapper } = renderComponent();
+
+ expect(globalDrawersWrapper.findDrawerById(drawerDefaults.id)).toBeFalsy();
+ expect(globalDrawersWrapper.findAiDrawerTrigger()).toBeTruthy();
+
+ globalDrawersWrapper.findAiDrawerTrigger()!.click();
+
+ expect(globalDrawersWrapper.findDrawerById(drawerDefaults.id)!.isActive()).toBe(true);
+ });
+
+ test('isAppLayoutReady returns true when app layout is ready', () => {
+ expect(awsuiWidgetPlugins.isAppLayoutReady()).toBe(false);
+ const { rerender } = renderComponent();
+
+ expect(awsuiWidgetPlugins.isAppLayoutReady()).toBe(true);
+
+ rerender(<>>);
+
+ expect(awsuiWidgetPlugins.isAppLayoutReady()).toBe(false);
+ });
+
+ test('adds ai drawer to an already rendered component', () => {
+ const { globalDrawersWrapper } = renderComponent();
+ expect(globalDrawersWrapper.findAiDrawerTrigger()).toBeFalsy();
+
+ act(() => awsuiWidgetPlugins.registerLeftDrawer(drawerDefaults));
+ expect(globalDrawersWrapper.findAiDrawerTrigger()).toBeTruthy();
+ });
+
+ test('should render custom header in global-ai drawer', () => {
+ awsuiWidgetPlugins.registerLeftDrawer({
+ ...drawerDefaults,
+ mountHeader: container => {
+ container.innerHTML = 'custom header';
+ },
+ unmountHeader: () => {},
+ });
+ const { globalDrawersWrapper } = renderComponent();
+
+ globalDrawersWrapper.findAiDrawerTrigger()!.click();
+ expect(globalDrawersWrapper.findDrawerById(drawerDefaults.id)!.getElement()).toHaveTextContent('custom header');
+ });
+
+ test('can update drawer config dynamically', () => {
+ awsuiWidgetPlugins.registerLeftDrawer(drawerDefaults);
+ const { globalDrawersWrapper } = renderComponent();
+
+ expect(globalDrawersWrapper.findAiDrawerTrigger()!.getElement()).not.toHaveAttribute('aria-label');
+ act(() =>
+ awsuiWidgetPlugins.updateDrawer({
+ type: 'updateDrawerConfig',
+ payload: { id: drawerDefaults.id, ariaLabels: { triggerButton: 'trigger button label' } },
+ })
+ );
+
+ expect(globalDrawersWrapper.findAiDrawerTrigger()!.getElement()).toHaveAttribute(
+ 'aria-label',
+ 'trigger button label'
+ );
+ });
+
+ test('should open global ai drawer by default when defaultActive is set', () => {
+ awsuiWidgetPlugins.registerLeftDrawer({
+ ...drawerDefaults,
+ defaultActive: true,
+ });
+
+ const { globalDrawersWrapper } = renderComponent();
+
+ expect(globalDrawersWrapper.findDrawerById(drawerDefaults.id)!.isActive()).toBe(true);
+ });
+
+ test('should open global ai drawer by default if it is dynamically registered', () => {
+ const { globalDrawersWrapper } = renderComponent();
+
+ awsuiWidgetPlugins.registerLeftDrawer({
+ ...drawerDefaults,
+ defaultActive: true,
+ });
+
+ expect(globalDrawersWrapper.findDrawerById(drawerDefaults.id)!.isActive()).toBe(true);
+ });
+
+ test('should open global ai drawer via API', () => {
+ awsuiWidgetPlugins.registerLeftDrawer(drawerDefaults);
+
+ const { globalDrawersWrapper } = renderComponent();
+ expect(globalDrawersWrapper.findDrawerById(drawerDefaults.id)).toBeFalsy();
+
+ act(() => awsuiWidgetPlugins.updateDrawer({ type: 'openDrawer', payload: { id: drawerDefaults.id } }));
+
+ expect(globalDrawersWrapper.findDrawerById(drawerDefaults.id)!.isActive()).toBe(true);
+ });
+
+ test('onResize functionality', () => {
+ const onResize = jest.fn();
+ awsuiWidgetPlugins.registerLeftDrawer({
+ ...drawerDefaults,
+ resizable: true,
+ onResize: event => onResize(event.detail),
+ });
+ const { wrapper, globalDrawersWrapper } = renderComponent();
+ globalDrawersWrapper.findAiDrawerTrigger()!.click();
+
+ if (size === 'mobile') {
+ expect(wrapper.findActiveDrawerResizeHandle()).toBeFalsy();
+ } else {
+ const handle = wrapper.findActiveDrawerResizeHandle()!;
+ handle.fireEvent(new MouseEvent('pointerdown', { bubbles: true }));
+ handle.fireEvent(new MouseEvent('pointermove', { bubbles: true }));
+ handle.fireEvent(new MouseEvent('pointerup', { bubbles: true }));
+
+ expect(onResize).toHaveBeenCalledWith({ size: expect.any(Number), id: drawerDefaults.id });
+ }
+ });
+
+ test('should exit focus mode by clicking on a custom exit button in the AI global drawer', () => {
+ awsuiWidgetPlugins.registerLeftDrawer({
+ ...drawerDefaults,
+ ariaLabels: {
+ exitExpandedModeButton: 'exitExpandedModeButton',
+ },
+ isExpandable: true,
+ });
+ const { globalDrawersWrapper } = renderComponent();
+
+ globalDrawersWrapper.findAiDrawerTrigger()!.click();
+ if (size === 'mobile') {
+ expect(globalDrawersWrapper.findExpandedModeButtonByActiveDrawerId(drawerDefaults.id)).toBeFalsy();
+ } else {
+ globalDrawersWrapper.findExpandedModeButtonByActiveDrawerId(drawerDefaults.id)!.click();
+ expect(globalDrawersWrapper.findDrawerById(drawerDefaults.id)!.isDrawerInExpandedMode()).toBe(true);
+ expect(globalDrawersWrapper.isLayoutInDrawerExpandedMode()).toBe(true);
+ globalDrawersWrapper.findLeaveExpandedModeButtonInAIDrawer()!.click();
+ expect(globalDrawersWrapper.isLayoutInDrawerExpandedMode()).toBe(false);
+ }
+ });
+
+ describe('metrics', () => {
+ let sendPanoramaMetricSpy: jest.SpyInstance;
+ beforeEach(() => {
+ sendPanoramaMetricSpy = jest.spyOn(metrics, 'sendOpsMetricObject').mockImplementation(() => {});
+ });
+
+ test('should report ops metric when unknown id is provided', () => {
+ awsuiWidgetPlugins.registerLeftDrawer(drawerDefaults);
+ renderComponent();
+
+ act(() => awsuiWidgetPlugins.updateDrawer({ type: 'openDrawer', payload: { id: 'unknown' } }));
+
+ expect(sendPanoramaMetricSpy).toHaveBeenCalledWith('awsui-widget-drawer-incorrect-id', {
+ oldId: 'test',
+ newId: 'unknown',
+ });
+ });
+ });
+});
diff --git a/src/app-layout/__tests__/runtime-drawers.test.tsx b/src/app-layout/__tests__/runtime-drawers.test.tsx
index f3cd4cbbce..55112c3250 100644
--- a/src/app-layout/__tests__/runtime-drawers.test.tsx
+++ b/src/app-layout/__tests__/runtime-drawers.test.tsx
@@ -11,6 +11,8 @@ import AppLayout, { AppLayoutProps } from '../../../lib/components/app-layout';
import { TOOLS_DRAWER_ID } from '../../../lib/components/app-layout/utils/use-drawers';
import { awsuiPlugins, awsuiPluginsInternal } from '../../../lib/components/internal/plugins/api';
import { DrawerConfig } from '../../../lib/components/internal/plugins/controllers/drawers';
+import { DrawerPayload as WidgetDrawerPayload } from '../../../lib/components/internal/plugins/widget/interfaces';
+import * as awsuiWidgetPlugins from '../../../lib/components/internal/plugins/widget/internal';
import SplitPanel from '../../../lib/components/split-panel';
import createWrapper from '../../../lib/components/test-utils/dom';
import {
@@ -29,6 +31,7 @@ import toolbarTriggerStyles from '../../../lib/components/app-layout/visual-refr
beforeEach(() => {
awsuiPluginsInternal.appLayout.clearRegisteredDrawers();
+ awsuiWidgetPlugins.clearInitialMessages();
activateAnalyticsMetadata(true);
});
@@ -58,7 +61,7 @@ function delay() {
const drawerDefaults: DrawerConfig = {
id: 'test',
ariaLabels: {},
- trigger: { iconSvg: '' },
+ trigger: { iconSvg: 'icon placeholder' },
mountContent: container => (container.textContent = 'runtime drawer content'),
unmountContent: () => {},
};
@@ -928,222 +931,303 @@ describe('toolbar mode only features', () => {
expect(globalDrawersWrapper.findActiveDrawers()[1].getElement()).toHaveTextContent('global drawer content 3');
});
- test('renders resize handle for a global drawer when config is enabled', async () => {
- awsuiPlugins.appLayout.registerDrawer({
- ...drawerDefaults,
- id: 'test-resizable',
- resizable: true,
- type: 'global',
- ariaLabels: {
- triggerButton: 'drawer trigger',
- content: 'drawer content',
- resizeHandle: 'drawer resize',
- closeButton: 'drawer close',
- },
- });
- const { globalDrawersWrapper, wrapper } = await renderComponent();
+ describe.each(['global', 'global-ai'] as const)('drawer type = %s', type => {
+ const findDrawerTriggerById = (id: string, renderProps: Awaited>) => {
+ if (type === 'global') {
+ return renderProps.wrapper.findDrawerTriggerById(id);
+ } else {
+ return renderProps.globalDrawersWrapper.findAiDrawerTrigger();
+ }
+ };
+ const registerDrawer = (payload: DrawerConfig | WidgetDrawerPayload) => {
+ if (type === 'global') {
+ awsuiPlugins.appLayout.registerDrawer({ ...payload, type } as DrawerConfig);
+ } else {
+ awsuiWidgetPlugins.registerLeftDrawer(payload as WidgetDrawerPayload);
+ }
+ };
- wrapper.findDrawerTriggerById('test-resizable')!.click();
+ test('renders resize handle for a global drawer when config is enabled', async () => {
+ registerDrawer({
+ ...drawerDefaults,
+ id: 'test-resizable',
+ resizable: true,
+ ariaLabels: {
+ triggerButton: 'drawer trigger',
+ content: 'drawer content',
+ resizeHandle: 'drawer resize',
+ closeButton: 'drawer close',
+ },
+ });
+ const renderProps = await renderComponent();
+ const { globalDrawersWrapper } = renderProps;
- await waitFor(() => {
- expect(globalDrawersWrapper.findResizeHandleByActiveDrawerId('test-resizable')!.getElement()).toHaveFocus();
- expect(globalDrawersWrapper.findResizeHandleByActiveDrawerId('test-resizable')!.getElement()).toHaveAttribute(
- 'aria-label',
- 'drawer resize'
- );
- });
- });
+ findDrawerTriggerById('test-resizable', renderProps)!.click();
- test('close active global drawer by clicking on close button', async () => {
- awsuiPlugins.appLayout.registerDrawer({
- ...drawerDefaults,
- id: 'global-drawer',
- type: 'global',
- ariaLabels: {
- triggerButton: 'drawer trigger',
- content: 'drawer content',
- resizeHandle: 'drawer resize',
- closeButton: 'drawer close',
- },
+ await waitFor(() => {
+ expect(globalDrawersWrapper.findResizeHandleByActiveDrawerId('test-resizable')!.getElement()).toHaveFocus();
+ expect(globalDrawersWrapper.findResizeHandleByActiveDrawerId('test-resizable')!.getElement()).toHaveAttribute(
+ 'aria-label',
+ 'drawer resize'
+ );
+ });
});
- const { wrapper, globalDrawersWrapper } = await renderComponent();
- wrapper.findDrawerTriggerById('global-drawer')!.click();
- expect(globalDrawersWrapper.findDrawerById('global-drawer')!.getElement()).toBeInTheDocument();
- globalDrawersWrapper.findCloseButtonByActiveDrawerId('global-drawer')!.click();
- expect(globalDrawersWrapper.findDrawerById('global-drawer')).toBeNull();
- });
+ test('close active global drawer by clicking on close button', async () => {
+ registerDrawer({
+ ...drawerDefaults,
+ id: 'global-drawer',
+ ariaLabels: {
+ triggerButton: 'drawer trigger',
+ content: 'drawer content',
+ resizeHandle: 'drawer resize',
+ closeButton: 'drawer close',
+ },
+ });
- test('the order of the opened global drawers should match the positions of their corresponding toggle buttons on the toolbar', async () => {
- awsuiPlugins.appLayout.registerDrawer({
- ...drawerDefaults,
- id: 'global-drawer-1',
- type: 'global',
- mountContent: container => (container.textContent = 'global drawer content 1'),
- });
- awsuiPlugins.appLayout.registerDrawer({
- ...drawerDefaults,
- id: 'global-drawer-2',
- type: 'global',
- mountContent: container => (container.textContent = 'global drawer content 2'),
+ const renderProps = await renderComponent();
+ const { globalDrawersWrapper } = renderProps;
+
+ findDrawerTriggerById('global-drawer', renderProps)!.click();
+ expect(globalDrawersWrapper.findDrawerById('global-drawer')!.getElement()).toBeInTheDocument();
+ globalDrawersWrapper.findCloseButtonByActiveDrawerId('global-drawer')!.click();
+ expect(globalDrawersWrapper.findDrawerById('global-drawer')).toBeNull();
});
- const { wrapper, globalDrawersWrapper } = await renderComponent();
+ test('opens a drawer when openDrawer is called', async () => {
+ awsuiPlugins.appLayout.registerDrawer({
+ ...drawerDefaults,
+ id: 'local-drawer',
+ mountContent: container => (container.textContent = 'local-drawer content'),
+ });
+ awsuiPlugins.appLayout.registerDrawer({
+ ...drawerDefaults,
+ id: 'global-drawer-1',
+ type: 'global',
+ mountContent: container => (container.textContent = 'global drawer content 1'),
+ });
+ registerDrawer({
+ ...drawerDefaults,
+ id: 'global-drawer-2',
+ mountContent: container => (container.textContent = 'global drawer content 2'),
+ });
- wrapper.findDrawerTriggerById('global-drawer-2')!.click();
- wrapper.findDrawerTriggerById('global-drawer-1')!.click();
+ const { globalDrawersWrapper } = await renderComponent();
- expect(globalDrawersWrapper.findActiveDrawers()[0].getElement()).toHaveTextContent('global drawer content 1');
- expect(globalDrawersWrapper.findActiveDrawers()[1].getElement()).toHaveTextContent('global drawer content 2');
- });
+ expect(globalDrawersWrapper.findActiveDrawers()).toHaveLength(0);
- test('should close opened global drawer by clicking on its trigger button', async () => {
- awsuiPlugins.appLayout.registerDrawer({
- ...drawerDefaults,
- id: 'global-drawer-1',
- type: 'global',
- mountContent: container => (container.textContent = 'global drawer content 1'),
+ awsuiPlugins.appLayout.openDrawer('local-drawer');
+
+ await delay();
+
+ expect(globalDrawersWrapper.findActiveDrawers()).toHaveLength(1);
+
+ awsuiPlugins.appLayout.openDrawer('global-drawer-1');
+
+ await delay();
+
+ expect(globalDrawersWrapper.findActiveDrawers()).toHaveLength(2);
});
- const { wrapper, globalDrawersWrapper } = await renderComponent();
+ test('does not do anything when openDrawer is called with active drawer id', async () => {
+ registerDrawer({
+ ...drawerDefaults,
+ id: 'local-drawer',
+ mountContent: container => (container.textContent = 'local-drawer content'),
+ });
- wrapper.findDrawerTriggerById('global-drawer-1')!.click();
+ const { globalDrawersWrapper } = await renderComponent();
- expect(globalDrawersWrapper.findDrawerById('global-drawer-1')!.getElement()).toBeInTheDocument();
+ expect(globalDrawersWrapper.findActiveDrawers()).toHaveLength(0);
- wrapper.findDrawerTriggerById('global-drawer-1')!.click();
+ if (type === 'global') {
+ awsuiPlugins.appLayout.openDrawer('local-drawer');
+ } else {
+ awsuiWidgetPlugins.updateDrawer({ type: 'openDrawer', payload: { id: 'local-drawer' } });
+ }
- expect(globalDrawersWrapper.findDrawerById('global-drawer-1')).toBeNull();
- });
+ await delay();
- test('opens a drawer when openDrawer is called', async () => {
- awsuiPlugins.appLayout.registerDrawer({
- ...drawerDefaults,
- id: 'local-drawer',
- mountContent: container => (container.textContent = 'local-drawer content'),
- });
- awsuiPlugins.appLayout.registerDrawer({
- ...drawerDefaults,
- id: 'global-drawer-1',
- type: 'global',
- mountContent: container => (container.textContent = 'global drawer content 1'),
+ expect(globalDrawersWrapper.findActiveDrawers()).toHaveLength(1);
+
+ if (type === 'global') {
+ awsuiPlugins.appLayout.openDrawer('local-drawer');
+ } else {
+ awsuiWidgetPlugins.updateDrawer({ type: 'openDrawer', payload: { id: 'local-drawer' } });
+ }
+
+ await delay();
+
+ expect(globalDrawersWrapper.findActiveDrawers()).toHaveLength(1);
});
- awsuiPlugins.appLayout.registerDrawer({
- ...drawerDefaults,
- id: 'global-drawer-2',
- type: 'global',
- mountContent: container => (container.textContent = 'global drawer content 2'),
+
+ test('should restore focus when a global drawer is closed', async () => {
+ registerDrawer({
+ ...drawerDefaults,
+ id: 'global-drawer-1',
+ mountContent: container => (container.textContent = 'global drawer content 1'),
+ });
+
+ const renderProps = await renderComponent();
+ const { globalDrawersWrapper } = renderProps;
+
+ findDrawerTriggerById('global-drawer-1', renderProps)!.focus();
+ findDrawerTriggerById('global-drawer-1', renderProps)!.click();
+ expect(globalDrawersWrapper.findDrawerById('global-drawer-1')!.getElement()).toBeInTheDocument();
+ globalDrawersWrapper.findCloseButtonByActiveDrawerId('global-drawer-1')!.click();
+ expect(globalDrawersWrapper.findDrawerById('global-drawer-1')).toBeNull();
+ await waitFor(() => {
+ expect(findDrawerTriggerById('global-drawer-1', renderProps)!.getElement()).toHaveFocus();
+ });
});
- const { globalDrawersWrapper } = await renderComponent();
+ test('when preserveInactiveContent is set to true, initially closed drawer does not exist in dom (but mounted and persists when opened and closed)', async () => {
+ registerDrawer({
+ ...drawerDefaults,
+ id: 'global-drawer-1',
+ mountContent: container => (container.textContent = 'global drawer content 1'),
+ preserveInactiveContent: true,
+ });
- expect(globalDrawersWrapper.findActiveDrawers()).toHaveLength(0);
+ const renderProps = await renderComponent();
+ const { globalDrawersWrapper } = renderProps;
- awsuiPlugins.appLayout.openDrawer('local-drawer');
+ expect(globalDrawersWrapper.findDrawerById('global-drawer-1')).toBeNull();
- await delay();
+ findDrawerTriggerById('global-drawer-1', renderProps)!.click();
- expect(globalDrawersWrapper.findActiveDrawers()).toHaveLength(1);
+ await delay();
- awsuiPlugins.appLayout.openDrawer('global-drawer-1');
+ expect(globalDrawersWrapper.findDrawerById('global-drawer-1')!.isActive()).toBe(true);
+ globalDrawersWrapper.findCloseButtonByActiveDrawerId('global-drawer-1')!.click();
- await delay();
+ expect(globalDrawersWrapper.findDrawerById('global-drawer-1')!.getElement()).toBeInTheDocument();
+ expect(globalDrawersWrapper.findDrawerById('global-drawer-1')!.isActive()).toBe(false);
+ });
- expect(globalDrawersWrapper.findActiveDrawers()).toHaveLength(2);
- });
+ test('should call visibilityChange callback when global drawer with preserveInactiveContent is opened and closed', async () => {
+ const onVisibilityChangeMock = jest.fn();
+ registerDrawer({
+ ...drawerDefaults,
+ id: 'global-drawer-1',
+ mountContent: (container, mountContext) => {
+ if (mountContext?.onVisibilityChange) {
+ mountContext.onVisibilityChange(onVisibilityChangeMock);
+ }
+ container.textContent = 'global drawer content 1';
+ },
+ preserveInactiveContent: true,
+ });
- test('does not do anything when openDrawer is called with active drawer id', async () => {
- awsuiPlugins.appLayout.registerDrawer({
- ...drawerDefaults,
- id: 'local-drawer',
- mountContent: container => (container.textContent = 'local-drawer content'),
+ const renderProps = await renderComponent();
+ const { globalDrawersWrapper } = renderProps;
+
+ findDrawerTriggerById('global-drawer-1', renderProps)!.click();
+
+ await delay();
+
+ expect(globalDrawersWrapper.findDrawerById('global-drawer-1')!.isActive()).toBe(true);
+ expect(onVisibilityChangeMock).toHaveBeenCalledWith(true);
+
+ globalDrawersWrapper.findCloseButtonByActiveDrawerId('global-drawer-1')!.click();
+ expect(onVisibilityChangeMock).toHaveBeenCalledWith(false);
});
- const { globalDrawersWrapper } = await renderComponent();
+ test(`closes a drawer when closeDrawer is called (${type} drawer)`, async () => {
+ registerDrawer({ ...drawerDefaults, resizable: true });
- expect(globalDrawersWrapper.findActiveDrawers()).toHaveLength(0);
+ const { wrapper } = await renderComponent();
- awsuiPlugins.appLayout.openDrawer('local-drawer');
+ if (type === 'global') {
+ awsuiPlugins.appLayout.openDrawer('test');
+ } else {
+ awsuiWidgetPlugins.updateDrawer({ type: 'openDrawer', payload: { id: 'test' } });
+ }
- await delay();
+ await delay();
- expect(globalDrawersWrapper.findActiveDrawers()).toHaveLength(1);
+ expect(wrapper.findActiveDrawer()!.getElement()).toHaveTextContent('runtime drawer content');
- awsuiPlugins.appLayout.openDrawer('local-drawer');
+ if (type === 'global') {
+ awsuiPlugins.appLayout.closeDrawer('test');
+ } else {
+ awsuiWidgetPlugins.updateDrawer({ type: 'closeDrawer', payload: { id: 'test' } });
+ }
- await delay();
+ await delay();
- expect(globalDrawersWrapper.findActiveDrawers()).toHaveLength(1);
- });
+ expect(wrapper.findActiveDrawer()).toBeFalsy();
+ });
- test('should restore focus when a global drawer is closed', async () => {
- awsuiPlugins.appLayout.registerDrawer({
- ...drawerDefaults,
- id: 'global-drawer-1',
- type: 'global',
- mountContent: container => (container.textContent = 'global drawer content 1'),
+ test('should render trigger buttons for global drawers even if local drawers are not present', async () => {
+ const renderProps = await renderComponent();
+
+ registerDrawer({
+ ...drawerDefaults,
+ id: 'global1',
+ });
+
+ await delay();
+
+ expect(findDrawerTriggerById('global1', renderProps)!.getElement()).toBeInTheDocument();
});
- const { wrapper, globalDrawersWrapper } = await renderComponent();
+ test(`calls onToggle handler by clicking on drawers trigger button (${type} runtime drawers)`, async () => {
+ const onToggle = jest.fn();
+ registerDrawer({
+ ...drawerDefaults,
+ id: 'global-drawer',
+ onToggle: event => onToggle(event.detail),
+ });
+ const renderProps = await renderComponent();
- wrapper.findDrawerTriggerById('global-drawer-1')!.focus();
- wrapper.findDrawerTriggerById('global-drawer-1')!.click();
- expect(globalDrawersWrapper.findDrawerById('global-drawer-1')!.getElement()).toBeInTheDocument();
- globalDrawersWrapper.findCloseButtonByActiveDrawerId('global-drawer-1')!.click();
- expect(globalDrawersWrapper.findDrawerById('global-drawer-1')).toBeNull();
- expect(wrapper.findDrawerTriggerById('global-drawer-1')!.getElement()).toHaveFocus();
+ findDrawerTriggerById('global-drawer', renderProps)!.click();
+ expect(onToggle).toHaveBeenCalledWith({ isOpen: true, initiatedByUserAction: true });
+ renderProps.globalDrawersWrapper.findCloseButtonByActiveDrawerId('global-drawer')!.click();
+ expect(onToggle).toHaveBeenCalledWith({ isOpen: false, initiatedByUserAction: true });
+ });
});
- test('when keepContentMounted is set to true, initially closed drawer does not exist in dom (but mounted and persists when opened and closed)', async () => {
+ test('the order of the opened global drawers should match the positions of their corresponding toggle buttons on the toolbar', async () => {
awsuiPlugins.appLayout.registerDrawer({
...drawerDefaults,
id: 'global-drawer-1',
type: 'global',
mountContent: container => (container.textContent = 'global drawer content 1'),
- preserveInactiveContent: true,
+ });
+ awsuiPlugins.appLayout.registerDrawer({
+ ...drawerDefaults,
+ id: 'global-drawer-2',
+ type: 'global',
+ mountContent: container => (container.textContent = 'global drawer content 2'),
});
const { wrapper, globalDrawersWrapper } = await renderComponent();
- expect(globalDrawersWrapper.findDrawerById('global-drawer-1')).toBeNull();
-
- wrapper.findDrawerTriggerById('global-drawer-1')!.click();
-
- await delay();
-
- expect(globalDrawersWrapper.findDrawerById('global-drawer-1')!.isActive()).toBe(true);
+ wrapper.findDrawerTriggerById('global-drawer-2')!.click();
wrapper.findDrawerTriggerById('global-drawer-1')!.click();
- expect(globalDrawersWrapper.findDrawerById('global-drawer-1')!.getElement()).toBeInTheDocument();
- expect(globalDrawersWrapper.findDrawerById('global-drawer-1')!.isActive()).toBe(false);
+ expect(globalDrawersWrapper.findActiveDrawers()[0].getElement()).toHaveTextContent('global drawer content 1');
+ expect(globalDrawersWrapper.findActiveDrawers()[1].getElement()).toHaveTextContent('global drawer content 2');
});
- test('should call visibilityChange callback when global drawer with preserveInactiveContent is opened and closed', async () => {
- const onVisibilityChangeMock = jest.fn();
+ test('should close opened global drawer by clicking on its trigger button', async () => {
awsuiPlugins.appLayout.registerDrawer({
...drawerDefaults,
id: 'global-drawer-1',
type: 'global',
- mountContent: (container, mountContext) => {
- if (mountContext?.onVisibilityChange) {
- mountContext.onVisibilityChange(onVisibilityChangeMock);
- }
- container.textContent = 'global drawer content 1';
- },
- preserveInactiveContent: true,
+ mountContent: container => (container.textContent = 'global drawer content 1'),
});
const { wrapper, globalDrawersWrapper } = await renderComponent();
wrapper.findDrawerTriggerById('global-drawer-1')!.click();
- await delay();
+ expect(globalDrawersWrapper.findDrawerById('global-drawer-1')!.getElement()).toBeInTheDocument();
- expect(globalDrawersWrapper.findDrawerById('global-drawer-1')!.isActive()).toBe(true);
- expect(onVisibilityChangeMock).toHaveBeenCalledWith(true);
+ wrapper.findDrawerTriggerById('global-drawer-1')!.click();
- globalDrawersWrapper.findCloseButtonByActiveDrawerId('global-drawer-1')!.click();
- expect(onVisibilityChangeMock).toHaveBeenCalledWith(false);
+ expect(globalDrawersWrapper.findDrawerById('global-drawer-1')).toBeNull();
});
test('should restore focus to a custom trigger when a global drawer does not have trigger button', async () => {
@@ -1187,24 +1271,6 @@ describe('toolbar mode only features', () => {
});
});
- test('closes a drawer when closeDrawer is called (global drawer)', async () => {
- awsuiPlugins.appLayout.registerDrawer({ ...drawerDefaults, resizable: true, type: 'global' });
-
- const { wrapper } = await renderComponent();
-
- awsuiPlugins.appLayout.openDrawer('test');
-
- await delay();
-
- expect(wrapper.findActiveDrawer()!.getElement()).toHaveTextContent('runtime drawer content');
-
- awsuiPlugins.appLayout.closeDrawer('test');
-
- await delay();
-
- expect(wrapper.findActiveDrawer()).toBeFalsy();
- });
-
test('should not render a trigger button if registered drawer does not have a trigger prop', async () => {
awsuiPlugins.appLayout.registerDrawer({ ...drawerDefaults, trigger: undefined });
@@ -1219,36 +1285,6 @@ describe('toolbar mode only features', () => {
expect(wrapper.findActiveDrawer()!.getElement()).toHaveTextContent('runtime drawer content');
});
- test('should render trigger buttons for global drawers even if local drawers are not present', async () => {
- const { wrapper } = await renderComponent();
-
- awsuiPlugins.appLayout.registerDrawer({
- ...drawerDefaults,
- id: 'global1',
- type: 'global',
- });
-
- await delay();
-
- expect(wrapper.findDrawerTriggerById('global1')!.getElement()).toBeInTheDocument();
- });
-
- test('calls onToggle handler by clicking on drawers trigger button (global runtime drawers)', async () => {
- const onToggle = jest.fn();
- awsuiPlugins.appLayout.registerDrawer({
- ...drawerDefaults,
- id: 'global-drawer',
- type: 'global',
- onToggle: event => onToggle(event.detail),
- });
- const { wrapper } = await renderComponent();
-
- wrapper.findDrawerTriggerById('global-drawer')!.click();
- expect(onToggle).toHaveBeenCalledWith({ isOpen: true, initiatedByUserAction: true });
- wrapper.findDrawerTriggerById('global-drawer')!.click();
- expect(onToggle).toHaveBeenCalledWith({ isOpen: false, initiatedByUserAction: true });
- });
-
test.each([true, false] as const)(
'calls onToggle handler by calling openDrawer and closeDrawer plugin api (global runtime drawers) initiatedByUserAction = %s',
async initiatedByUserAction => {
@@ -1375,106 +1411,154 @@ describe('toolbar mode only features', () => {
});
describe('expanded mode for global drawers', () => {
- test('should set a drawer to expanded mode by clicking on "expanded mode" button', async () => {
- const drawerId = 'global-drawer';
- awsuiPlugins.appLayout.registerDrawer({
- ...drawerDefaults,
- ariaLabels: {
- expandedModeButton: 'Expanded mode button',
- },
- id: drawerId,
- type: 'global',
- isExpandable: true,
- });
- const { wrapper, globalDrawersWrapper } = await renderComponent();
-
- wrapper.findDrawerTriggerById(drawerId)!.click();
- expect(globalDrawersWrapper.findExpandedModeButtonByActiveDrawerId(drawerId)!.getElement()).toBeInTheDocument();
- expect(globalDrawersWrapper.findDrawerById(drawerId)!.isDrawerInExpandedMode()).toBe(false);
- globalDrawersWrapper.findExpandedModeButtonByActiveDrawerId(drawerId)!.click();
- expect(globalDrawersWrapper.findDrawerById(drawerId)!.isDrawerInExpandedMode()).toBe(true);
- expect(
- getGeneratedAnalyticsMetadata(
- globalDrawersWrapper.findExpandedModeButtonByActiveDrawerId(drawerId)!.getElement()
- )
- ).toEqual(
- expect.objectContaining({
- action: 'expand',
- detail: {
- label: 'Expanded mode button',
+ describe.each(['global', 'global-ai'] as const)('drawer type = %s', type => {
+ const findDrawerTriggerById = (id: string, renderProps: Awaited>) => {
+ if (type === 'global') {
+ return renderProps.wrapper.findDrawerTriggerById(id);
+ } else {
+ return renderProps.globalDrawersWrapper.findAiDrawerTrigger();
+ }
+ };
+ const registerDrawer = (payload: DrawerConfig | WidgetDrawerPayload) => {
+ if (type === 'global') {
+ awsuiPlugins.appLayout.registerDrawer({ ...payload, type } as DrawerConfig);
+ } else {
+ awsuiWidgetPlugins.registerLeftDrawer(payload as WidgetDrawerPayload);
+ }
+ };
+
+ test('should set a drawer to expanded mode by clicking on "expanded mode" button', async () => {
+ const drawerId = 'global-drawer';
+ registerDrawer({
+ ...drawerDefaults,
+ ariaLabels: {
+ expandedModeButton: 'Expanded mode button',
},
- })
- );
+ id: drawerId,
+ isExpandable: true,
+ });
+ const renderProps = await renderComponent();
+ const { globalDrawersWrapper } = renderProps;
- globalDrawersWrapper.findExpandedModeButtonByActiveDrawerId(drawerId)!.click();
- expect(globalDrawersWrapper.findDrawerById(drawerId)!.isDrawerInExpandedMode()).toBe(false);
- expect(
- getGeneratedAnalyticsMetadata(
+ findDrawerTriggerById(drawerId, renderProps)!.click();
+ expect(
globalDrawersWrapper.findExpandedModeButtonByActiveDrawerId(drawerId)!.getElement()
- )
- ).toEqual(
- expect.objectContaining({
- action: 'collapse',
- detail: {
- label: 'Expanded mode button',
- },
- })
- );
- });
+ ).toBeInTheDocument();
+ expect(globalDrawersWrapper.findDrawerById(drawerId)!.isDrawerInExpandedMode()).toBe(false);
+ globalDrawersWrapper.findExpandedModeButtonByActiveDrawerId(drawerId)!.click();
+ expect(globalDrawersWrapper.findDrawerById(drawerId)!.isDrawerInExpandedMode()).toBe(true);
+ expect(
+ getGeneratedAnalyticsMetadata(
+ globalDrawersWrapper.findExpandedModeButtonByActiveDrawerId(drawerId)!.getElement()
+ )
+ ).toEqual(
+ expect.objectContaining({
+ action: 'expand',
+ detail: {
+ label: 'Expanded mode button',
+ },
+ })
+ );
- test('only one drawer could be in expanded mode. all other panels should be closed', async () => {
- const drawerId1 = 'global-drawer1';
- const drawerId2 = 'global-drawer2';
- const drawerId3Local = 'local-drawer';
- awsuiPlugins.appLayout.registerDrawer({
- ...drawerDefaults,
- id: drawerId1,
- type: 'global',
- isExpandable: true,
- });
- awsuiPlugins.appLayout.registerDrawer({
- ...drawerDefaults,
- id: drawerId2,
- type: 'global',
- isExpandable: true,
- });
- awsuiPlugins.appLayout.registerDrawer({
- ...drawerDefaults,
- id: drawerId3Local,
+ globalDrawersWrapper.findExpandedModeButtonByActiveDrawerId(drawerId)!.click();
+ expect(globalDrawersWrapper.findDrawerById(drawerId)!.isDrawerInExpandedMode()).toBe(false);
+ expect(
+ getGeneratedAnalyticsMetadata(
+ globalDrawersWrapper.findExpandedModeButtonByActiveDrawerId(drawerId)!.getElement()
+ )
+ ).toEqual(
+ expect.objectContaining({
+ action: 'collapse',
+ detail: {
+ label: 'Expanded mode button',
+ },
+ })
+ );
});
- const { wrapper, globalDrawersWrapper } = await renderComponent(
- nav} />
- );
- await delay();
+ test('only one drawer could be in expanded mode. all other panels should be closed', async () => {
+ const drawerId1 = 'global-drawer1';
+ const drawerId2 = 'global-drawer2';
+ const drawerId3Local = 'local-drawer';
+ awsuiPlugins.appLayout.registerDrawer({
+ ...drawerDefaults,
+ id: drawerId1,
+ type: 'global',
+ isExpandable: true,
+ });
+ registerDrawer({
+ ...drawerDefaults,
+ id: drawerId2,
+ isExpandable: true,
+ });
+ awsuiPlugins.appLayout.registerDrawer({
+ ...drawerDefaults,
+ id: drawerId3Local,
+ });
+ const renderProps = await renderComponent(