@@ -40,6 +40,7 @@ const BreadcrumbsMenuItem = React.forwardRef<HTMLButtonElement, BreadcrumbsMenuI
40
40
aria-haspopup = "menu"
41
41
aria-expanded = "false"
42
42
variant = "invisible"
43
+ size = "small"
43
44
trailingAction = { null }
44
45
style = { { display : 'inline-flex' } }
45
46
{ ...rest }
@@ -80,13 +81,11 @@ function Breadcrumbs({className, children, sx: sxProp, overflow = 'wrap', hideRo
80
81
const [ menuItems , setMenuItems ] = useState < React . ReactElement [ ] > ( [ ] )
81
82
const [ itemWidths , setItemWidths ] = useState < number [ ] > ( [ ] )
82
83
const [ effectiveHideRoot , setEffectiveHideRoot ] = useState < boolean > ( hideRoot )
83
- const previousWidthsRef = useRef < string > ( '' )
84
84
85
85
const childArray = React . Children . toArray ( children ) . filter ( child =>
86
86
React . isValidElement ( child ) ,
87
87
) as React . ReactElement [ ]
88
88
89
- // Initialize visible items to show all items initially for measurement
90
89
useEffect ( ( ) => {
91
90
if ( visibleItems . length === 0 && childArray . length > 0 ) {
92
91
setVisibleItems ( childArray )
@@ -101,26 +100,6 @@ function Breadcrumbs({className, children, sx: sxProp, overflow = 'wrap', hideRo
101
100
102
101
useResizeObserver ( handleResize , containerRef )
103
102
104
- // Calculate item widths from rendered items using parent container
105
- useEffect ( ( ) => {
106
- if ( containerRef . current && overflow === 'menu' ) {
107
- const listElement = containerRef . current . querySelector ( 'ol' )
108
- if ( listElement && listElement . children . length > 0 ) {
109
- // Only measure widths when all original items are visible (no overflow menu yet)
110
- if ( listElement . children . length === childArray . length ) {
111
- const widths = Array . from ( listElement . children ) . map ( child => ( child as HTMLElement ) . offsetWidth )
112
- const widthsString = JSON . stringify ( widths )
113
- // Only update if widths have actually changed to prevent infinite loops
114
- if ( widthsString !== previousWidthsRef . current ) {
115
- previousWidthsRef . current = widthsString
116
- setItemWidths ( widths )
117
- }
118
- }
119
- }
120
- }
121
- } , [ childArray , overflow , visibleItems ] )
122
-
123
- // Calculate which items are visible vs in menu
124
103
useEffect ( ( ) => {
125
104
if ( overflow === 'wrap' ) {
126
105
setVisibleItems ( childArray )
@@ -132,8 +111,22 @@ function Breadcrumbs({className, children, sx: sxProp, overflow = 'wrap', hideRo
132
111
// For 'menu' overflow mode
133
112
// Helper function to calculate visible items and menu items with progressive hiding
134
113
const calculateOverflow = ( availableWidth : number ) => {
114
+ const listElement = containerRef . current ?. querySelector ( 'ol' )
115
+ if ( listElement && listElement . children . length > 0 && itemWidths . length === 0 ) {
116
+ const widths = Array . from ( listElement . children ) . map ( child => ( child as HTMLElement ) . offsetWidth )
117
+ setItemWidths ( widths )
118
+ }
135
119
const MENU_BUTTON_WIDTH = 50 // Approximate width of "..." button
136
120
121
+ // Helper function to calculate total width of visible items
122
+ const calculateVisibleItemsWidth = ( items : React . ReactElement [ ] ) => {
123
+ return items
124
+ . map ( ( item , index ) => {
125
+ return itemWidths [ index ]
126
+ } )
127
+ . reduce ( ( sum , width ) => sum + width , 0 )
128
+ }
129
+
137
130
let currentVisibleItems = [ ...childArray ]
138
131
let currentMenuItems : React . ReactElement [ ] = [ ]
139
132
@@ -146,13 +139,8 @@ function Breadcrumbs({className, children, sx: sxProp, overflow = 'wrap', hideRo
146
139
}
147
140
148
141
// Now check if current visible items fit in available width
149
- if ( availableWidth > 0 && itemWidths . length === childArray . length ) {
150
- let visibleItemsWidthTotal = currentVisibleItems
151
- . map ( item => {
152
- const index = childArray . findIndex ( child => child . key === item . key )
153
- return index !== - 1 ? itemWidths [ index ] : 0
154
- } )
155
- . reduce ( ( sum , width ) => sum + width , 0 )
142
+ if ( availableWidth > 0 ) {
143
+ let visibleItemsWidthTotal = calculateVisibleItemsWidth ( currentVisibleItems )
156
144
157
145
// Add menu button width if we have hidden items
158
146
if ( currentMenuItems . length > 0 ) {
@@ -161,7 +149,6 @@ function Breadcrumbs({className, children, sx: sxProp, overflow = 'wrap', hideRo
161
149
162
150
// Progressive hiding: keep moving items to menu until they fit
163
151
let effectiveHideRoot = hideRoot
164
-
165
152
while ( visibleItemsWidthTotal > availableWidth && currentVisibleItems . length > 1 ) {
166
153
// Determine which item to hide based on hideRoot setting
167
154
let itemToHide : React . ReactElement
@@ -179,12 +166,7 @@ function Breadcrumbs({className, children, sx: sxProp, overflow = 'wrap', hideRo
179
166
currentMenuItems = [ itemToHide , ...currentMenuItems ]
180
167
181
168
// Recalculate width
182
- visibleItemsWidthTotal = currentVisibleItems
183
- . map ( item => {
184
- const index = childArray . findIndex ( child => child . key === item . key )
185
- return index !== - 1 ? itemWidths [ index ] : 0
186
- } )
187
- . reduce ( ( sum , width ) => sum + width , 0 )
169
+ visibleItemsWidthTotal = calculateVisibleItemsWidth ( currentVisibleItems )
188
170
189
171
// Add menu button width
190
172
if ( currentMenuItems . length > 0 ) {
@@ -206,24 +188,13 @@ function Breadcrumbs({className, children, sx: sxProp, overflow = 'wrap', hideRo
206
188
currentMenuItems = [ rootItem , ...currentMenuItems ]
207
189
208
190
// Recalculate width one more time
209
- visibleItemsWidthTotal = currentVisibleItems
210
- . map ( item => {
211
- const index = childArray . findIndex ( child => child . key === item . key )
212
- return index !== - 1 ? itemWidths [ index ] : 0
213
- } )
214
- . reduce ( ( sum , width ) => sum + width , 0 )
191
+ visibleItemsWidthTotal = calculateVisibleItemsWidth ( currentVisibleItems )
215
192
216
193
if ( currentMenuItems . length > 0 ) {
217
194
visibleItemsWidthTotal += MENU_BUTTON_WIDTH
218
195
}
219
196
}
220
197
}
221
-
222
- // Final check: if even the leaf breadcrumb + menu doesn't fit, just show them anyway
223
- // The CSS will handle truncation of the leaf breadcrumb
224
- if ( visibleItemsWidthTotal > availableWidth && currentVisibleItems . length === 1 ) {
225
- // Keep the current configuration - CSS will handle truncation
226
- }
227
198
}
228
199
229
200
return {
0 commit comments