diff --git a/package.json b/package.json
index 24a44681d5..0881725b54 100644
--- a/package.json
+++ b/package.json
@@ -164,7 +164,7 @@
{
"path": "lib/components/internal/widget-exports.js",
"brotli": false,
- "limit": "775 kB",
+ "limit": "776 kB",
"ignore": "react-dom"
}
],
diff --git a/pages/app-layout/utils/external-widget.tsx b/pages/app-layout/utils/external-widget.tsx
index 0edf5eefbd..b0137f824a 100644
--- a/pages/app-layout/utils/external-widget.tsx
+++ b/pages/app-layout/utils/external-widget.tsx
@@ -3,6 +3,7 @@
import React, { useEffect, useImperativeHandle, useRef, useState } from 'react';
import ReactDOM, { unmountComponentAtNode } from 'react-dom';
+import ButtonDropdown from '~components/button-dropdown';
import Drawer from '~components/drawer';
import awsuiPlugins from '~components/internal/plugins';
@@ -153,13 +154,20 @@ awsuiPlugins.appLayout.registerDrawer({
mountContent: (container, mountContext) => {
ReactDOM.render(
-
- global widget content circle 1
- {new Array(100).fill(null).map((_, index) => (
- {index}
- ))}
- circle-global bottom content
- ,
+ Global drawer}
+ headerActions={
+
+ }
+ >
+
+ global widget content circle 1
+ {new Array(100).fill(null).map((_, index) => (
+ {index}
+ ))}
+ circle-global bottom content
+
+ ,
container
);
},
diff --git a/src/__tests__/snapshot-tests/__snapshots__/documenter.test.ts.snap b/src/__tests__/snapshot-tests/__snapshots__/documenter.test.ts.snap
index 24b942b4a9..4b22dd5285 100644
--- a/src/__tests__/snapshot-tests/__snapshots__/documenter.test.ts.snap
+++ b/src/__tests__/snapshot-tests/__snapshots__/documenter.test.ts.snap
@@ -8451,6 +8451,11 @@ It should contain the only \`h2\` used in the drawer.",
"isDefault": false,
"name": "header",
},
+ {
+ "description": "Actions for the header. Available only if you specify the \`header\` property.",
+ "isDefault": false,
+ "name": "headerActions",
+ },
],
"releaseStatus": "stable",
}
diff --git a/src/__tests__/snapshot-tests/__snapshots__/test-utils-selectors.test.tsx.snap b/src/__tests__/snapshot-tests/__snapshots__/test-utils-selectors.test.tsx.snap
index c47fe6939d..7c52e98da4 100644
--- a/src/__tests__/snapshot-tests/__snapshots__/test-utils-selectors.test.tsx.snap
+++ b/src/__tests__/snapshot-tests/__snapshots__/test-utils-selectors.test.tsx.snap
@@ -246,6 +246,7 @@ exports[`test-utils selectors 1`] = `
],
"drawer": [
"awsui_drawer_1sxt8",
+ "awsui_header-actions_1sxt8",
"awsui_header_1sxt8",
"awsui_test-utils-drawer-content_1sxt8",
],
diff --git a/src/drawer/__tests__/drawer.test.tsx b/src/drawer/__tests__/drawer.test.tsx
index 26b8241c23..0109d762f6 100644
--- a/src/drawer/__tests__/drawer.test.tsx
+++ b/src/drawer/__tests__/drawer.test.tsx
@@ -25,6 +25,22 @@ test('renders header if it is provided', () => {
expect(wrapper.findContent()!.getElement()).toHaveTextContent('there is a header above');
});
+test('renders header actions if it is provided', () => {
+ const wrapper = renderDrawer(
+ Header actions}>
+ there is a header above
+
+ );
+ expect(wrapper.findHeader()!.getElement()).toHaveTextContent('Bla bla');
+ expect(wrapper.findHeaderActions()!.getElement()).toHaveTextContent('Header actions');
+ expect(wrapper.findContent()!.getElement()).toHaveTextContent('there is a header above');
+});
+
+test('does not render header actions if header is not provided', () => {
+ const wrapper = renderDrawer(Header actions}>there is a header above);
+ expect(wrapper.findHeaderActions()).toBeFalsy();
+});
+
test('renders loading state', () => {
const { container } = render();
expect(createWrapper(container).findStatusIndicator()!.getElement()).toHaveTextContent('Loading content');
diff --git a/src/drawer/implementation.tsx b/src/drawer/implementation.tsx
index 9cddc690c2..40e710242d 100644
--- a/src/drawer/implementation.tsx
+++ b/src/drawer/implementation.tsx
@@ -23,6 +23,7 @@ export function DrawerImplementation({
i18nStrings,
disableContentPaddings,
__internalRootRef,
+ headerActions,
...restProps
}: DrawerInternalProps) {
const baseProps = getBaseProps(restProps);
@@ -32,6 +33,7 @@ export function DrawerImplementation({
...baseProps,
className: clsx(baseProps.className, styles.drawer, isToolbar && styles['with-toolbar']),
};
+
return loading ? (
) : (
- {header &&
{header}
}
+ {header && (
+
+ {header}
+ {headerActions &&
{headerActions}
}
+
+ )}
& {
border-color: transparent;
margin-block-end: 0px;
@@ -36,6 +39,17 @@
/* stylelint-enable @cloudscape-design/no-implicit-descendant, selector-max-type */
}
+.header-actions {
+ display: inline-flex;
+ align-items: start;
+ z-index: 1;
+ /*
+ Compensate for the difference between the runtime drawer's and the drawer component's heading
+ to ensure the header actions are vertically aligned
+ */
+ margin-block-start: -6px;
+}
+
.content-with-paddings:not(:empty) {
padding-block-start: awsui.$space-panel-content-top;
padding-inline-start: awsui.$space-panel-side-left;
diff --git a/src/test-utils/dom/drawer/index.ts b/src/test-utils/dom/drawer/index.ts
index 00d4020439..7d6b009750 100644
--- a/src/test-utils/dom/drawer/index.ts
+++ b/src/test-utils/dom/drawer/index.ts
@@ -11,6 +11,10 @@ export default class DrawerWrapper extends ComponentWrapper {
return this.findByClassName(styles.header);
}
+ findHeaderActions(): ElementWrapper | null {
+ return this.findByClassName(styles['header-actions']);
+ }
+
findContent(): ElementWrapper | null {
return this.findByClassName(styles['test-utils-drawer-content']);
}