Breadcrumbs
Render a Linear-style breadcrumb trail with links, dropdown menus, and Home/Back controls.
Breadcrumbs is a client component that renders a data-driven breadcrumb trail for the Next.js App Router. Pass an ordered items array; each crumb can be a link, a button, plain current-page text or custom content, and can open a dropdown menu. Optional Home and Back buttons and right-aligned actions complete the header row.
Import#
import { Breadcrumbs, BreadcrumbCrumb, pathToBreadcrumbItems, humanizeSegment } from "@reactberry/system/blocks";
import type { BreadcrumbItem, BreadcrumbsProps } from "@reactberry/system/blocks";
Usage#
import { Breadcrumbs } from "@reactberry/system/blocks";
import { Button } from "@reactberry/system/elements";
export default function ProjectHeader() {
return (
<Breadcrumbs
showHome
items={[
{ label: "Projects", href: "/projects" },
{ label: "Website", current: true },
]}
actions={
<Button as="button" type="button" variant="ghost" $size="small">
Share
</Button>
}
/>
);
}
Examples#
Sibling menu#
Give a crumb a menu to add a chevron that opens a popover. A function receives close, so the menu can dismiss itself after a selection.
From a pathname#
pathToBreadcrumbItems turns a pathname into crumbs with cumulative hrefs and humanized labels. Use labels to replace ids with names.
Back button, icons and truncation#
showBack adds a Back button that calls onBack (here a counter) instead of router.back(). Crumbs accept an icon, an onClick when there is no href, and a maxWidth for long labels.
API#
Breadcrumbs#
| Prop | Type | Default | Description |
|---|---|---|---|
items* | BreadcrumbItem[] | — | Ordered crumbs, root first. |
separator | ReactNode | — | Node rendered between crumbs. Defaults to a right chevron. |
showHome | boolean | false | Show a leading Home button linking to |
homeHref | string | / | Home destination. Default "/". |
showBack | boolean | false | Show a leading Back button. |
onBack | (() => void) | — | Back handler. Defaults to |
actions | ReactNode | — | Right-aligned actions (e.g. favourite / overflow menu). |
dataTest | string | breadcrumbs | Prefix for |
Remaining props are spread onto the root Group (rendered as a nav), so layout and style props such as flex, px and minWidth work.
BreadcrumbItem#
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | — | Stable identity used as the React key. Falls back to |
label | string | — | Text label, truncated to one line. |
href | string | — | Renders the crumb as a Next.js |
onClick | () => void | — | Renders the crumb as a |
icon | ReactNode | — | Leading visual rendered before the label. |
render | ReactNode | — | Custom content that replaces the icon and label. The link, button or current wrapper still applies. |
menu | ReactNode | ((props: { close: () => void }) => ReactNode) | — | Popover content opened from a chevron next to the crumb. |
current | boolean | — | Marks the current page: no link or button, primary colour and |
maxWidth | string | "12rem" | Maximum width of the icon and label before truncation. |
dataTest | string | — | Suffix for the crumb's |
BreadcrumbCrumb#
Renders a single crumb. Breadcrumbs uses it for every item; use it directly to build a custom trail.
| Prop | Type | Default | Description |
|---|---|---|---|
item* | BreadcrumbItem | — | The crumb to render. |
dataTest | string | "breadcrumbs" | Prefix for the |
pathToBreadcrumbItems#
Builds BreadcrumbItem[] from a pathname. Each segment becomes a crumb whose href is the path up to that segment.
| Prop | Type | Default | Description |
|---|---|---|---|
pathname* | string | — | Pathname such as |
options.labels | Record<string, string> | {} | Label overrides keyed by the raw segment ( |
options.exclude | (segment: string, index: number) => boolean | — | Return |
options.markLastCurrent | boolean | true | Marks the last crumb as |
Returns BreadcrumbItem[].
humanizeSegment#
humanizeSegment(segment: string): string decodes a URL segment, replaces - and _ with spaces and capitalizes each word: "project-templates" becomes "Project Templates".
Accessibility#
- The root is a
navwitharia-label="Breadcrumb". - The current crumb has
aria-current="page"and is not interactive. - Crumbs with
hrefrender a Next.jsLink; crumbs with onlyonClickrender a nativebutton type="button". - The Home and Back buttons have
aria-label="Home"andaria-label="Go back". - The default separator icon is
aria-hidden. - The menu chevron is a Headless UI popover button with no accessible name. Crumbs are not wrapped in a list (
ol/li).
Notes#
BreadcrumbscallsuseRouterfromnext/navigation, so it must render inside the Next.js App Router.- The Home button counts as the root crumb, so a separator follows it. The Back button has no separator.
hreftakes precedence overonClick. Acurrentcrumb ignores both.- The menu opens with
placement="bottom start". data-testhooks are<dataTest>-back,<dataTest>-home,<dataTest>-<crumb>and<dataTest>-<crumb>-menu, where<crumb>is the item'sdataTestor slugified label.slugifyis exported from the Breadcrumbs module but not from@reactberry/system/blocks.