nori-ui

Breadcrumb

Cross-platform breadcrumb trail with width-aware collapse, sibling menus, JSON-LD schema, and an agent-friendly items API.

9.3 kBgzipped

At a glance

  • Two equivalent APIs: <Breadcrumb items={[…]} /> for terse, agent-friendly markup and a compound Breadcrumb.List / Breadcrumb.Item / Breadcrumb.Link / Breadcrumb.Page form for full JSX control.
  • Width-aware collapse on web AND native via onLayout (RN-Web routes through ResizeObserver; native uses its own layout system). Middle items fold into an interactive ellipsis when the container can't fit the trail. On by default — pass collapseOnOverflow={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; scroll falls back to a horizontal scroller for IDE-style file paths; none is 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 BreadcrumbList structured data is injected automatically on web for SEO + LLM ingest. SSR consumers should call the exported getBreadcrumbJsonLd(items) helper from their framework's metadata API instead.
  • Auto aria-current="page" on the last item (or any item flagged current), with a visually-hidden "Current page:" prefix for screen readers. The wrapper is a real <nav> landmark with a localized aria-label.
  • i18n hooks: breadcrumb.ariaLabel, breadcrumb.expandLabel, breadcrumb.ellipsisLabel, breadcrumb.currentPageLabel, breadcrumb.siblingMenuLabel.

Preview

Direction:
Locale:

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).

Direction:
Locale:

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:

import { getBreadcrumbJsonLd } from '@nori-ui/core';
 
// Next.js App Router metadata
export async function generateMetadata() {
    return {
        other: {
            'application/ld+json': getBreadcrumbJsonLd([
                { label: 'Home', href: 'https://example.com/' },
                { label: 'Docs', href: 'https://example.com/docs' },
                { label: 'Breadcrumb' },
            ]),
        },
    };
}

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.

PropPurpose
ariaLabel<nav> landmark label
currentPageLabelVisually-hidden prefix on the current item ("Current page:")
ellipsisLabelAccessible name for the collapsed-middle ellipsis
expandLabelTooltip / aria-label on the click-to-expand affordance
siblingMenuLabelAccessible name for the sibling-pages chevron toggle
<Breadcrumb ariaLabel="Site navigation" items={[…]} />

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".

<Breadcrumb separator="/" items={…} />
<Breadcrumb separator={<SlashIcon />} items={…} />

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.

<Breadcrumb maxLabelLength={24} items={…} />

dir

rtl flips the chevron direction and the DOM order of the trail so the start of the path sits on the right.

<Breadcrumb dir="rtl" items={…} />

Props

PropTypeDefaultDescription
ariaLabelstringVisible aria-label on the wrapping `<nav>`. @defaultValue translated "Breadcrumb"
classNamestring
collapseOnOverflowbooleanWidth-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
currentPageLabelstringVisually-hidden prefix announced before the current page's label. Helps screen readers convey "Current page: Settings" instead of "Settings".
direnumltrReading direction. RTL flips the default chevron separator and the collapse logic so the start/end stay anchored to the right edge. @defaultValue 'ltr'
ellipsisLabelstringOverride the default i18n string for the ellipsis SR label.
expandBehaviorenumWhat the ellipsis does when tapped/clicked. @defaultValue 'inline' on web, 'menu' on native
expandLabelstringOverride the default i18n string for the "show full path" SR label.
itemsreadonly BreadcrumbItemData[]Items-array mode. When provided, `children` is ignored.
itemsAfterCollapsenumber1How many items at the END of the list stay visible when the middle collapses. @defaultValue 1
itemsBeforeCollapsenumber1How many items at the START of the list stay visible when the middle collapses. @defaultValue 1
maxItemsnumberMaximum 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.
maxLabelLengthnumber0Truncate each item's label after this many characters. Per-item `maxLabelLength` overrides this. @defaultValue 0 (no truncation)
schemaOrgbooleanEmit JSON-LD `BreadcrumbList` structured data for SEO + LLM ingest. Web only; ignored on native. @defaultValue true (only when `items` is provided AND on web)
separatorBreadcrumbSeparatorValueVisual 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)
siblingMenuLabelstringOverride the SR label for sibling menus opened from a crumb.
testIDstring
PropTypeDefaultDescription
classNamestring
testIDstring
PropTypeDefaultDescription
classNamestring
testIDstring
PropTypeDefaultDescription
asChildboolean
classNamestring
hrefstring
onPress() => void
testIDstring
PropTypeDefaultDescription
classNamestring
testIDstring
PropTypeDefaultDescription
classNamestring
testIDstring
PropTypeDefaultDescription
classNamestring
ellipsisLabelstring
testIDstring
Preview theme