Skip to content

Breadcrumbs: Only show the previous breadcrumb on narrow viewports#7735

Open
liuliu-dev wants to merge 9 commits intomainfrom
liuliu/only-show-the-previous-breadcrumb-on-narrow
Open

Breadcrumbs: Only show the previous breadcrumb on narrow viewports#7735
liuliu-dev wants to merge 9 commits intomainfrom
liuliu/only-show-the-previous-breadcrumb-on-narrow

Conversation

@liuliu-dev
Copy link
Copy Markdown
Contributor

@liuliu-dev liuliu-dev commented Apr 7, 2026

Closes https://github.com/github/primer/issues/6371

Changelog

Changed

On narrow viewports (≤544px), breadcrumbs collapse to show only the previous (parent) item as a back link. The current page is hidden since you're already on it. Consumers can pass visibleItemsOnNarrow to control how many items stay visible.

Screen.Recording.2026-04-09.at.4.13.54.PM.mov

Rollout strategy

  • Minor release

Testing & Reviewing

Merge checklist

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 7, 2026

🦋 Changeset detected

Latest commit: f54db6f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@primer/react Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 7, 2026

⚠️ Action required

👋 Hi, this pull request contains changes to the source code that github/github-ui depends on. If you are GitHub staff, test these changes with github/github-ui using the integration workflow. Check the integration testing docs for step-by-step instructions. Or, apply the integration-tests: skipped manually label to skip these checks.

To publish a canary release for integration testing, apply the Canary Release label to this PR.

@github-actions github-actions bot added the integration-tests: recommended This change needs to be tested for breaking changes. See https://arc.net/l/quote/tdmpakpm label Apr 7, 2026
@github-actions github-actions bot temporarily deployed to storybook-preview-7735 April 7, 2026 22:53 Inactive
@liuliu-dev liuliu-dev added the Canary Release Apply this label when you want CI to create a canary release of the current PR label Apr 7, 2026
@github-actions github-actions bot temporarily deployed to storybook-preview-7735 April 7, 2026 23:32 Inactive
@github-actions github-actions bot requested a deployment to storybook-preview-7735 April 9, 2026 21:35 Abandoned
@primer
Copy link
Copy Markdown
Contributor

primer bot commented Apr 9, 2026

🤖 Lint issues have been automatically fixed and committed to this PR.

@github-actions github-actions bot requested a deployment to storybook-preview-7735 April 9, 2026 21:43 Abandoned
@primer-integration
Copy link
Copy Markdown

👋 Hi from github/github-ui! Your integration PR is ready: https://github.com/github/github-ui/pull/18292

@primer-integration
Copy link
Copy Markdown

Integration test results from github/github-ui:

Passed  CI   Passed
Passed  VRT   Passed
Passed  Projects   Passed

All checks passed!

@liuliu-dev liuliu-dev requested a review from francinelucca April 9, 2026 23:15
@liuliu-dev liuliu-dev marked this pull request as ready for review April 9, 2026 23:15
@liuliu-dev liuliu-dev requested a review from a team as a code owner April 9, 2026 23:15
Copilot AI review requested due to automatic review settings April 9, 2026 23:15
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates Breadcrumbs to collapse on narrow viewports (≤544px) by hiding most crumbs and exposing only the prior crumb(s) as back-navigation links, with a new prop to control how many items remain visible.

Changes:

  • Add visibleItemsOnNarrow prop (default 1) and render-time data attributes to mark crumbs for narrow-viewport hiding.
  • Add narrow-viewport CSS rules to hide marked items and remove the trailing separator on the last visible item.
  • Add Storybook example + Playwright coverage for narrow vs wide behavior and custom visible counts.
Show a summary per file
File Description
packages/react/src/Breadcrumbs/Breadcrumbs.tsx Adds visibleItemsOnNarrow prop and wraps breadcrumb items with narrow-viewport data attributes.
packages/react/src/Breadcrumbs/Breadcrumbs.module.css Adds media-query styles to hide data-narrow-hidden items and suppress the last separator on narrow viewports.
packages/react/src/Breadcrumbs/Breadcrumbs.features.stories.tsx Adds a Storybook story demonstrating custom visibleItemsOnNarrow.
e2e/components/Breadcrumbs.test.ts Adds AVT coverage for narrow/wide behavior and custom narrow visible count.
.changeset/slow-sides-feel.md Announces the new visibleItemsOnNarrow prop as a minor change.

