Skip to main content
Gremorie

Breadcrumb

Hierarchical trail showing the user's path. Semantic nav with explicit terminal page and optional collapse.

Overview

Breadcrumb is the hierarchical-trail primitive: a <nav> wrapping an ordered list that shows where the user is in the site or app, one segment per ancestor. The trail terminates explicitly with <BreadcrumbPage> (a non-link span carrying aria-current="page"), making the current location unambiguous to readers and screen readers alike.

Reach for Breadcrumb only on deep hierarchies (three levels or more). Flat sites pay the visual noise cost without a payoff. When the middle of a long trail crowds the layout, collapse it with <BreadcrumbEllipsis> paired with a Popover or DropdownMenu listing the hidden segments.

Preview

'use client';import {  Breadcrumb,  BreadcrumbEllipsis,  BreadcrumbItem,  BreadcrumbLink,  BreadcrumbList,  BreadcrumbPage,  BreadcrumbSeparator,} from '@gremorie/rx-navigation';export function BreadcrumbPreview() {  return (    <Breadcrumb>      <BreadcrumbList>        <BreadcrumbItem>          <BreadcrumbLink href="#">Docs</BreadcrumbLink>        </BreadcrumbItem>        <BreadcrumbSeparator />        <BreadcrumbItem>          <BreadcrumbLink href="#">Components</BreadcrumbLink>        </BreadcrumbItem>        <BreadcrumbSeparator />        <BreadcrumbItem>          <BreadcrumbEllipsis />        </BreadcrumbItem>        <BreadcrumbSeparator />        <BreadcrumbItem>          <BreadcrumbPage>Breadcrumb</BreadcrumbPage>        </BreadcrumbItem>      </BreadcrumbList>    </Breadcrumb>  );}

Anatomy

Breadcrumb                     <nav aria-label="breadcrumb"> wrapper
└─ BreadcrumbList              <ol> row of segments
   ├─ BreadcrumbItem           one segment cell
   │  ├─ BreadcrumbLink        navigable ancestor link (asChild swaps the tag)
   │  ├─ BreadcrumbPage        terminal current page (not a link)
   │  └─ BreadcrumbEllipsis    collapsed-middle indicator, paired with a menu
   └─ BreadcrumbSeparator      divider between segments (defaults to a chevron)

Installation

bash npx gremorie@latest add rx-breadcrumb
bash pnpm dlx gremorie@latest add rx-breadcrumb
bash yarn dlx gremorie@latest add rx-breadcrumb

bash bunx --bun gremorie@latest add rx-breadcrumb

Usage

import {
  Breadcrumb,
  BreadcrumbList,
  BreadcrumbItem,
  BreadcrumbLink,
  BreadcrumbPage,
  BreadcrumbSeparator,
} from "@gremorie/rx-navigation";

export function DocsCrumbs() {
  return (
    <Breadcrumb>
      <BreadcrumbList>
        <BreadcrumbItem>
          <BreadcrumbLink href="/docs">Docs</BreadcrumbLink>
        </BreadcrumbItem>
        <BreadcrumbSeparator />
        <BreadcrumbItem>
          <BreadcrumbLink href="/docs/components">Components</BreadcrumbLink>
        </BreadcrumbItem>
        <BreadcrumbSeparator />
        <BreadcrumbItem>
          <BreadcrumbPage>Breadcrumb</BreadcrumbPage>
        </BreadcrumbItem>
      </BreadcrumbList>
    </Breadcrumb>
  );
}

The Angular edition of this component ships from source today (see the workbench for the side-by-side); its registry entry is coming next.

API

Renders a <nav aria-label="breadcrumb">.

PropTypeDefaultDescription
...propsReact.ComponentProps<"nav">-Standard nav attributes. The aria-label="breadcrumb" is set automatically.

Renders an <ol> with flex-wrap and subtle gap.

PropTypeDefaultDescription
...propsReact.ComponentProps<"ol">-Standard ol attributes.

Renders an <li> with inline-flex items-center gap-1.5.

PropTypeDefaultDescription
...propsReact.ComponentProps<"li">-Standard li attributes.

The clickable ancestor segment. Renders an <a> by default; pass asChild to delegate rendering to a routing component (Next.js Link, React Router Link).

PropTypeDefaultDescription
asChildbooleanfalseWhen true, renders into the single child element via Radix Slot. Use with framework Link components.
...propsReact.ComponentProps<"a">-Standard anchor attributes, including href.

The terminal segment - the current page. Renders a <span> with role="link", aria-disabled="true", and aria-current="page". Not interactive.

PropTypeDefaultDescription
...propsReact.ComponentProps<"span">-Standard span attributes.

The visual divider between segments. Renders an <li role="presentation" aria-hidden="true"> containing a ChevronRight by default. Override by passing children.

PropTypeDefaultDescription
childrenReact.ReactNode<ChevronRight />Custom separator content (e.g. a slash, a different icon).
...propsReact.ComponentProps<"li">-Standard li attributes.

Placeholder for collapsed middle segments. Renders a 36 by 36 px square containing a MoreHorizontal icon and a visually hidden "More" label. Wrap inside a Popover or DropdownMenu trigger to reveal the hidden segments.

PropTypeDefaultDescription
...propsReact.ComponentProps<"span">-Standard span attributes.

Composition

  1. <Breadcrumb> is the semantic nav landmark.
  2. <BreadcrumbList> is the ordered list of segments.
  3. Each segment is a <BreadcrumbItem>, alternating with <BreadcrumbSeparator>.
  4. Ancestors use <BreadcrumbLink>; the current page uses <BreadcrumbPage> (never a link).
  5. Collapsed middle segments become <BreadcrumbEllipsis>, optionally as the trigger of an overlay listing the hidden items.

