Breadcrumbs
The trail from the top of a hierarchy down to the current page, every level above it one click away.
144 lines · TypeScript
- The last item is the page you are on: plain text, marked as the current page for screen readers.
- In the file header, click … to bring back the folders it hides.
- Out of room on its line, the full trail below wraps between items.
Field marks
- Import
import { Breadcrumbs, BreadcrumbItem } from "cennge-ui";- Size
- 1.1 KB gzip for this import, its dependencies aside
- Pattern
- WAI-ARIA breadcrumb: a named
<nav>around an ordered list,aria-current="page"on the last item - Keyboard
- Tab Enter
- State
- None to hold: the collapsed middle opens on a click and stays open
- SSR
- Rendered on the server in the Next.js check; hydrates without a warning
- Separators
- Hidden from screen readers; a chevron unless you pass your own
- Tests
- Unit tests
When to use#
Breadcrumbs show where a page sits in a hierarchy, a file in a repository or a page in a documentation site, and make each level above it one click away. They sit at the top of the page, under the main navigation, and they do not replace it: they only lead upwards.
Similar#
- Pagination moves along a sequence of pages at the same level; Breadcrumbs move up the hierarchy.
- Stepper shows how far a task has gone and what is left; Breadcrumbs show where the reader is, not what comes next.
Collapse a long trail#
With maxItems, a longer trail shows only that many items: itemsBeforeCollapse from the start (one unless you say otherwise), the rest from the end, and a … button between them. A click on it shows the whole trail.
import { BreadcrumbItem, Breadcrumbs } from "cennge-ui";
const tree = "https://github.com/Cennge/cennge-ui/tree/main";
export default function CollapsedTrail() {
return (
<Breadcrumbs maxItems={4} itemsBeforeCollapse={2} aria-label="Source file">
<BreadcrumbItem href="https://github.com/Cennge">Cennge</BreadcrumbItem>
<BreadcrumbItem href="https://github.com/Cennge/cennge-ui">cennge-ui</BreadcrumbItem>
<BreadcrumbItem href={`${tree}/src`}>src</BreadcrumbItem>
<BreadcrumbItem href={`${tree}/src/components`}>components</BreadcrumbItem>
<BreadcrumbItem href={`${tree}/src/components/navigation-menu`}>navigation-menu</BreadcrumbItem>
<BreadcrumbItem>navigation-menu.tsx</BreadcrumbItem>
</Breadcrumbs>
);
}Next.js links#
With asChild a BreadcrumbItem gives its look to your own link, here Next.js Link. startContent is not drawn in that case: put an icon inside the link, as the home icon here.
import Link from "next/link";
import { BreadcrumbItem, Breadcrumbs } from "cennge-ui";
function HomeIcon() {
return (
<svg viewBox="0 0 24 24" className="size-4" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden="true">
<path d="M4 10.5 12 4l8 6.5V20h-5.5v-5.5h-5V20H4v-9.5Z" strokeLinejoin="round" />
</svg>
);
}
export default function DocsTrail() {
return (
<Breadcrumbs>
<BreadcrumbItem asChild>
<Link href="/">
<HomeIcon />
cennge-ui
</Link>
</BreadcrumbItem>
<BreadcrumbItem asChild>
<Link href="/docs/">Docs</Link>
</BreadcrumbItem>
<BreadcrumbItem>Breadcrumbs</BreadcrumbItem>
</Breadcrumbs>
);
}Separators and sizes#
separator takes any node, a slash here, in place of the chevron. size sets the text: sm, md or lg.
import { BreadcrumbItem, Breadcrumbs } from "cennge-ui";
export default function TrailSizes() {
return (
<div className="flex flex-col gap-4">
<Breadcrumbs size="sm" separator="/" aria-label="Breadcrumb, small">
<BreadcrumbItem href="https://github.com/Cennge">Cennge</BreadcrumbItem>
<BreadcrumbItem href="https://github.com/Cennge/ai-niche-scout">ai-niche-scout</BreadcrumbItem>
<BreadcrumbItem>Settings</BreadcrumbItem>
</Breadcrumbs>
<Breadcrumbs size="lg" aria-label="Breadcrumb, large">
<BreadcrumbItem href="https://github.com/Cennge">Cennge</BreadcrumbItem>
<BreadcrumbItem href="https://github.com/Cennge/spredo-crypto-screener">spredo-crypto-screener</BreadcrumbItem>
<BreadcrumbItem>Releases</BreadcrumbItem>
</Breadcrumbs>
</div>
);
}Accessibility#
The trail is a <nav> named "Breadcrumb", and the items are an ordered list, so screen readers say how many levels there are. Rename it with aria-label when a page has more than one trail or speaks another language. The last item becomes the current page unless you set its isCurrent yourself; isCurrent={false} keeps it a link. The … button is named "Show all breadcrumbs".
Props#
Breadcrumbs#
BreadcrumbItem#
Also takes every attribute of <a>.