Skip to content

Commit 10147a7

Browse files
Revert "Remove breadcrumbs overflow menu feature flag" (#7073)
1 parent c32f726 commit 10147a7

File tree

5 files changed

+163
-83
lines changed

5 files changed

+163
-83
lines changed

.changeset/chilled-eggs-warn.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

packages/react/src/Breadcrumbs/Breadcrumbs.features.stories.tsx

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type {Meta} from '@storybook/react-vite'
22
import type React from 'react'
33
import type {ComponentProps} from '../utils/types'
44
import Breadcrumbs from './Breadcrumbs'
5+
import {FeatureFlags} from '../FeatureFlags'
56

67
export default {
78
title: 'Components/Breadcrumbs/Features',
@@ -22,7 +23,23 @@ export const OverflowWrap = () => (
2223
</Breadcrumbs>
2324
)
2425

25-
export const OverflowMenu = () => (
26+
export const OverflowMenuFeatureFlagEnabled = () => (
27+
<FeatureFlags flags={{primer_react_breadcrumbs_overflow_menu: true}}>
28+
<Breadcrumbs overflow="menu">
29+
<Breadcrumbs.Item href="#">Home</Breadcrumbs.Item>
30+
<Breadcrumbs.Item href="#">Products</Breadcrumbs.Item>
31+
<Breadcrumbs.Item href="#">Category</Breadcrumbs.Item>
32+
<Breadcrumbs.Item href="#">Subcategory</Breadcrumbs.Item>
33+
<Breadcrumbs.Item href="#">Item</Breadcrumbs.Item>
34+
<Breadcrumbs.Item href="#">Details</Breadcrumbs.Item>
35+
<Breadcrumbs.Item href="#" selected>
36+
Current Page
37+
</Breadcrumbs.Item>
38+
</Breadcrumbs>
39+
</FeatureFlags>
40+
)
41+
42+
export const OverflowMenuFeatureFlagDisabled = () => (
2643
<Breadcrumbs overflow="menu">
2744
<Breadcrumbs.Item href="#">Home</Breadcrumbs.Item>
2845
<Breadcrumbs.Item href="#">Products</Breadcrumbs.Item>
@@ -36,7 +53,7 @@ export const OverflowMenu = () => (
3653
</Breadcrumbs>
3754
)
3855

39-
export const OverflowMenuShowRoot = () => (
56+
export const OverflowMenuShowRootFeatureFlagDisabled = () => (
4057
<Breadcrumbs overflow="menu-with-root">
4158
<Breadcrumbs.Item href="#">github</Breadcrumbs.Item>
4259
<Breadcrumbs.Item href="#">Teams</Breadcrumbs.Item>
@@ -49,18 +66,35 @@ export const OverflowMenuShowRoot = () => (
4966
</Breadcrumbs>
5067
)
5168

69+
export const OverflowMenuShowRootFeatureFlagEnabled = () => (
70+
<FeatureFlags flags={{primer_react_breadcrumbs_overflow_menu: true}}>
71+
<Breadcrumbs overflow="menu-with-root">
72+
<Breadcrumbs.Item href="#">github</Breadcrumbs.Item>
73+
<Breadcrumbs.Item href="#">Teams</Breadcrumbs.Item>
74+
<Breadcrumbs.Item href="#">Engineering</Breadcrumbs.Item>
75+
<Breadcrumbs.Item href="#">core-productivity</Breadcrumbs.Item>
76+
<Breadcrumbs.Item href="#">collaboration-workflows-flex</Breadcrumbs.Item>
77+
<Breadcrumbs.Item href="#" selected>
78+
global-navigation-reviewers
79+
</Breadcrumbs.Item>
80+
</Breadcrumbs>
81+
</FeatureFlags>
82+
)
83+
5284
export const SpaciousVariantWithOverflowMenu = () => (
53-
<Breadcrumbs overflow="menu" variant="spacious">
54-
<Breadcrumbs.Item href="#">Home</Breadcrumbs.Item>
55-
<Breadcrumbs.Item href="#">Products</Breadcrumbs.Item>
56-
<Breadcrumbs.Item href="#">Category</Breadcrumbs.Item>
57-
<Breadcrumbs.Item href="#">Subcategory</Breadcrumbs.Item>
58-
<Breadcrumbs.Item href="#">Item</Breadcrumbs.Item>
59-
<Breadcrumbs.Item href="#">Details</Breadcrumbs.Item>
60-
<Breadcrumbs.Item href="#" selected>
61-
Current Page
62-
</Breadcrumbs.Item>
63-
</Breadcrumbs>
85+
<FeatureFlags flags={{primer_react_breadcrumbs_overflow_menu: true}}>
86+
<Breadcrumbs overflow="menu" variant="spacious">
87+
<Breadcrumbs.Item href="#">Home</Breadcrumbs.Item>
88+
<Breadcrumbs.Item href="#">Products</Breadcrumbs.Item>
89+
<Breadcrumbs.Item href="#">Category</Breadcrumbs.Item>
90+
<Breadcrumbs.Item href="#">Subcategory</Breadcrumbs.Item>
91+
<Breadcrumbs.Item href="#">Item</Breadcrumbs.Item>
92+
<Breadcrumbs.Item href="#">Details</Breadcrumbs.Item>
93+
<Breadcrumbs.Item href="#" selected>
94+
Current Page
95+
</Breadcrumbs.Item>
96+
</Breadcrumbs>
97+
</FeatureFlags>
6498
)
6599

66100
export const SpaciousVariantWithOverflowWrap = () => (

packages/react/src/Breadcrumbs/Breadcrumbs.tsx

Lines changed: 71 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {useResizeObserver} from '../hooks/useResizeObserver'
1010
import type {ResizeObserverEntry} from '../hooks/useResizeObserver'
1111
import {useOnEscapePress} from '../hooks/useOnEscapePress'
1212
import {useOnOutsideClick} from '../hooks/useOnOutsideClick'
13+
import {useFeatureFlag} from '../FeatureFlags'
1314

1415
export type BreadcrumbsProps = React.PropsWithChildren<{
1516
/**
@@ -144,6 +145,8 @@ const getValidChildren = (children: React.ReactNode) => {
144145
}
145146

146147
function 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

Comments
 (0)