Separators are siblings of items inside the list, not children of items, so screen readers walk the trail cleanly.

Variations

Simple chain

<Breadcrumb>
  <BreadcrumbList>
    <BreadcrumbItem>
      <BreadcrumbLink href="/">Home</BreadcrumbLink>
    </BreadcrumbItem>
    <BreadcrumbSeparator />
    <BreadcrumbItem>
      <BreadcrumbLink href="/settings">Settings</BreadcrumbLink>
    </BreadcrumbItem>
    <BreadcrumbSeparator />
    <BreadcrumbItem>
      <BreadcrumbPage>Account</BreadcrumbPage>
    </BreadcrumbItem>
  </BreadcrumbList>
</Breadcrumb>

Use for shallow hierarchies (three to four levels) where every ancestor fits on a single line.

With ellipsis collapse

<Breadcrumb>
  <BreadcrumbList>
    <BreadcrumbItem>
      <BreadcrumbLink href="/docs">Docs</BreadcrumbLink>
    </BreadcrumbItem>
    <BreadcrumbSeparator />
    <BreadcrumbItem>
      <BreadcrumbEllipsis />
    </BreadcrumbItem>
    <BreadcrumbSeparator />
    <BreadcrumbItem>
      <BreadcrumbLink href="/docs/components">Components</BreadcrumbLink>
    </BreadcrumbItem>
    <BreadcrumbSeparator />
    <BreadcrumbItem>
      <BreadcrumbPage>Breadcrumb</BreadcrumbPage>
    </BreadcrumbItem>
  </BreadcrumbList>
</Breadcrumb>

Use when the chain is long enough to wrap awkwardly. The ellipsis announces "More" to assistive tech and signals truncation to sighted users.

With dropdown collapse

'use client';import {  Breadcrumb,  BreadcrumbEllipsis,  BreadcrumbItem,  BreadcrumbLink,  BreadcrumbList,  BreadcrumbPage,  BreadcrumbSeparator,} from '@gremorie/rx-navigation';import {  DropdownMenu,  DropdownMenuContent,  DropdownMenuItem,  DropdownMenuTrigger,} from '@gremorie/rx-overlays';export function BreadcrumbDropdownPreview() {  return (    <Breadcrumb>      <BreadcrumbList>        <BreadcrumbItem>          <BreadcrumbLink href="#">Docs</BreadcrumbLink>        </BreadcrumbItem>        <BreadcrumbSeparator />        <BreadcrumbItem>          <DropdownMenu>            <DropdownMenuTrigger className="flex items-center gap-1">              <BreadcrumbEllipsis />              <span className="sr-only">Toggle menu</span>            </DropdownMenuTrigger>            <DropdownMenuContent align="start">              <DropdownMenuItem>Components</DropdownMenuItem>              <DropdownMenuItem>Navigation</DropdownMenuItem>              <DropdownMenuItem>Overlays</DropdownMenuItem>            </DropdownMenuContent>          </DropdownMenu>        </BreadcrumbItem>        <BreadcrumbSeparator />        <BreadcrumbItem>          <BreadcrumbPage>Breadcrumb</BreadcrumbPage>        </BreadcrumbItem>      </BreadcrumbList>    </Breadcrumb>  );}

Wrap a <BreadcrumbEllipsis> in a DropdownMenu trigger to make the collapsed middle operable. The menu lists the hidden ancestors so users can jump to any of them.

With custom separator

'use client';import {  Breadcrumb,  BreadcrumbItem,  BreadcrumbLink,  BreadcrumbList,  BreadcrumbPage,  BreadcrumbSeparator,} from '@gremorie/rx-navigation';import { SlashIcon } from 'lucide-react';export function BreadcrumbSeparatorPreview() {  return (    <Breadcrumb>      <BreadcrumbList>        <BreadcrumbItem>          <BreadcrumbLink href="#">Home</BreadcrumbLink>        </BreadcrumbItem>        <BreadcrumbSeparator>          <SlashIcon />        </BreadcrumbSeparator>        <BreadcrumbItem>          <BreadcrumbLink href="#">Settings</BreadcrumbLink>        </BreadcrumbItem>        <BreadcrumbSeparator>          <SlashIcon />        </BreadcrumbSeparator>        <BreadcrumbItem>          <BreadcrumbPage>Account</BreadcrumbPage>        </BreadcrumbItem>      </BreadcrumbList>    </Breadcrumb>  );}

Pass children to <BreadcrumbSeparator> to swap the default chevron for a slash, dot, or any icon. Keep separators short (a single character or icon) so the trail stays scannable.

Accessibility

  • Landmark: the outer <nav> carries aria-label="breadcrumb", making the trail a discoverable landmark for screen reader users.
  • Current page: <BreadcrumbPage> sets aria-current="page" so assistive tech announces the user's location explicitly. Never wrap the current page in <BreadcrumbLink>.
  • Separators: <BreadcrumbSeparator> is aria-hidden="true" and role="presentation" - the trail reads as "Docs, Components, Breadcrumb" without the chevrons.
  • Ellipsis: <BreadcrumbEllipsis> exposes a visually hidden "More" label so screen readers announce the collapsed segment. Wrap it in a Popover or DropdownMenu trigger to make it operable.
  • Keyboard: links are reachable in order with Tab. The current page is not focusable.
  • NavigationMenu - primary site navigation with rich panels, not a back-trace.
  • Tabs - sibling content panels within one page.
  • Popover - common host for an ellipsis collapse menu.

On this page