React 19 · shadcn/ui · Tailwind CSS v4

The breadcrumb that always fits.

ResponsiveBreadcrumb measures its real rendered DOM, solves the best layout in a single pass, then truncates, collapses, or falls back to a title — it never overflows, at any container width.

$ bunx shadcn@latest add Fefedu973/responsive-breadcrumb/responsive-breadcrumb
  • Real DOM measurement
  • Single-pass layout solver
  • Popover → drawer on mobile
  • Truncation before collapse
  • RTL & localization
  • Schema.org built in

01 — Playground

Try every prop, live

One breadcrumb, all the main options. Drag the handle or press play to watch it truncate, collapse into ellipsis menus, and finally fall back to a single title.

0px

Drag the handle, press play, or tab to the handle and use the arrow keys. Click the ellipsis and chevrons to open the overlay menus — a drawer replaces the popover on small screens.

02 — Features

Every capability, isolated

Each card demonstrates exactly one feature with its own resizable stage. All crumbs and menu entries are clickable — clicks surface as toasts.

Collapse strategy

strategy decides where the ellipsis appears when space runs out.

Collapses the middle — preserves both the root and the current page.

0px

Fit preference

preference is the tie-breaker when several collapsed layouts fit.

Hide as few crumbs as possible, even if they are wide.

0px

Label truncation

enableTruncation shrinks wide labels before anything gets collapsed.

Minimum label width — 60px

Truncation order

0px

Hover a truncated label to read the full text in a tooltip.

Title-only fallback

When even a fully collapsed trail cannot fit, only the current page remains — guaranteed to never overflow.

fallbackAtWidth — disabled (automatic fallback only)

0px

Multiple ellipses

allowMultipleEllipses + grouping let collapsed groups form around pinned crumbs (“v4.2” has canCollapse: false).

Any combination of collapsed groups — maximum flexibility.

0px

Separator tree menus

separatorNavItems turns separators into sibling menus — navigate sideways through the hierarchy, like a file tree.

Menu anchors to

Include current item in menu

0px

Click a chevron between two crumbs to list the sibling pages.

Next-page arrow

showNextArrow appends a forward arrow after the current page, listing the pages one level deeper.

0px

Click the arrow after “Retrospective”.

Pinned head & tail

alwaysShow pins a number of crumbs at each end; individual crumbs can also opt out with canCollapse: false.

Head crumbs

1

Tail crumbs

2

0px

Forced collapse & priorities

forceCollapse pre-collapses matching crumbs even when there is room; itemPriority steers which crumbs disappear first.

Collapse first when space runs out

0px

Overflow behavior

Collapsing is the default, but the same component can fall back to native horizontal scrolling or multi-line wrapping.

0px

RTL & localization

direction flips the layout for right-to-left scripts, and strings localizes every visible and ARIA label.

0px

Shrink the stage and open the ellipsis — the overlay title is localized too.

Loading state

While isLoading is true the breadcrumb renders the current title, a custom skeleton, or nothing at all.

0px

Custom rendering

Every part is a render prop: items, separators, ellipsis, menus and links. The hidden measurement tree uses the same renderers, so custom markup stays pixel-accurate.

renderSeparator + renderEllipsis

0px

renderItem

0px

SEO & accessibility

Schema.org structured data (JSON-LD or microdata) ships with the component, and the focus ring style adapts to clipped containers.

Structured data

Focus ring

0px

Emitted <script type="application/ld+json"> (server-rendered)

{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {
      "@type": "ListItem",
      "position": 1,
      "name": "Home",
      "item": "/"
    },
    {
      "@type": "ListItem",
      "position": 2,
      "name": "Documentation",
      "item": "/docs"
    },
    {
      "@type": "ListItem",
      "position": 3,
      "name": "Components",
      "item": "/docs/components"
    },
    {
      "@type": "ListItem",
      "position": 4,
      "name": "Navigation",
      "item": "/docs/components/navigation"
    },
    {
      "@type": "ListItem",
      "position": 5,
      "name": "Responsive Breadcrumb"
    }
  ]
}

Press Tab to walk the links and compare the focus ring styles.

03 — Inspector

See what the solver sees

The component exposes its internals: measured widths, the collapsed ranges, truncation results and remaining space, streamed through onDebugStateChange on every layout pass.

0px

Waiting for the first measurement…

The colored outlines mark what the component measures: items (green), separators (gray), the ellipsis (yellow), and the list container (blue). Everything in the panel above streams from the debug + onDebugStateChange props.

04 — API

Props reference

The full public surface of ResponsiveBreadcrumb, grouped by concern.

Data

