+ {/* Render virtual content first to ensure React refs for content will be assigned on the actual nodes. */}
+ {content(true)}
+
+ {content(false)}
+
+ {menuTriggerVisible && overflowMenuOpen && (
+
+
+ (!responsiveState.hideUtilities || responsiveState.hideUtilities.indexOf(i) !== -1) &&
+ !utility.disableUtilityCollapse
+ )}
+ onClose={toggleOverflowMenu}
+ />
+
+ )}
+ >
+ );
+
return (
-
- {/* Render virtual content first to ensure React refs for content will be assigned on the actual nodes. */}
- {content(true)}
-
- {content(false)}
-
- {menuTriggerVisible && overflowMenuOpen && (
-
-
- (!responsiveState.hideUtilities || responsiveState.hideUtilities.indexOf(i) !== -1) &&
- !utility.disableUtilityCollapse
- )}
- onClose={toggleOverflowMenu}
- />
-
- )}
-
+ {visualContext === 'top-navigation' ? (
+
{structuredContent}
+ ) : (
+ structuredContent
+ )}
);
}
diff --git a/src/top-navigation/styles.scss b/src/top-navigation/styles.scss
index 6167698a8a..ebd06cb915 100644
--- a/src/top-navigation/styles.scss
+++ b/src/top-navigation/styles.scss
@@ -42,6 +42,10 @@
inline-size: 9000px;
}
+.custom-content {
+ /* used in test-utils */
+}
+
.hidden {
@include styles.awsui-util-hide;
visibility: hidden;
diff --git a/src/top-navigation/use-top-navigation.ts b/src/top-navigation/use-top-navigation.ts
index 9c922fd200..fa22b49abc 100644
--- a/src/top-navigation/use-top-navigation.ts
+++ b/src/top-navigation/use-top-navigation.ts
@@ -30,6 +30,7 @@ export interface TopNavigationSizeConfiguration {
fullIdentityWidth: number;
titleWidth: number;
searchSlotWidth: number;
+ customContentWidth: number;
searchUtilityWidth: number;
utilityWithLabelWidths: number[];
utilityWithoutLabelWidths: number[];
@@ -59,7 +60,7 @@ export function useTopNavigation({ identity, search, utilities }: UseTopNavigati
// The component works by calculating the possible resize states that it can
// be in, and having a state variable to track which state we're currently in.
const hasSearch = !!search;
- const hasTitleWithLogo = identity && !!identity.logo && !!identity.title;
+ const hasTitleWithLogo = !!identity && !!identity.logo && !!identity.title;
const responsiveStates = useMemo
>(() => {
return generateResponsiveStateKeys(utilities, hasSearch, hasTitleWithLogo);
}, [utilities, hasSearch, hasTitleWithLogo]);
@@ -93,11 +94,13 @@ export function useTopNavigation({ identity, search, utilities }: UseTopNavigati
availableWidth,
// Get widths from the hidden top navigation
- fullIdentityWidth: virtualRef.current.querySelector(`.${styles.identity}`)!.getBoundingClientRect().width,
+ fullIdentityWidth: virtualRef.current.querySelector(`.${styles.identity}`)?.getBoundingClientRect().width ?? 0,
titleWidth: virtualRef.current.querySelector(`.${styles.title}`)?.getBoundingClientRect().width ?? 0,
searchSlotWidth: virtualRef.current.querySelector(`.${styles.search}`)?.getBoundingClientRect().width ?? 0,
- searchUtilityWidth: virtualRef.current.querySelector('[data-utility-special="search"]')!.getBoundingClientRect()
- .width,
+ searchUtilityWidth:
+ virtualRef.current.querySelector('[data-utility-special="search"]')?.getBoundingClientRect().width ?? 0,
+ customContentWidth:
+ virtualRef.current.querySelector(`.${styles['custom-content']}`)?.getBoundingClientRect().width ?? 0,
utilitiesLeftPadding: parseFloat(
getComputedStyle(virtualRef.current.querySelector(`.${styles.utilities}`)!).paddingLeft || '0px'
),
@@ -107,9 +110,8 @@ export function useTopNavigation({ identity, search, utilities }: UseTopNavigati
utilityWithoutLabelWidths: Array.prototype.slice
.call(virtualRef.current.querySelectorAll(`[data-utility-hide="true"]`))
.map((element: Element) => element.getBoundingClientRect().width),
- menuTriggerUtilityWidth: virtualRef.current
- .querySelector('[data-utility-special="menu-trigger"]')!
- .getBoundingClientRect().width,
+ menuTriggerUtilityWidth:
+ virtualRef.current.querySelector('[data-utility-special="menu-trigger"]')?.getBoundingClientRect().width ?? 0,
};
setResponsiveState(determineBestResponsiveState(responsiveStates, sizeConfiguration));
}, [responsiveStates, hasSearch]);
@@ -226,6 +228,7 @@ export function determineBestResponsiveState(
fullIdentityWidth,
titleWidth,
searchSlotWidth,
+ customContentWidth,
searchUtilityWidth,
utilityWithLabelWidths,
utilityWithoutLabelWidths,
@@ -239,7 +242,8 @@ export function determineBestResponsiveState(
.reduce((sum, width) => sum + width, 0);
const menuTriggerWidth = state.hideUtilities ? menuTriggerUtilityWidth : 0;
const identityWidth = state.hideTitle ? fullIdentityWidth - titleWidth : fullIdentityWidth;
- const expectedInnerWidth = identityWidth + searchWidth + utilitiesLeftPadding + utilitiesWidth + menuTriggerWidth;
+ const expectedInnerWidth =
+ identityWidth + searchWidth + customContentWidth + utilitiesLeftPadding + utilitiesWidth + menuTriggerWidth;
if (expectedInnerWidth <= availableWidth - RESPONSIVENESS_BUFFER) {
return state;
}