Skip to content
Twilight React Playground
ثيم رائدaren

Breadcrumb

componentBeginnerserverbrowserlive demo

Draws a page's breadcrumb trail from its loader data, with structured data for search engines, unless the merchant turned breadcrumbs off.

import { Breadcrumb } from '@salla.sa/twilight-theme-engine/components/common';

In plain words

Breadcrumbs are the "Home › Chairs › Wooden chair" trail at the top of a page. Give Breadcrumb the page object your route's loader returned (the function that fetches a page's data before it shows), and it draws the trail as links.

It also writes a hidden description of the trail that search engines read, and it hides itself when the merchant switched breadcrumbs off in the theme settings.

Signature

const Breadcrumb: LazyExoticComponent<(props: BreadcrumbProps) => JSX.Element | null>

// BreadcrumbProps is not exported
interface BreadcrumbProps {
  page?: Page | null;   // the page object a route loader returns
  className?: string;   // replaces 'breadcrumbs w-full py-5' on the <nav>
}

Try it live

Breadcrumb for a page object like a route loader returns. The trail's links point at pages of these docs.Try this: raise the crumbs to 5: the middle collapses behind a ••• button. Set it to 0 for the Home plus title fallback, then open the JSON-LD: each URL is store.url plus the crumb path, double slash included.
Storefront canvas · ar · RTL
The JSON-LD it also rendered, for search engines
(nothing: the trail is empty)
Controls
0 sends no page.breadcrumbs at all.
What a theme writes
import { Breadcrumb } from '@salla.sa/twilight-theme-engine/components/common';
import type { Page } from '@salla.sa/twilight-theme-engine/types';

// `page` is what the route loader returned, e.g.
// { title: 'Breadcrumb', slug: 'page-single',
//   breadcrumbs: [{ name: 'Link', url: '/playground/reference/components/link' },
//     { name: 'Image', url: '/playground/reference/components/image' },
//     { name: 'Breadcrumb', url: '/playground/reference/components/breadcrumb' }] }
export function PageTop({ page }: { page: Page }) {
  return <Breadcrumb page={page} />;
}

Example

app/components/PageTop.tsx
import { Breadcrumb } from '@salla.sa/twilight-theme-engine/components/common';
import type { Page } from '@salla.sa/twilight-theme-engine/types';

export function PageTop({ page }: { page: Page }) {
  return (
    <div className="container">
      <Breadcrumb page={page} />
      <h1>{page.title}</h1>
    </div>
  );
}

How it behaves

  • The trail is useBreadcrumbs(page): page.breadcrumbs when the loader sent any, otherwise Home plus the page title, and nothing on the home page or without a page.

  • Markup: <nav aria-label="Breadcrumb"> around <ol className="s-breadcrumb-wrapper">, with schema.org microdata. Every crumb but the last is an engine Link followed by a chevron; the last is plain text with aria-current="page".

  • More than 4 crumbs collapse to the first, a "•••" button and the last two. The button expands the trail; a new trail collapses it again.

  • It also renders a <script type="application/ld+json"> BreadcrumbList. Each URL is store.url followed by the crumb's url, unless that already starts with http; the last item uses @id instead of item.

  • It renders nothing when the theme setting is_breadcrumbs_enabled is false. A store that never saved the setting shows breadcrumbs.

  • It is lazy (code-split), like NoContent, RenderWhenVisible, CurrencySymbol and ErrorPage: the first render suspends while its code loads.

Gotchas

  • docs/23-breadcrumb-system.md imports BreadcrumbTrail and BreadcrumbJsonLd from @salla.sa/twilight-theme-engine/components/common. Neither is exported, so that import fails. For custom markup, build on useBreadcrumbs from @salla.sa/twilight-theme-engine/hooks.

  • Rendering it records the page in sessionStorage (breadcrumb-referrer), and the next product page shows that entry as its middle crumb. A Breadcrumb for something that is not a real page (a modal, a preview panel) puts a wrong crumb on product pages.

  • The structured data joins text. store.url can end in / (the demo store's is https://demostore.salla.sa/ar/dev-vgckq3fssfhjewwi/), and then a relative crumb such as Home (/) becomes …/dev-vgckq3fssfhjewwi//. Crumbs built from API url fields are absolute and unaffected.

  • A page object built during render is new every time, and both the trail and the referrer effect depend on that object: each re-render rewrites sessionStorage and collapses an expanded trail. Loader data is stable; memoise hand-built pages with useMemo.

Related

Source and docs