Skip to content

Breadcrumbs

Composed breadcrumbs (LAYOUT): renders the ui Breadcrumb primitive, adds a Home item, and emits schema.org BreadcrumbList JSON-LD for SEO. Takes a normalized trail so it stays domain-agnostic — the caller maps its own data to { name, href }; this package never fetches. Server-renderable so the JSON-LD lands in the initial HTML.

import { Breadcrumbs } from "@evolve-storefront/layout/breadcrumbs";

Preview

DefaultOpen in Storybook ↗

Usage

<Breadcrumbs
items={trail}
origin="https://shop.example"
renderLink={({ href, children, className }) => (
<Link href={href} className={className}>
{children}
</Link>
)}
/>;

Props

PropTypeDescription
itemsBreadcrumbTrailItem[]

The trail, ancestor → current. The last item renders as the current page.

home?BreadcrumbTrailItem | null

The leading Home item. Pass null to omit it; omit the prop for the default (localized "Home" → /).

origin?string

Site origin used to make JSON-LD item URLs absolute (required by Google Rich Results). Omit only if hrefs are already absolute.

renderLink?((props: BreadcrumbLinkRenderProps) => ReactNode)

Render an ancestor link with the app's router (e.g. Next Link). Defaults to a plain <a href> — this package references routes but owns no routing.

resolveHref?((href: string) => string)

The public path of a trail href, with its locale prefix — (href) => getPathname({ href, locale }). Feeds the JSON-LD item and the plain <a>; renderLink gets the raw href, which the app's router localizes.

Any other props go to the root element, like on a plain HTML element.

Examples

Long Trail
// A deep category path is the same call: the trail wraps, nothing is configured.
const trail = category.ancestors.map((ancestor) => ({ name: ancestor.name, href: ancestor.href }));
<Breadcrumbs items={trail} origin={origin} renderLink={renderLink} />;
Open in Storybook ↗
Single Item
// A top-level page: Home plus the current page.
<Breadcrumbs items={[{ name: t("account"), href: "/account" }]} origin={origin} renderLink={renderLink} />;
Open in Storybook ↗
No Home
// The account section starts its own trail, without the leading Home item.
<Breadcrumbs home={null} items={trail} origin={origin} renderLink={renderLink} />;
Open in Storybook ↗
LocalizedLocalized for crawlers too. resolveHref gives each trail href its locale prefix, so the JSON-LD item is the absolute URL a visitor actually loads — Home included, which lands on the locale root rather than /.
<Breadcrumbs
items={trail}
origin={origin}
resolveHref={(href) => getPathname({ href, locale })}
/>;
Open in Storybook ↗
Localized With Router LinksrenderLink gets the raw href. The app's router localizes it, so handing it the resolved one would prefix twice; only the JSON-LD reads resolveHref.
<Breadcrumbs
items={trail}
resolveHref={(href) => getPathname({ href, locale })}
renderLink={(props) => <Link {...props} />}
/>;
Open in Storybook ↗