PropTypeDefaultDescription
itemsBreadcrumbData[]Ordered crumbs from root to current page.
separatorNavItemsRecord<string, SeparatorNavItem[]>Sibling menus per separator, keyed by item key or "prev:next" pair.
nextItemsSeparatorNavItem[][]Pages one level deeper, shown by the next-page arrow.
onItemClick(item) => voidFires for crumbs and menu entries.

Item shape (BreadcrumbData)

PropTypeDefaultDescription
key / label / hrefstring / ReactNode / string?Identity, content, and optional link target.
clickable / disabledbooleanInteractive without a link / grayed out.
canCollapsebooleantrue (edges: false)Whether the solver may hide this crumb.
canTruncatebooleantrue (last: false)Whether truncation may shrink this crumb.
icon / customElementReactNodeLeading icon, or full custom content.
measureElementReactNodeLightweight stand-in rendered in the hidden measurement tree.

Collapse

PropTypeDefaultDescription
strategy"start" | "center" | "end" | "none""start"Where the collapsed range is placed.
preference"minimize-count" | "minimize-visibility" | "none""none"Tie-breaker between fitting layouts.
alwaysShow{ head?, tail? }{ head: 1, tail: 1 }Crumbs pinned at each end.
forceCollapse(item, index) => booleanPre-collapses matching crumbs even when everything fits.
itemPriority(item, index) => numberLower values collapse earlier.
allowMultipleEllipsesbooleanfalseAllow several collapsed groups. Requires grouping ≠ "contiguous".
grouping"contiguous" | "smart" | "free""contiguous"How collapsed groups may form.
overflowBehavior"collapse" | "scroll" | "wrap""collapse"Solver-driven collapse, or native scroll / wrap.

Truncation

PropTypeDefaultDescription
enableTruncationbooleanfalseShrink wide labels before collapsing.
truncateMinWidth / truncateMaxWidthnumber60 / 200Bounds for a truncated label's width (px).
truncateThresholdnumber100Only labels wider than this are candidates.
truncateOrder"biggest-first" | "smallest-first""biggest-first"Which candidates shrink first.
showTooltipOnTruncatebooleantrueFull label in a tooltip when truncated.

Fallbacks & loading

PropTypeDefaultDescription
titleOnlyFallbackReactNodelast item labelContent of the title-only fallback.
titleOnlyIcon / titleOnlyCustomElementReactNodeIcon or full custom title-only content.
fallbackAtWidthnumberForce title-only at or below this container width.
isLoadingbooleanfalseSwitches to the loading fallback.
loadingFallback"title" | "custom" | "none""none"What renders while loading.
customLoadingFallbackReactNodeCustom loading content (e.g. a skeleton).

Menus & overlays

PropTypeDefaultDescription
separatorNavSide"right" | "left""right"Which neighbor a separator menu belongs to.
showCurrentInNav"never" | "with-others" | "always""never"Include the anchor item in its own menu.
clickableLeftOfEllipsisbooleanfalseKeep the separator before an ellipsis interactive.
showNextArrowbooleanfalseForward arrow after the current page.
showCollapsedCountbooleanfalseBadge with the number of hidden crumbs.
collapsedCountPlacement"inline" | "outside""outside"Place the count inside the ellipsis button or floating beside it.
customEllipsisElementReactNodeCustom ellipsis trigger content.
lockOnOverlayOpenbooleantrueFreeze measurements while a popover/drawer is open.

Rendering

PropTypeDefaultDescription
renderItem(ctx) => ReactNodeCustom crumb content — receives mode: visible | measure | menu.
renderSeparator(prevKey, nextKey) => ReactNodeCustom decorative separator.
renderEllipsis / renderTitleOnly(ctx) => ReactNodeCustom ellipsis trigger / title-only content.
renderMenuItem(ctx) => ReactNodeCustom overlay menu rows.
renderItemLink / renderMenuLink(ctx) => ReactNodeWrap links with your router's Link component.
showHomeIconbooleantrueHome icon on the first crumb.
lastItemClickablebooleanfalseMake the current page interactive.

Accessibility, i18n & SEO

PropTypeDefaultDescription
stringsPartial<ResponsiveBreadcrumbStrings>Localize every visible and ARIA label.
direction"ltr" | "rtl" | "auto""auto"Layout direction; auto reads the document.
focusRing"inset" | "outer" | "clip-margin" | "none""inset" in collapse modeFocus style that survives clipped containers.
schema"json-ld" | "microdata" | "none""json-ld"Schema.org BreadcrumbList output.

Debugging

PropTypeDefaultDescription
debugbooleanfalseDraw measurement outlines.
onDebugStateChange(state: BreadcrumbDebugState) => voidStream solver internals: widths, ranges, remaining space…