Breadcrumb
PolymorphicA trail of links showing the current page's place in a hierarchy, with an auto-muted current crumb and router-link support.
Breadcrumb renders a trail of links showing the current page's place in a hierarchy — home → … → current page. It's a pure Server Component — no state, no "use client".
import { Breadcrumb } from "@42-central/ui-react/breadcrumb";
<Breadcrumb
withHome={{ href: "/" }}
data={[
{ label: "Repo", href: "/repo" },
{ label: "File" },
]}
/>;Basic
The data form is the quickest way to use it — pass an array of crumbs. The last entry defaults to the current, non-interactive crumb unless another entry explicitly sets current; separators between crumbs are generated automatically, never placed by hand.
Code
<Breadcrumb
withHome={{ href: '/' }}
data={[
{ label: 'ui-react', href: '/ui-react' },
{ label: 'components', href: '/ui-react/components' },
{ label: 'breadcrumb.tsx' },
]}
/>The last crumb renders muted and non-interactive (aria-current="page") — it isn't a link, so it's deliberately de-emphasized rather than made the visually strongest item. That's the inverse of some breadcrumb conventions; it's what this component's source design calls for.
Compound form
Drop to Breadcrumb.Root + Breadcrumb.Home/Breadcrumb.Item for full control over composition — same rendering as the data form, hand-written instead of generated.
Code
<Breadcrumb.Root>
<Breadcrumb.Home href="/" />
<Breadcrumb.Item href="/repo">Repo</Breadcrumb.Item>
<Breadcrumb.Item current>File</Breadcrumb.Item>
</Breadcrumb.Root>Truncation
The trail always fits its container, and it takes no JavaScript to do it: when space runs out, link crumbs ellipsize first — all the way down to a bare "…" — and the current crumb only starts shrinking once they can't give up any more. The home icon and separators never shrink. Hover or keyboard-focus a crumb to open it back up to its full label. Drag the corner of the box below to try it.
Code
<div className="w-[420px] max-w-full resize-x overflow-hidden p-1">
<Breadcrumb
withHome={{ href: '/' }}
data={[
{ label: 'packages', href: '/packages' },
{ label: 'react', href: '/packages/react' },
{ label: 'components', href: '/packages/react/components' },
{ label: 'breadcrumb.test.tsx' },
]}
/>
</div>The full label stays in the DOM, so screen readers always announce it. Inside a flex row (a header next to other controls), the breadcrumb's <nav> already carries min-w-0, so it shrinks with the row instead of pushing it wider.
Router links
Pass linkComponent to route every generated crumb through your framework's own Link instead of a plain <a>, so navigation stays client-side. It works on Breadcrumb/Breadcrumb.Root (the default for every crumb) or per-item (overrides just one):
import Link from "next/link";
import { Breadcrumb } from "@42-central/ui-react/breadcrumb";
<Breadcrumb
linkComponent={Link}
data={[{ label: "Repo", href: "/repo" }, { label: "File" }]}
/>;Routers whose Link takes to instead of href (React Router) need a two-line local wrapper renaming the prop before passing it as linkComponent:
import { Link as RouterLink } from "react-router";
const Link = ({ href, ...props }: { href?: string }) => (
<RouterLink to={href ?? "#"} {...props} />
);For one-off composition, asChild (inherited from Ark) still works on any single Breadcrumb.Item/Breadcrumb.Home, and wins over linkComponent:
<Breadcrumb.Item asChild>
<Link href="/repo">Repo</Link>
</Breadcrumb.Item>Breadcrumb.Home puts its house icon inside an asChild link that has no children of its own, so a bare router link is enough:
<Breadcrumb.Home asChild>
<Link href="/" />
</Breadcrumb.Home>Back button
Every one of this component's source designs pairs it with a leading "back" icon-button — but that's a router/history action this kit has no opinion on, so it isn't part of Breadcrumb. Compose one next to it with ActionIcon:
Code
<div className="flex items-center gap-1">
<ActionIcon variant="subtle" size="sm" radius="xs" aria-label="Back">
<ChevronLeft aria-hidden />
</ActionIcon>
<Breadcrumb withHome={{ href: '/' }} data={[{ label: 'File' }]} />
</div>Subcomponents
Prop
Type
Every part renders testId as data-testid on its own DOM node — see Testing.
API
Breadcrumb
Prop
Type
Breadcrumb.Root takes the same props except data/withHome — compose Breadcrumb.Home/Breadcrumb.Item as its children instead.
Breadcrumb.Item
Prop
Type
Breadcrumb.Home
Prop
Type
Accessibility
- Renders
<nav aria-label="Breadcrumb">(override viaaria-label) wrapping an<ol>. - The current/last crumb gets
aria-current="page"and isn't focusable or a link. - Separators are decorative —
aria-hidden, never announced. Breadcrumb.Homedefaults its accessible name to"Home"viaaria-label.
Changelog
Schedule
Mantine-Scheduler-style agenda component — Days/Month/Year/Agenda views over user-defined and static events, with a configurable Days window, click-drag-to-create, drag-to-move, edge-resize, a now-cursor, and configurable overlap prevention.
NavLink
A self-nesting sidebar/nav row — leading startSlot, label, trailing endSlot, current-page state, and expand/collapse for arbitrary-depth children.