Collapse strategy
strategy decides where the ellipsis appears when space runs out.
Collapses the middle — preserves both the root and the current page.
0px
React 19 · shadcn/ui · Tailwind CSS v4
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-breadcrumb01 — Playground
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
Each card demonstrates exactly one feature with its own resizable stage. All crumbs and menu entries are clickable — clicks surface as toasts.
strategy decides where the ellipsis appears when space runs out.
Collapses the middle — preserves both the root and the current page.
0px
preference is the tie-breaker when several collapsed layouts fit.
Hide as few crumbs as possible, even if they are wide.
0px
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.
When even a fully collapsed trail cannot fit, only the current page remains — guaranteed to never overflow.
fallbackAtWidth — disabled (automatic fallback only)
0px
allowMultipleEllipses + grouping let collapsed groups form around pinned crumbs (“v4.2” has canCollapse: false).
Any combination of collapsed groups — maximum flexibility.
0px
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.
showNextArrow appends a forward arrow after the current page, listing the pages one level deeper.
0px
Click the arrow after “Retrospective”.
alwaysShow pins a number of crumbs at each end; individual crumbs can also opt out with canCollapse: false.
Head crumbs
Tail crumbs
0px
forceCollapse pre-collapses matching crumbs even when there is room; itemPriority steers which crumbs disappear first.
Collapse first when space runs out
0px
Collapsing is the default, but the same component can fall back to native horizontal scrolling or multi-line wrapping.
0px
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.
While isLoading is true the breadcrumb renders the current title, a custom skeleton, or nothing at all.
0px
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
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
The component exposes its internals: measured widths, the collapsed ranges, truncation results and remaining space, streamed through onDebugStateChange on every layout pass.
0px
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
The full public surface of ResponsiveBreadcrumb, grouped by concern.
| Prop | Type | Default | Description |
|---|---|---|---|
| items | BreadcrumbData[] | — | Ordered crumbs from root to current page. |
| separatorNavItems | Record<string, SeparatorNavItem[]> | — | Sibling menus per separator, keyed by item key or "prev:next" pair. |
| nextItems | SeparatorNavItem[] | [] | Pages one level deeper, shown by the next-page arrow. |
| onItemClick | (item) => void | — | Fires for crumbs and menu entries. |
| Prop | Type | Default | Description |
|---|---|---|---|
| key / label / href | string / ReactNode / string? | — | Identity, content, and optional link target. |
| clickable / disabled | boolean | — | Interactive without a link / grayed out. |
| canCollapse | boolean | true (edges: false) | Whether the solver may hide this crumb. |
| canTruncate | boolean | true (last: false) | Whether truncation may shrink this crumb. |
| icon / customElement | ReactNode | — | Leading icon, or full custom content. |
| measureElement | ReactNode | — | Lightweight stand-in rendered in the hidden measurement tree. |
| Prop | Type | Default | Description |
|---|---|---|---|
| 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) => boolean | — | Pre-collapses matching crumbs even when everything fits. |
| itemPriority | (item, index) => number | — | Lower values collapse earlier. |
| allowMultipleEllipses | boolean | false | Allow 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. |
| Prop | Type | Default | Description |
|---|---|---|---|
| enableTruncation | boolean | false | Shrink wide labels before collapsing. |
| truncateMinWidth / truncateMaxWidth | number | 60 / 200 | Bounds for a truncated label's width (px). |
| truncateThreshold | number | 100 | Only labels wider than this are candidates. |
| truncateOrder | "biggest-first" | "smallest-first" | "biggest-first" | Which candidates shrink first. |
| showTooltipOnTruncate | boolean | true | Full label in a tooltip when truncated. |
| Prop | Type | Default | Description |
|---|---|---|---|
| titleOnlyFallback | ReactNode | last item label | Content of the title-only fallback. |
| titleOnlyIcon / titleOnlyCustomElement | ReactNode | — | Icon or full custom title-only content. |
| fallbackAtWidth | number | — | Force title-only at or below this container width. |
| isLoading | boolean | false | Switches to the loading fallback. |
| loadingFallback | "title" | "custom" | "none" | "none" | What renders while loading. |
| customLoadingFallback | ReactNode | — | Custom loading content (e.g. a skeleton). |
| Prop | Type | Default | Description |
|---|---|---|---|
| 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. |
| clickableLeftOfEllipsis | boolean | false | Keep the separator before an ellipsis interactive. |
| showNextArrow | boolean | false | Forward arrow after the current page. |
| showCollapsedCount | boolean | false | Badge with the number of hidden crumbs. |
| collapsedCountPlacement | "inline" | "outside" | "outside" | Place the count inside the ellipsis button or floating beside it. |
| customEllipsisElement | ReactNode | — | Custom ellipsis trigger content. |
| lockOnOverlayOpen | boolean | true | Freeze measurements while a popover/drawer is open. |
| Prop | Type | Default | Description |
|---|---|---|---|
| renderItem | (ctx) => ReactNode | — | Custom crumb content — receives mode: visible | measure | menu. |
| renderSeparator | (prevKey, nextKey) => ReactNode | — | Custom decorative separator. |
| renderEllipsis / renderTitleOnly | (ctx) => ReactNode | — | Custom ellipsis trigger / title-only content. |
| renderMenuItem | (ctx) => ReactNode | — | Custom overlay menu rows. |
| renderItemLink / renderMenuLink | (ctx) => ReactNode | — | Wrap links with your router's Link component. |
| showHomeIcon | boolean | true | Home icon on the first crumb. |
| lastItemClickable | boolean | false | Make the current page interactive. |
| Prop | Type | Default | Description |
|---|---|---|---|
| strings | Partial<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 mode | Focus style that survives clipped containers. |
| schema | "json-ld" | "microdata" | "none" | "json-ld" | Schema.org BreadcrumbList output. |
| Prop | Type | Default | Description |
|---|---|---|---|
| debug | boolean | false | Draw measurement outlines. |
| onDebugStateChange | (state: BreadcrumbDebugState) => void | — | Stream solver internals: widths, ranges, remaining space… |