@@ -10,6 +10,7 @@ import {useResizeObserver} from '../hooks/useResizeObserver'
1010import type { ResizeObserverEntry } from '../hooks/useResizeObserver'
1111import { useOnEscapePress } from '../hooks/useOnEscapePress'
1212import { useOnOutsideClick } from '../hooks/useOnOutsideClick'
13+ import { useFeatureFlag } from '../FeatureFlags'
1314
1415export type BreadcrumbsProps = React . PropsWithChildren < {
1516 /**
@@ -144,6 +145,8 @@ const getValidChildren = (children: React.ReactNode) => {
144145}
145146
146147function Breadcrumbs ( { className, children, style, overflow = 'wrap' , variant = 'normal' } : BreadcrumbsProps ) {
148+ const overflowMenuEnabled = useFeatureFlag ( 'primer_react_breadcrumbs_overflow_menu' )
149+ const wrappedChildren = React . Children . map ( children , child => < li className = { classes . ItemWrapper } > { child } </ li > )
147150 const containerRef = useRef < HTMLElement > ( null )
148151
149152 const measureMenuButton = useCallback ( ( element : HTMLDetailsElement | null ) => {
@@ -173,13 +176,18 @@ function Breadcrumbs({className, children, style, overflow = 'wrap', variant = '
173176
174177 useEffect ( ( ) => {
175178 const listElement = containerRef . current ?. querySelector ( 'ol' )
176- if ( listElement && listElement . children . length > 0 && listElement . children . length === childArray . length ) {
179+ if (
180+ overflowMenuEnabled &&
181+ listElement &&
182+ listElement . children . length > 0 &&
183+ listElement . children . length === childArray . length
184+ ) {
177185 const listElementArray = Array . from ( listElement . children ) as HTMLElement [ ]
178186 const widths = listElementArray . map ( child => child . offsetWidth )
179187 setChildArrayWidths ( widths )
180188 setRootItemWidth ( listElementArray [ 0 ] . offsetWidth )
181189 }
182- } , [ childArray ] )
190+ } , [ childArray , overflowMenuEnabled ] )
183191
184192 const calculateOverflow = useCallback (
185193 ( availableWidth : number ) => {
@@ -239,7 +247,7 @@ function Breadcrumbs({className, children, style, overflow = 'wrap', variant = '
239247
240248 const handleResize = useCallback (
241249 ( entries : ResizeObserverEntry [ ] ) => {
242- if ( entries [ 0 ] ) {
250+ if ( overflowMenuEnabled && entries [ 0 ] ) {
243251 const containerWidth = entries [ 0 ] . contentRect . width
244252 const result = calculateOverflow ( containerWidth )
245253 if (
@@ -252,66 +260,73 @@ function Breadcrumbs({className, children, style, overflow = 'wrap', variant = '
252260 }
253261 }
254262 } ,
255- [ calculateOverflow , effectiveHideRoot , menuItems . length , visibleItems . length ] ,
263+ [ calculateOverflow , effectiveHideRoot , menuItems . length , overflowMenuEnabled , visibleItems . length ] ,
256264 )
257265
258266 useResizeObserver ( handleResize , containerRef )
259267
260268 useEffect ( ( ) => {
261- if ( ( overflow === 'menu' || overflow === 'menu-with-root' ) && childArray . length > 5 && menuItems . length === 0 ) {
269+ if (
270+ overflowMenuEnabled &&
271+ ( overflow === 'menu' || overflow === 'menu-with-root' ) &&
272+ childArray . length > 5 &&
273+ menuItems . length === 0
274+ ) {
262275 const containerWidth = containerRef . current ?. offsetWidth || 800
263276 const result = calculateOverflow ( containerWidth )
264277 setVisibleItems ( result . visibleItems )
265278 setMenuItems ( result . menuItems )
266279 setEffectiveHideRoot ( result . effectiveHideRoot )
267280 }
268- } , [ overflow , childArray , calculateOverflow , menuItems . length ] )
281+ } , [ overflow , childArray , calculateOverflow , menuItems . length , overflowMenuEnabled ] )
269282
270283 const finalChildren = React . useMemo ( ( ) => {
271- if ( overflow === 'wrap' || menuItems . length === 0 ) {
272- return React . Children . map ( children , child => < li className = { classes . ItemWrapper } > { child } </ li > )
273- }
274-
275- let effectiveMenuItems = [ ...menuItems ]
276- // In 'menu-with-root' mode, include the root item inside the menu even if it's visible in the breadcrumbs
277- if ( ! effectiveHideRoot ) {
278- effectiveMenuItems = [ ...menuItems . slice ( 1 ) ]
279- }
280- const menuElement = (
281- < li className = { classes . BreadcrumbsItem } key = "breadcrumbs-menu" >
282- < BreadcrumbsMenuItem
283- ref = { measureMenuButton }
284- items = { effectiveMenuItems }
285- aria-label = { `${ effectiveMenuItems . length } more breadcrumb items` }
286- />
287- < ItemSeparator />
288- </ li >
289- )
290-
291- const visibleElements = visibleItems . map ( ( child , index ) => (
292- < li className = { classes . BreadcrumbsItem } key = { `visible + ${ index } ` } >
293- { child }
294- < ItemSeparator />
295- </ li >
296- ) )
297-
298- const rootElement = (
299- < li className = { classes . BreadcrumbsItem } key = { `rootElement` } >
300- { rootItem }
301- < ItemSeparator />
302- </ li >
303- )
284+ if ( overflowMenuEnabled ) {
285+ if ( overflow === 'wrap' || menuItems . length === 0 ) {
286+ return React . Children . map ( children , child => < li className = { classes . ItemWrapper } > { child } </ li > )
287+ }
304288
305- if ( effectiveHideRoot ) {
306- // Show: [overflow menu, leaf breadcrumb]
307- return [ menuElement , ...visibleElements ]
308- } else {
309- // Show: [root breadcrumb, overflow menu, leaf breadcrumb]
310- return [ rootElement , menuElement , ...visibleElements ]
289+ let effectiveMenuItems = [ ...menuItems ]
290+ // In 'menu-with-root' mode, include the root item inside the menu even if it's visible in the breadcrumbs
291+ if ( ! effectiveHideRoot ) {
292+ effectiveMenuItems = [ ...menuItems . slice ( 1 ) ]
293+ }
294+ const menuElement = (
295+ < li className = { classes . BreadcrumbsItem } key = "breadcrumbs-menu" >
296+ < BreadcrumbsMenuItem
297+ ref = { measureMenuButton }
298+ items = { effectiveMenuItems }
299+ aria-label = { `${ effectiveMenuItems . length } more breadcrumb items` }
300+ />
301+ < ItemSeparator />
302+ </ li >
303+ )
304+
305+ const visibleElements = visibleItems . map ( ( child , index ) => (
306+ < li className = { classes . BreadcrumbsItem } key = { `visible + ${ index } ` } >
307+ { child }
308+ < ItemSeparator />
309+ </ li >
310+ ) )
311+
312+ const rootElement = (
313+ < li className = { classes . BreadcrumbsItem } key = { `rootElement` } >
314+ { rootItem }
315+ < ItemSeparator />
316+ </ li >
317+ )
318+
319+ if ( effectiveHideRoot ) {
320+ // Show: [overflow menu, leaf breadcrumb]
321+ return [ menuElement , ...visibleElements ]
322+ } else {
323+ // Show: [root breadcrumb, overflow menu, leaf breadcrumb]
324+ return [ rootElement , menuElement , ...visibleElements ]
325+ }
311326 }
312- } , [ overflow , menuItems , effectiveHideRoot , measureMenuButton , visibleItems , rootItem , children ] )
327+ } , [ overflowMenuEnabled , overflow , menuItems , effectiveHideRoot , measureMenuButton , visibleItems , rootItem , children ] )
313328
314- return (
329+ return overflowMenuEnabled ? (
315330 < nav
316331 className = { clsx ( className , classes . BreadcrumbsBase ) }
317332 aria-label = "Breadcrumbs"
@@ -322,6 +337,15 @@ function Breadcrumbs({className, children, style, overflow = 'wrap', variant = '
322337 >
323338 < BreadcrumbsList > { finalChildren } </ BreadcrumbsList >
324339 </ nav >
340+ ) : (
341+ < nav
342+ className = { clsx ( className , classes . BreadcrumbsBase ) }
343+ aria-label = "Breadcrumbs"
344+ style = { style }
345+ data-variant = { variant }
346+ >
347+ < BreadcrumbsList > { wrappedChildren } </ BreadcrumbsList >
348+ </ nav >
325349 )
326350}
327351
0 commit comments