Siteplane UI

Breadcrumb

Show the current location within a navigation hierarchy.

Markdown
"use client";

import { FolderIcon } from "lucide-react";
import {
  Breadcrumb,
  BreadcrumbEllipsis,
  BreadcrumbItem,
  BreadcrumbLink,
  BreadcrumbList,
  BreadcrumbPage,
  BreadcrumbSeparator,
} from "@/siteplane/components/breadcrumb";
import { Button } from "@/siteplane/components/button";
import {
  Menu,
  MenuLinkItem,
  MenuPopup,
  MenuTrigger,
} from "@/siteplane/components/menu";

export default function Example() {
  return (
    <Breadcrumb>
      <BreadcrumbList>
        <BreadcrumbItem>
          <BreadcrumbLink href="#workspace">Workspace</BreadcrumbLink>
        </BreadcrumbItem>
        <BreadcrumbSeparator />
        <BreadcrumbItem>
          <Menu>
            <MenuTrigger
              aria-label="Show hidden levels"
              render={
                <Button profile="inline" profileTone="muted" variant="text" />
              }
            >
              <BreadcrumbEllipsis />
            </MenuTrigger>
            <MenuPopup align="start">
              <MenuLinkItem href="#projects">
                <FolderIcon />
                Projects
              </MenuLinkItem>
              <MenuLinkItem href="#marketing">
                <FolderIcon />
                Marketing
              </MenuLinkItem>
            </MenuPopup>
          </Menu>
        </BreadcrumbItem>
        <BreadcrumbSeparator />
        <BreadcrumbItem>
          <BreadcrumbLink href="#website">Website</BreadcrumbLink>
        </BreadcrumbItem>
        <BreadcrumbSeparator />
        <BreadcrumbItem>
          <BreadcrumbPage>Pricing</BreadcrumbPage>
        </BreadcrumbItem>
      </BreadcrumbList>
    </Breadcrumb>
  );
}

Installation

pnpm dlx shadcn@4.18.0 add @siteplane/breadcrumb

Complete the one-time setup first. Registry JSON lists source files and dependencies.

For this page’s examples, also install:

pnpm dlx shadcn@4.18.0 add @siteplane/button @siteplane/menu

Usage

import {
  Breadcrumb,
  BreadcrumbList,
  BreadcrumbItem,
  BreadcrumbLink,
  BreadcrumbPage,
  BreadcrumbSeparator,
} from "@/siteplane/components/breadcrumb";

<Breadcrumb>
  <BreadcrumbList>
    <BreadcrumbItem>
      <BreadcrumbLink href="#home">Workspace</BreadcrumbLink>
    </BreadcrumbItem>
    <BreadcrumbSeparator />
    <BreadcrumbItem>
      <BreadcrumbLink href="#projects">Projects</BreadcrumbLink>
    </BreadcrumbItem>
    <BreadcrumbSeparator />
    <BreadcrumbItem>
      <BreadcrumbPage>Website</BreadcrumbPage>
    </BreadcrumbItem>
  </BreadcrumbList>
</Breadcrumb>;

Composition

Breadcrumb
└── BreadcrumbList
    ├── BreadcrumbItem → BreadcrumbLink or BreadcrumbPage
    ├── BreadcrumbSeparator
    └── BreadcrumbItem → BreadcrumbEllipsis

Custom separator

Pass children to replace the default chevron.

"use client";

import {
  Breadcrumb,
  BreadcrumbItem,
  BreadcrumbLink,
  BreadcrumbList,
  BreadcrumbPage,
  BreadcrumbSeparator,
} from "@/siteplane/components/breadcrumb";

export default function Example() {
  return (
    <Breadcrumb>
      <BreadcrumbList>
        <BreadcrumbItem>
          <BreadcrumbLink href="#home">Workspace</BreadcrumbLink>
        </BreadcrumbItem>
        <BreadcrumbSeparator>/</BreadcrumbSeparator>
        <BreadcrumbItem>
          <BreadcrumbLink href="#projects">Projects</BreadcrumbLink>
        </BreadcrumbItem>
        <BreadcrumbSeparator>/</BreadcrumbSeparator>
        <BreadcrumbItem>
          <BreadcrumbPage>Website</BreadcrumbPage>
        </BreadcrumbItem>
      </BreadcrumbList>
    </Breadcrumb>
  );
}

Collapsed path

BreadcrumbEllipsis is a decorative placeholder for omitted levels. If people need to reach them, use a labeled menu trigger as in the first example. Its trigger is a text Button with profile="inline" and profileTone="muted", which keeps the bare look and hover of the links.

"use client";

import {
  Breadcrumb,
  BreadcrumbEllipsis,
  BreadcrumbItem,
  BreadcrumbLink,
  BreadcrumbList,
  BreadcrumbPage,
  BreadcrumbSeparator,
} from "@/siteplane/components/breadcrumb";

export default function Example() {
  return (
    <Breadcrumb>
      <BreadcrumbList>
        <BreadcrumbItem>
          <BreadcrumbLink href="#workspace">Workspace</BreadcrumbLink>
        </BreadcrumbItem>
        <BreadcrumbSeparator />
        <BreadcrumbItem>
          <BreadcrumbEllipsis />
        </BreadcrumbItem>
        <BreadcrumbSeparator />
        <BreadcrumbItem>
          <BreadcrumbLink href="#website">Website</BreadcrumbLink>
        </BreadcrumbItem>
        <BreadcrumbSeparator />
        <BreadcrumbItem>
          <BreadcrumbPage>Pricing</BreadcrumbPage>
        </BreadcrumbItem>
      </BreadcrumbList>
    </Breadcrumb>
  );
}

API reference

Component properties
PropTypeDefaultDescription
Breadcrumbnav propsaria-label: "breadcrumb"Navigation landmark; override the label for multiple trails.
BreadcrumbList / BreadcrumbItemol / li props—Ordered list and link or page item.
BreadcrumbLinkuseRender.ComponentProps<"a">ahref and native anchor props; render supports router links.
BreadcrumbPagespan propsaria-current: "page"Current location, not a link. Stays on one line and ends with an ellipsis when the trail has no room; plain text keeps its full value in title unless you pass one.
BreadcrumbSeparator.childrenReactNodeChevronRightIconDecorative list item with role presentation and aria-hidden. The default chevron mirrors in a right-to-left page.
BreadcrumbEllipsisspan propsMoreHorizontalIconDecorative omitted path indicator in the muted link color, not a button. Inside a menu trigger it turns to the link hover color on hover and while the menu is open.

Read the installed source.

Usage notes

Keep separators as list children, outside BreadcrumbItem. Use real destination URLs in your application. These examples use fragment destinations to keep the preview local.

A trail wraps onto more lines where it has no room, and a long link wraps inside its level. The current page stays on one line and ends with an ellipsis instead. In a Dashboard Shell header, which is one line, the trail keeps one row: its links end with an ellipsis as well.

In a right-to-left page the levels run from right to left and the default chevron points to the left. A separator you pass as children keeps its own glyph.