Breadcrumb
Cross-platform breadcrumb trail with width-aware collapse, sibling menus, JSON-LD schema, and an agent-friendly items API.
At a glance
- Two equivalent APIs:
<Breadcrumb items={[…]} />for terse, agent-friendly markup and a compoundBreadcrumb.List/Breadcrumb.Item/Breadcrumb.Link/Breadcrumb.Pageform for full JSX control. - Width-aware collapse on web AND native via
onLayout(RN-Web routes throughResizeObserver; native uses its own layout system). Middle items fold into an interactive ellipsis when the container can't fit the trail. On by default — passcollapseOnOverflow={false}to opt out. - Count-based collapse (
maxItems,itemsBeforeCollapse,itemsAfterCollapse) as a deterministic ceiling above width fit. expandBehavior:inline(web default) folds the trail back open;menu(native default) opens a popover with the hidden items;scrollfalls back to a horizontal scroller for IDE-style file paths;noneis purely visual.- Per-item icons, sibling menus (the VSCode/file-path pattern), label truncation, loading skeletons, and RTL chevron flip via
dir="rtl". - JSON-LD
BreadcrumbListstructured data is injected automatically on web for SEO + LLM ingest. SSR consumers should call the exportedgetBreadcrumbJsonLd(items)helper from their framework's metadata API instead. - Auto
aria-current="page"on the last item (or any item flaggedcurrent), with a visually-hidden "Current page:" prefix for screen readers. The wrapper is a real<nav>landmark with a localizedaria-label. - i18n hooks:
breadcrumb.ariaLabel,breadcrumb.expandLabel,breadcrumb.ellipsisLabel,breadcrumb.currentPageLabel,breadcrumb.siblingMenuLabel.
Preview
Custom separators
The default is a chevron that auto-flips for RTL. Pass any string, ReactNode, or (ctx) => ReactNode to customize.
With icons
Add a leading icon per item via the icon prop — sized to the line height. Any icon component with the shape ({ size?: number; color?: string }) => ReactNode works (lucide, custom SVG, your own icon set).
Count-based collapse
Set maxItems to fold the middle of the trail into an ellipsis. Click the ellipsis to expand inline (default on web).
Width-based collapse
Width-based collapse is on by default. The library renders a hidden measurement copy of every item via onLayout, then shows only the items that fit the container's available width — middle items fold into the ellipsis. Resize the container in the demo below to see it in action. Pass collapseOnOverflow={false} to opt out and let the row grow to its natural width (consider only when the parent provides its own scroll/clip handling).
Sibling menus (VSCode-style)
Pass a siblings array on any item to add a chevron toggle that opens a popover menu of sibling pages — useful for file paths or any breadcrumb where the user might want to jump laterally.
Compound API
For full JSX control, use the compound subcomponents. Separators auto-insert between consecutive Breadcrumb.Items unless you place your own.
SEO + LLM ingest
The component injects a BreadcrumbList JSON-LD document into <head> on the client when items is provided. For SSR-time emission (recommended for crawler reliability), use the helper:
Pass schemaOrg={false} on the component to opt out of the client-side injection if you're already emitting JSON-LD via your metadata pipeline.
Localization — ariaLabel, currentPageLabel, ellipsisLabel, expandLabel, siblingMenuLabel
Every user-visible string is overridable per-instance. Defaults come
from the active i18n dictionary (breadcrumb.* keys); pass props to
override one Breadcrumb without touching the global translations.
| Prop | Purpose |
|---|---|
ariaLabel | <nav> landmark label |
currentPageLabel | Visually-hidden prefix on the current item ("Current page:") |
ellipsisLabel | Accessible name for the collapsed-middle ellipsis |
expandLabel | Tooltip / aria-label on the click-to-expand affordance |
siblingMenuLabel | Accessible name for the sibling-pages chevron toggle |
separator
Customize the per-item separator. Accepts a string, a ReactNode, or a
function (ctx) => ReactNode that gets the surrounding item context.
Default is a chevron that flips for dir="rtl".
maxLabelLength
Cap individual item labels at N characters; the component truncates
with an ellipsis and exposes the full label on hover (web title)
and to assistive tech. Useful for file-path breadcrumbs where one
segment can be unboundedly long.
dir
rtl flips the chevron direction and the DOM order of the trail so
the start of the path sits on the right.
Props
Breadcrumb
| Prop | Type | Default | Description |
|---|---|---|---|
ariaLabel | string | — | Visible aria-label on the wrapping `<nav>`. @defaultValue translated "Breadcrumb" |
className | string | — | — |
collapseOnOverflow | boolean | — | Width-based collapse using `onLayout` (works on RN-Web via the built-in ResizeObserver shim and on native via the layout system). The library renders a hidden measurement copy of every item, then shows only the items that fit the container — middle items are folded into the ellipsis. Pass `false` to opt out and let the row grow to its natural width (it will overflow its parent if the parent does not provide its own scroll/clip handling). @defaultValue true |
currentPageLabel | string | — | Visually-hidden prefix announced before the current page's label. Helps screen readers convey "Current page: Settings" instead of "Settings". |
dir | enum | ltr | Reading direction. RTL flips the default chevron separator and the collapse logic so the start/end stay anchored to the right edge. @defaultValue 'ltr' |
ellipsisLabel | string | — | Override the default i18n string for the ellipsis SR label. |
expandBehavior | enum | — | What the ellipsis does when tapped/clicked. @defaultValue 'inline' on web, 'menu' on native |
expandLabel | string | — | Override the default i18n string for the "show full path" SR label. |
items | readonly BreadcrumbItemData[] | — | Items-array mode. When provided, `children` is ignored. |
itemsAfterCollapse | number | 1 | How many items at the END of the list stay visible when the middle collapses. @defaultValue 1 |
itemsBeforeCollapse | number | 1 | How many items at the START of the list stay visible when the middle collapses. @defaultValue 1 |
maxItems | number | — | Maximum number of visible items. The middle is collapsed into a single ellipsis; the first / last items are kept by default. Pass `0` or `undefined` to disable count-based collapse. |
maxLabelLength | number | 0 | Truncate each item's label after this many characters. Per-item `maxLabelLength` overrides this. @defaultValue 0 (no truncation) |
schemaOrg | boolean | — | Emit JSON-LD `BreadcrumbList` structured data for SEO + LLM ingest. Web only; ignored on native. @defaultValue true (only when `items` is provided AND on web) |
separator | BreadcrumbSeparatorValue | — | Visual separator between items. Strings render as plain text; nodes render as-is; functions receive `(ctx)` and return a node. @defaultValue a chevron glyph (auto-flips for RTL) |
siblingMenuLabel | string | — | Override the SR label for sibling menus opened from a crumb. |
testID | string | — | — |
Breadcrumb.List
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | — |
testID | string | — | — |
Breadcrumb.Item
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | — |
testID | string | — | — |
Breadcrumb.Link
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | — | — |
className | string | — | — |
href | string | — | — |
onPress | () => void | — | — |
testID | string | — | — |
Breadcrumb.Page
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | — |
testID | string | — | — |
Breadcrumb.Separator
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | — |
testID | string | — | — |
Breadcrumb.Ellipsis
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | — |
ellipsisLabel | string | — | — |
testID | string | — | — |