@@ -47,11 +47,12 @@ const overflowEffect = (
4747 childArray : Array < React . ReactElement < any > > ,
4848 childWidthArray : ChildWidthArray ,
4949 noIconChildWidthArray : ChildWidthArray ,
50- updateListAndMenu : ( props : ResponsiveProps , iconsVisible : boolean ) => void ,
50+ updateListAndMenu : ( props : ResponsiveProps , iconsVisible : boolean , overflowMeasured : boolean ) => void ,
5151) => {
5252 let iconsVisible = true
5353 if ( childWidthArray . length === 0 ) {
54- updateListAndMenu ( { items : childArray , menuItems : [ ] } , iconsVisible )
54+ updateListAndMenu ( { items : childArray , menuItems : [ ] } , iconsVisible , false )
55+ return
5556 }
5657 const numberOfItemsPossible = calculatePossibleItems ( childWidthArray , navWidth )
5758 const numberOfItemsWithoutIconPossible = calculatePossibleItems ( noIconChildWidthArray , navWidth )
@@ -104,7 +105,7 @@ const overflowEffect = (
104105 }
105106 }
106107 }
107- updateListAndMenu ( { items, menuItems} , iconsVisible )
108+ updateListAndMenu ( { items, menuItems} , iconsVisible , true )
108109}
109110
110111export const getValidChildren = ( children : React . ReactNode ) => {
@@ -166,6 +167,8 @@ export const UnderlineNav = forwardRef(
166167 const [ iconsVisible , setIconsVisible ] = useState < boolean > ( true )
167168 const [ childWidthArray , setChildWidthArray ] = useState < ChildWidthArray > ( [ ] )
168169 const [ noIconChildWidthArray , setNoIconChildWidthArray ] = useState < ChildWidthArray > ( [ ] )
170+ // Track whether the initial overflow calculation is complete to prevent CLS
171+ const [ isOverflowMeasured , setIsOverflowMeasured ] = useState ( false )
169172
170173 const validChildren = getValidChildren ( children )
171174
@@ -209,7 +212,7 @@ export const UnderlineNav = forwardRef(
209212 prospectiveListItem : React . ReactElement < any > ,
210213 indexOfProspectiveListItem : number ,
211214 event : React . MouseEvent < HTMLAnchorElement > | React . KeyboardEvent < HTMLAnchorElement > ,
212- callback : ( props : ResponsiveProps , displayIcons : boolean ) => void ,
215+ callback : ( props : ResponsiveProps , displayIcons : boolean , overflowMeasured : boolean ) => void ,
213216 ) => {
214217 // get the selected menu item's width
215218 const widthToFitIntoList = getItemsWidth ( prospectiveListItem . props . children )
@@ -229,7 +232,7 @@ export const UnderlineNav = forwardRef(
229232 const updatedMenuItems = [ ...menuItems ]
230233 // Add itemsToAddToMenu array's items to the menu at the index of the prospectiveListItem and remove 1 count of items (prospectiveListItem)
231234 updatedMenuItems . splice ( indexOfProspectiveListItem , 1 , ...itemsToAddToMenu )
232- callback ( { items : updatedItemList , menuItems : updatedMenuItems } , false )
235+ callback ( { items : updatedItemList , menuItems : updatedMenuItems } , false , true )
233236 }
234237 // How many items do we need to pull in to the menu to make room for the selected menu item.
235238 function getBreakpointForItemSwapping ( widthToFitIntoList : number , availableSpace : number ) {
@@ -245,10 +248,17 @@ export const UnderlineNav = forwardRef(
245248 return breakpoint
246249 }
247250
248- const updateListAndMenu = useCallback ( ( props : ResponsiveProps , displayIcons : boolean ) => {
249- setResponsiveProps ( props )
250- setIconsVisible ( displayIcons )
251- } , [ ] )
251+ const updateListAndMenu = useCallback (
252+ ( props : ResponsiveProps , displayIcons : boolean , overflowMeasured : boolean ) => {
253+ setResponsiveProps ( props )
254+ setIconsVisible ( displayIcons )
255+
256+ if ( overflowMeasured ) {
257+ setIsOverflowMeasured ( true )
258+ }
259+ } ,
260+ [ ] ,
261+ )
252262 const setChildrenWidth = useCallback ( ( size : ChildSize ) => {
253263 setChildWidthArray ( arr => {
254264 const newArr = [ ...arr , size ]
@@ -330,7 +340,14 @@ export const UnderlineNav = forwardRef(
330340 } }
331341 >
332342 { ariaLabel && < VisuallyHidden as = "h2" > { `${ ariaLabel } navigation` } </ VisuallyHidden > }
333- < UnderlineWrapper as = { as } aria-label = { ariaLabel } className = { className } ref = { navRef } data-variant = { variant } >
343+ < UnderlineWrapper
344+ as = { as }
345+ aria-label = { ariaLabel }
346+ className = { className }
347+ ref = { navRef }
348+ data-variant = { variant }
349+ data-overflow-measured = { isOverflowMeasured ? 'true' : 'false' }
350+ >
334351 < UnderlineItemList ref = { listRef } role = "list" >
335352 { listItems }
336353 { menuItems . length > 0 && (
0 commit comments