Copilot's findings

  • Files reviewed: 5/5 changed files
  • Comments generated: 5

const wrappedChildren = React.Children.map(children, child => <li className={classes.ItemWrapper}>{child}</li>)
const containerRef = useRef<HTMLElement>(null)
const childArray = useMemo(() => getValidChildren(children), [children])
const visibleCountOnNarrow = Math.max(1, Math.min(visibleItemsOnNarrow, childArray.length - 1))
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

visibleCountOnNarrow can become NaN if a consumer passes visibleItemsOnNarrow={NaN} (Math.min/Math.max will propagate NaN), which then causes all items to be treated as hidden on narrow viewports. Consider sanitizing visibleItemsOnNarrow with Number.isFinite (and/or an integer clamp) before computing visibleCountOnNarrow so invalid values fall back to the default behavior.

Suggested change
const visibleCountOnNarrow = Math.max(1, Math.min(visibleItemsOnNarrow, childArray.length - 1))
const sanitizedVisibleItemsOnNarrow = Number.isFinite(visibleItemsOnNarrow) ? visibleItemsOnNarrow : 1
const visibleCountOnNarrow = Math.max(1, Math.min(sanitizedVisibleItemsOnNarrow, childArray.length - 1))

Copilot uses AI. Check for mistakes.
Comment on lines +158 to +167
const applyNarrow = validChildren.length > 1
const isLast = index === validChildren.length - 1
const isVisibleOnNarrow = applyNarrow && index >= validChildren.length - 1 - visibleCountOnNarrow && !isLast
const isLastVisibleOnNarrow = applyNarrow && index === validChildren.length - 2
return (
<li
className={classes.ItemWrapper}
key={index}
data-narrow-hidden={isVisibleOnNarrow ? undefined : applyNarrow ? '' : undefined}
data-narrow-last={isLastVisibleOnNarrow ? '' : undefined}
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On narrow viewports the "current page" crumb is hidden via display: none (because the last item always gets data-narrow-hidden). This removes the aria-current="page" item from the accessibility tree, which can make the breadcrumb trail lose the current-location context for screen reader users. Consider keeping the current page accessible (e.g., visually-hidden rather than display:none, or alternative markup/ARIA so the current page is still conveyed).

Copilot uses AI. Check for mistakes.
Comment on lines 324 to 328
const finalChildren = React.useMemo(() => {
if (overflowMenuEnabled) {
if (overflow === 'wrap' || menuItems.length === 0) {
return React.Children.map(children, child => <li className={classes.ItemWrapper}>{child}</li>)
return wrapItemsWithNarrowAttrs(children, visibleCountOnNarrow)
}
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The narrow-viewport collapsing is only implemented for the wrap rendering path (ItemWrapper + data-narrow-*). When the overflow menu feature flag is enabled and overflow is menu/menu-with-root with menuItems.length > 0, the rendered <li>s use BreadcrumbsItem and never receive data-narrow-hidden/data-narrow-last, so the narrow collapse behavior won’t apply there. If the intent is for the narrow behavior to be consistent across overflow modes, consider applying the same narrow attributes (and CSS) to the BreadcrumbsItem render path as well.

Copilot uses AI. Check for mistakes.
Comment on lines +51 to +56
const items = page.locator('li')

// "Home" should be hidden, "About" (previous) visible, "Team" (current) hidden
await expect(items.nth(0)).toBeHidden()
await expect(items.nth(1)).toBeVisible()
await expect(items.nth(2)).toBeHidden()
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests use page.locator('li'), which isn’t scoped to the Breadcrumbs component and could become flaky if the story renders other lists (or if future Breadcrumbs variants render nested lists like overflow menus). Consider scoping to the Breadcrumbs nav/ol (e.g., page.getByRole('navigation', {name: 'Breadcrumbs'}).locator('li')) so the assertions only target the component under test.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Canary Release Apply this label when you want CI to create a canary release of the current PR integration-tests: recommended This change needs to be tested for breaking changes. See https://arc.net/l/quote/tdmpakpm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants