Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/breadcrumbs-shrink-in-flex-row.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/react': patch
---

Breadcrumbs: In `menu` and `menu-with-root` overflow modes, collapse crumbs as soon as they no longer fit beside sibling content in a flex row, so the collapse point no longer depends on crumb length or resize direction.
7 changes: 7 additions & 0 deletions packages/react/src/Breadcrumbs/Breadcrumbs.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@
margin-bottom: 0;
}

/* The menu modes fit the crumbs to the width the parent offers. As a flex item the nav would
otherwise never shrink below its crumbs, so they would always measure as fitting and nothing
would collapse until the parent was narrower than every crumb together. */
.BreadcrumbsBase:where([data-overflow^='menu']) {
min-width: 0;
}

[data-overflow='menu'],
[data-overflow='menu-with-root'] {
& .BreadcrumbsList {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,33 @@ describe('Breadcrumbs overflow regressions (real layout)', () => {
}
})

it('collapses when it shares a flex row with a sibling that can shrink', async () => {
// Mirrors a header region where the crumbs sit beside a search field. If the nav kept its
// crumbs' width, the sibling would absorb the squeeze and the crumbs would always measure as
// fitting, so nothing would collapse until the row was narrower than the crumbs alone.
// Whole-pixel widths, so rounding can't decide whether the crumbs fit.
const ui = (width: number) => (
<div style={{display: 'flex', width, ['--text-body-size-medium' as string]: '20px'}}>
<Breadcrumbs overflow="menu">
{['owner', 'repository'].map((label, index) => (
<Breadcrumbs.Item key={label} href={`#${label}`} selected={index === 1} style={{width: 150}}>
{label}
</Breadcrumbs.Item>
))}
</Breadcrumbs>
<div style={{flex: '0 1 400px', minWidth: 100}} />
</div>
)
const {rerender} = render(ui(1600))
await nextFrame()
expect(menuButton()).toBeNull()

// The crumbs only fit if the sibling gives up everything above its minimum width.
rerender(ui(screen.getByRole('list').getBoundingClientRect().width + 100))
await nextFrame()
expect(visibleLinks()).toEqual(['repository'])
})

it('starts with the overflow menu closed after switching to wrap and back', async () => {
const user = userEvent.setup()
const ui = (overflow: 'wrap' | 'menu') => <div style={{width: 300}}>{crumbs(overflow, labels)}</div>
Expand Down
Loading